Извлечение словосочетаний для данного слова из текстового корпуса - Python
Я пытаюсь выяснить, как извлечь словосочетания определенного слова из текста. Как в: каковы слова, которые делают статистически значимое словосочетание, например, со словом "хоббит" во всем текстовом корпусе? Я ожидаю результат, похожий на список слов (словосочетаний) или, может быть, кортежей (мое слово + его словосочетание).
Я знаю, как составлять би- и триграммы с помощью nltk, а также как выбирать только би- или триграммы, содержащие мое слово интереса. Я использую следующий код (адаптированный из этого вопроса Stackru).
import nltk
from nltk.collocations import *
corpus = nltk.Text(text) # "text" is a list of tokens
trigram_measures = nltk.collocations.TrigramAssocMeasures()
tri_finder = TrigramCollocationFinder.from_words(corpus)
# Only trigrams that appear 3+ times
tri_finder.apply_freq_filter(3)
# Only the ones containing my word
my_filter = lambda *w: 'Hobbit' not in w
tri_finder.apply_ngram_filter(my_filter)
print tri_finder.nbest(trigram_measures.likelihood_ratio, 20)
Это прекрасно работает и дает мне список триграмм (один из элементов которого - мое слово), каждая со своим значением логарифмического правдоподобия. Но я не хочу выбирать слова только из списка триграмм. Я хотел бы сделать все возможные комбинации N-граммов в окне по своему выбору (например, все слова в окне 3 слева и 3 справа от моего слова - это будет означать 7 граммов), а затем проверить, какой из эти N-грамматические слова имеют статистически значимую частоту в паре с моим словом интереса. Я хотел бы принять значение логарифмического правдоподобия для этого.
Моя идея была бы:
1) Рассчитать все комбинации N-граммов разных размеров, содержащие мое слово (необязательно используя nltk, если только он не позволяет вычислять единицы больше, чем триграммы, но я не нашел эту опцию),
2) Вычислите значение логарифмического правдоподобия для каждого из слов, составляющих мои N-граммы, и каким-то образом сравните его с частотой n-грамма, в котором они появляются (?). Здесь я немного теряюсь... Я не опытен в этом, и я не знаю, как думать об этом шаге.
У кого-нибудь есть предложения, как мне поступить? И если предположить, что я сейчас использую пул триграмм, предоставленных nltk: есть ли у кого-нибудь идеи, как поступить оттуда, чтобы получить список наиболее релевантных слов рядом с моим поисковым словом?
Спасибо
1 ответ
Интересная проблема...
В связи с 1) взглянуть на эту тему... различные хорошие решения, чтобы сделать ngrams.. в основном я
from nltk import ngrams
sentence = 'this is a foo bar sentences and i want to ngramize it'
n = 6
sixgrams = ngrams(sentence.split(), n)
for grams in sixgrams:
print (grams)
Другой способ может быть:
phrases = Phrases(doc,min_count=2)
bigram = models.phrases.Phraser(phrases)
phrases = Phrases(bigram[doc],min_count=2)
trigram = models.phrases.Phraser(phrases)
phrases = Phrases(trigram[doc],min_count=2)
Quadgram = models.phrases.Phraser(phrases)
... (you could continue infinitely)
min_count контролирует частоту каждого слова в корпусе.
Относится к 2) Как-то сложно вычислить логарифмическое правдоподобие для более чем двух переменных, так как вы должны учитывать все перестановки. посмотрите этот тезис, который парень предложил решение (страница 26 содержит хорошее объяснение).
Однако, в дополнение к функции логарифмического правдоподобия, существует метрика PMI (Pointwise Mutual Information), которая вычисляет одновременное вхождение пары слов, разделенных на их индивидуальную частоту в тексте. PMI легко понять и рассчитать, какой вы можете использовать его для каждой пары слов.