Как получить n-грамм словосочетаний и ассоциации в Python NLTK?
В этой документации есть пример использования nltk.collocations.BigramAssocMeasures()
, BigramCollocationFinder
,nltk.collocations.TrigramAssocMeasures()
, а также TrigramCollocationFinder
,
Существует пример метода find nbest, основанный на pmi для биграма и триграммы. пример:
finder = BigramCollocationFinder.from_words(
... nltk.corpus.genesis.words('english-web.txt'))
>>> finder.nbest(bigram_measures.pmi, 10)
я знаю это BigramCollocationFinder
а также TrigramCollocationFinder
наследовать от AbstractCollocationFinder.
В то время как BigramAssocMeasures()
а также TrigramAssocMeasures()
наследовать от NgramAssocMeasures.
Как я могу использовать методы (например, nbest()
) в AbstractCollocationFinder
а также NgramAssocMeasures
для 4-грамма, 5-грамма, 6-грамма,...., n-грамма (как легко использовать биграммы и триграммы)?
Должен ли я создать класс, который наследует AbstractCollocationFinder
?
Благодарю.
2 ответа
отредактированный
Текущий NLTK имеет функцию hardcoder для до QuadCollocationFinder
но обоснование того, почему вы не можете просто создать NgramCollocationFinder
все еще стоит, вам придется радикально изменить формулы в from_words()
функция для другого порядка ngram.
Короткий ответ: нет, вы не можете просто создать AbstractCollocationFinder
(АКФ), чтобы позвонить nbest()
функция, если вы хотите найти словосочетания за 2- и 3-грамм.
Это из-за разницы в 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'
Так, учитывая это from_words()
в TrigramCF:
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)
Тогда вам также придется изменить любую часть кода, которая использует cls
вернулся из from_words
соответственно.
Итак, вы должны спросить, какова конечная цель поиска словосочетаний?
Если вы смотрите на извлечение слов в словосочетаниях с окнами, большими чем 2 или 3 грамма, то вы в значительной степени получаете много шума при поиске слов.
Если вы собираетесь построить базу моделей в режиме совместного размещения, используя окна 2 или 3 грамма, то у вас также возникнут проблемы с разреженностью.
Если вы хотите найти граммы, превышающие 2 или 3 грамма, вы можете использовать пакет scikit и функцию Freqdist, чтобы получить счетчик для этих граммов. Я пытался сделать это с помощью nltk.collocations, но я не думаю, что мы сможем найти более 3-граммовой оценки. Поэтому я скорее решил пойти с грамм. Я надеюсь, что это может немного помочь. Thankz
вот код
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, ...>