Создавайте униграммы и биграммы из списка триграмм

Я ищу возможные способы просто сохранить частоты триграмм в памяти и вычислить частоты униграмм и биграмм на лету следующим образом:

Дана триграмма u, v, w:

count (v, w) = sum (., v, w) т.е. сумма по всем u

Аналогично count (w) = sum (., W)

Это обязательно приведет к отсутствию нескольких униграмм, например, маркера начала предложения, но звучит ли это как действительный подход к созданию униграмм и биграмм?


person subzero    schedule 17.11.2013    source источник


Ответы (1)


да. Это будет работать. Вы можете проверить это, сделав себе крошечный корпус и вручную посчитав, чтобы убедиться, что он получился таким же.

from collections import Counter

corpus = [['the','dog','walks'], ['the','dog','runs'], ['the','cat','runs']]
corpus_with_ends = [['<s>','<s>'] + s + ['<e>'] for s in corpus]

trigram_counts = Counter(trigram for s in corpus_with_ends for trigram in zip(s,s[1:],s[2:]))

unique_bigrams = set((b,c) for a,b,c in trigram_counts)
bigram_counts = dict((bigram,sum(count for trigram,count in trigram_counts.iteritems() if trigram[1:] == bigram)) for bigram in unique_bigrams)

unique_unigrams = set((c,) for a,b,c in trigram_counts if c != '<e>')
unigram_counts = dict((unigram,sum(count for trigram,count in trigram_counts.iteritems() if trigram[2:] == unigram)) for unigram in unique_unigrams)

Теперь вы можете проверить:

>>> true_bigrams = [bigram for s in corpus_with_ends for bigram in zip(s[1:],s[2:])]
>>> true_bigram_counts = Counter(true_bigrams)
>>> bigram_counts == true_bigram_counts
True

>>> true_unigrams = [(unigram,) for s in corpus_with_ends for unigram in s[2:-1]]
>>> true_unigram_counts = Counter(true_unigrams)
>>> unigram_counts == true_unigram_counts
True
person dhg    schedule 17.11.2013