Pull to refresh

Comments 5

я для подобной задачи использовал библиотеку nltk:

import nltk

string_to_analyze = 'some long text string'
nltk_tokens = nltk.word_tokenize(string_to_analyze)

bigrams = list(nltk.bigrams(nltk_tokens))
trigrams = list(nltk.trigrams(nltk_tokens))

в ней так же есть набор стоп-слов (+слов-паразитов) для большинства языков:

nltk.download('stopwords')
from nltk.corpus import stopwords

Сам файлик со словами лежит где-то в документах и его можно редактировать по необходимости)

Да, удобный вариант, но хотелось сделать максимально прозрачно и просто. Плюс не всегда в рамках закрытого контура можно юзать сторонние библиотеки.

Вообще, это стандартная задача NLP, и должна решаться в 5-10 строк. Проверим:

Чтобы перебрать все биграммы, нужно просто написать

for a, b in zip(words, words[1:]):
    p = a + '_' + b

Аналогично, если хотите все биграммы с пропуском в одно слово, то

for a, b in zip(words, words[2:]):
    p = a + '^' + b

А дальше используем Counter из стандартной библиотеки

from collections import Counter
import re
c = Counter()
words = re.findall('\w+', text.lower())
for a, b in zip(words, words[1:]):
    c[a+' '+b] += 1
for a, b in zip(words, words[2:]):
    c[a+' ... '+b] += 1
import pprint
pprint.pprint(c.most_common(20)) # выведем красиво

Эх, немного не уложился в 5 строк, но в 10 строк уложился ;)

А вообще, есть такое понятие Wiki: PMI , которое гораздо лучше выделит подобные выражения. Просто нужно будет посчитать ещё униграммы и сделать рескоринг для биграмм.

Юрий, отличное, лаконичное решение, буду иметь ввиду что сахар полезен для здоровья кода. Также спасибо за ссылку про PMI, вспомнилась песня «Все решено» Гостей из Будущего.

PMI увы тоже работает не идеально, потому что в идеале для выделения фраз нужно считать статистику с учётом синонимов.
Поэтому скомбинировать и будут неплохие рекомендации.

Sign up to leave a comment.

Articles