我有一个很大的 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,并且您正在处理纯英文文本),只需将它们存储在一个大数组中,直接查找——但在这种情况下,无论如何,您可能可以将整个内容放入内存中。
关于python - 在 Python 中计算 n-gram 的逐点互信息 (PMI) 分数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5231627/