存储ngram模型python

时间:2017-07-23 12:14:20

标签: python data-structures web-applications nlp n-gram

我将语言模型作为个人挑战实现,作为简单Web应用程序的一部分。我仍然避免使用NLTK,但是面对MemoryError有足够大的语料库(词汇量约为50000,三卦数量约为440000) - 我使用了标准的python字典,并在尝试了numpy数组后将所有word-ngram概率存储为矩阵)。因此,似乎解决方案是使用更高效的数据结构,这里提到了train a language model using Google Ngrams或在磁盘上存储模型。总的来说,您能否建议哪种方法可以更好地存储ngram模型(在内存或磁盘空间中)以及将其用作web-app的一部分后?

2 个答案:

答案 0 :(得分:1)

我将我的答案分为两部分,第一部分是为什么以字典的形式存储它是一个坏主意,第二部分是存储ngrams的最佳数据结构。

考虑将以下单词存储在字典中:" Bond"," Boat"," Build",包含这些键的字典大小散列到某些字典整数大致与单词数量+字符成正比。因此,我们在技术上花费额外的空间来存储可能重复的某些字母。现在,问题变得明显,我们在存储我们不需要重新存储的字符串部分时花费了大量额外的内存。

问题仍然存在,这里可以使用的理想数据结构是什么。此数据结构的必要条件是:

  1. 高效存储
  2. 检索值(大致恒定的时间)
  3. 如果我们考虑哪种数据结构符合这些要求,立即想到的是 Trie ,或者更确切地说是 Prefix Trie 。 Trie的固有结构很有用,因为我们会节省单个字符的空间,否则我们会存储几次。用上面例子中的一小组单词来说,问题并不是很严重。但是,随着我们的单词集的长度增加,我们将很快使用哈希表/字典耗尽空间。

    希望这有帮助。

答案 1 :(得分:1)

您不是第一个尝试使用N-gram语言模型的人,也不是最后一个。

作为另一个解决方案说明,我们可以将大型词典存储在树型结构中,以便共享前k个单词(k

Building a Vocab Tree

如果有的话,先验会以这种格式存储n-gram,因此将其修剪通常是谨慎的。也就是说,如果您将计数变量附加到模型中,我们可以删除频率较低的元素。如果您的数据混乱,则低频n-gram通常对应于拼写错误的单词或实词错误。

即使树结构的效率很高,也很难有效地扩展n> 3的n元语法,除非您有像vocab这样的小字符。对于中等高的n值(如n = 6),一种流行的解决方案是使用(修改的)Kneser-Ney平滑法。像

这样的库

https://github.com/kpu/kenlm

高效并且具有python接口。尽管对于大型语料库,仍建议在构建自己的模型以及类似Trie压缩以从ARPA模型创建二进制文件时进行修剪。这产生对数概率作为分数。我的第一个6克模型是7Gb语料库中的11Gb。我对其进行了修剪和压缩,以获得合理的400Mb模型。加载后速度非常快。通过明智地集中您的语料库,应该很容易获得适用于Web应用程序的模型。

可通过pip安装获得基于Kneser-Ney的插值的类似的纯基于python的方法。可以在这里找到自己实现模型的规范论文:

An empirical study of smoothing techniques for language modeling

对于上述方法失败的非常大的n,您可以使用语料库创建嵌入,并使用循环神经网络(如基于LSTM或GRU的网络)来输出元组的对数概率或概率本身。如果您有Keras或Pytorch的手柄,这并不难。像2层LSTM的结构一样,应引起注意。在神经网络方向上编码n-gram可能会有很多事情要做。