如何在Python的nltk中获取n元搭配和联想?

7
这份文档中,有一个使用nltk.collocations.BigramAssocMeasures()BigramCollocationFindernltk.collocations.TrigramAssocMeasures()TrigramCollocationFinder的示例。
其中有一个示例方法是基于pmi查找bigram和trigram的nbest。 例如:
finder = BigramCollocationFinder.from_words(
...     nltk.corpus.genesis.words('english-web.txt'))
>>> finder.nbest(bigram_measures.pmi, 10)

我知道BigramCollocationFinderTrigramCollocationFinder都是从AbstractCollocationFinder继承而来的。而BigramAssocMeasures()TrigramAssocMeasures()则是从NgramAssocMeasures继承而来的。
如果我想使用AbstractCollocationFinderNgramAssocMeasures中的方法(例如nbest()),以便处理4-gram、5-gram、6-gram等n-gram数据(和容易处理bigram和trigram一样),应该怎么做呢?
我需要创建一个继承AbstractCollocationFinder的类吗?
谢谢。
2个回答

10
如果您想查找2或3克拉以上的克拉数,可以使用Scikit包和Freqdist函数来获取这些克拉数的计数。我尝试使用nltk.collocations来实现这一点,但我认为我们无法找到超过3-grams分数。所以我决定使用克拉数的计数。希望这可以对您有所帮助。谢谢。 这是代码:
from sklearn.metrics.pairwise import cosine_similarity
from sklearn.feature_extraction.text import CountVectorizer
from nltk.collocations import *
from nltk.probability import FreqDist
import nltk

query = "This document gives a very short introduction to machine learning problems"
vect = CountVectorizer(ngram_range=(1,4))
analyzer = vect.build_analyzer()
listNgramQuery = analyzer(query)
listNgramQuery.reverse()
print "listNgramQuery=", listNgramQuery
NgramQueryWeights = nltk.FreqDist(listNgramQuery)
print "\nNgramQueryWeights=", NgramQueryWeights

这将给出输出

listNgramQuery= [u'to machine learning problems', u'introduction to machine learning', u'short introduction to machine', u'very short introduction to', u'gives very short introduction', u'document gives very short', u'this document gives very', u'machine learning problems', u'to machine learning', u'introduction to machine', u'short introduction to', u'very short introduction', u'gives very short', u'document gives very', u'this document gives', u'learning problems', u'machine learning', u'to machine', u'introduction to', u'short introduction', u'very short', u'gives very', u'document gives', u'this document', u'problems', u'learning', u'machine', u'to', u'introduction', u'short', u'very', u'gives', u'document', u'this']

NgramQueryWeights= <FreqDist: u'document': 1, u'document gives': 1, u'document gives very': 1, u'document gives very short': 1, u'gives': 1, u'gives very': 1, u'gives very short': 1, u'gives very short introduction': 1, u'introduction': 1, u'introduction to': 1, ...>

6

编辑

目前的NLTK有一个硬编码函数,最多可以处理QuadCollocationFinder,但为什么不能简单地创建一个NgramCollocationFinder的原因仍然存在,您需要彻底改变from_words()函数中不同ngram顺序的公式。


简短回答,如果你想要寻找超过2-gram和3-gram的搭配,你不能简单地创建一个AbstractCollocationFinder(ACF)来调用nbest()函数。这是因为不同ngrams的from_words()有所不同。只有ACF的子类(即BigramCF和TrigramCF)才有from_words()函数。
>>> finder = BigramCollocationFinder.from_words(nltk.corpus.genesis.words('english-web.txt'))
>>> finder = AbstractCollocationFinder.from_words(nltk.corpus.genesis.words('english-web.txt',5))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'AbstractCollocationFinder' has no attribute 'from_words'

因此,在TrigramCF中给定这个from_words()

from nltk.probability import FreqDist
@classmethod
def from_words(cls, words):
    wfd, wildfd, bfd, tfd = (FreqDist(),)*4

    for w1,w2,w3 in ingrams(words,3,pad_right=True):
      wfd.inc(w1)

      if w2 is None:
        continue
      bfd.inc((w1,w2))

      if w3 is None:
        continue
      wildfd.inc((w1,w3))
      tfd.inc((w1,w2,w3))

    return cls(wfd, bfd, wildfd, tfd)

你可以通过某种方式进行黑客攻击,并尝试硬编码一个4元组关联查找器,如下所示:

@classmethod
def from_words(cls, words):
    wfd, wildfd = (FreqDist(),)*2
    bfd, tfd ,fofd = (FreqDist(),)*3

    for w1,w2,w3,w4,w5 in ingrams(words,5,pad_right=True):
      wfd.inc(w1)

      if w2 is None:
        continue
      bfd.inc((w1,w2))

      if w3 is None:
        continue
      wildfd.inc((w1,w3))
      tfd.inc((w1,w2,w3))

      if w4 is None:
        continue
      wildfd.inc((w1,w4))
      wildfd.inc((w2,w4))
      wildfd.inc((w3,w4))
      wildfd.inc((w1,w3))
      wildfd.inc((w2,w3))
      wildfd.inc((w1,w2))
      ffd.inc((w1,w2,w3,w4))

    return cls(wfd, bfd, wildfd, tfd, ffd)

然后你还需要更改代码的哪部分使用从`from_words`返回的`cls`。因此,您必须询问查找搭配的最终目的是什么?
  • 如果您正在检索大于2或3克拉窗口中的搭配词,则基本上会有很多噪音。

  • 如果您要构建基于2或3克拉窗口使用搭配模式的模型,则还将面临稀疏性问题。


感谢 @2er0 是的,我想在大于3-gram的搭配中计算pmi n-gram模型。 - Fahmi Rizal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接