我有大量的 n-gram 语料库和几个外部 n-gram。我想根据这个语料库(计数)计算每个外部 n-gram 的 PMI 分数。
是否有任何工具可以做到这一点,或者有人可以为我提供一段可以做到这一点的 Python 代码吗?
问题是我的 n-gram 是 2-gram、3-gram、4-gram 和 5-gram。所以计算 3 克或更多的概率真的很耗时。
如果我正确理解您的问题,您想要计算诸如 log { P("x1 x2 x3 x4 x5") / P("x1") P("x2") ... P("x5") }其中 P 测量任何给定的 5-gram 或 1-gram 是给定事物的概率(并且基本上是计数的比率,可能具有拉普拉斯式偏移量)。因此,通过您的语料库并存储(1)每个 1-gram,(2)每个 n-gram(对后者使用 dict)的计数,然后对于每个外部 n-gram,您执行一些 dict查找,一些算术,你就完成了。一开始通过语料库,然后每个外部 n-gram 的工作量固定。
(注意:实际上我不确定如何为两个以上的随机变量定义 PMI;也许它类似于 log P(a)P(b)P(c)P(abc) / P(ab)P(bc) P(a_c). 但是如果它是沿着这些线的任何东西,你可以用同样的方法来做:遍历你的语料库,计算很多东西,然后你需要的所有概率只是计数的比率,也许用拉普拉斯- ish更正。)
如果您的语料库太大以至于无法将 n-gram dict 放入内存中,则将其划分为有点内存大小的块,为每个块计算 n-gram dicts 并将它们以允许您的形式存储在磁盘上合理有效地获取任何给定的 n-gram 条目;然后,对于每个 extern n-gram,遍历块并将计数相加。
什么形式?由你决定。一个简单的选择:按照 n-gram 的字典顺序(注意:如果您使用的是单词而不是字母,您可能希望从将单词转换为数字开始;您需要对语料库进行一次初步传递这); 然后找到你想要的 n-gram 是二进制搜索或类似的东西,对于大小为 1GB 的块,这意味着每个块大约需要 15-20 次搜索;您可以添加一些额外的索引来减少这种情况。或者:使用磁盘上的哈希表,使用 Berkeley DB 或其他东西;在这种情况下,您可以放弃分块。或者,如果字母表很小(例如,这些是字母 n-gram 而不是单词 n-gram,并且您正在处理纯英文文本),只需将它们存储在一个大数组中,并直接查找 - 但在这种情况下,无论如何,您可能都可以将整个内容放入内存中。