鴨川η

ユニグラム言語モデルと最尤推定

トピックモデル本のユニグラムモデルの最尤推定のコード. 最尤推定なので,の計算はすぐにできる.

import sys
from collections import Counter

fname = sys.argv[1]

docs = []
w_freq = Counter()

with open(fname) as f:
    for l in f:
        doc = l.strip().split()
        docs.append(doc)
        for w in doc:
            w_freq[w] += 1

total_freq = sum(w_freq.values())
phi = {}

# 最尤推定
for w in set([word for doc in docs for word in doc]):
    phi[w] = w_freq[w]/total_freq

print(sum(phi.values()))  #  1.0

generate = 1.0
for k, v in w_freq.items():
    print(k, v, phi[k])
    generate *= pow(phi[k], v)

print("docs pro: ", generate)

例えば以下の2つの文書(1行が1文書に相当)からなる文書集合があったとする.

はじめまして ★ 城ヶ崎 美 嘉 だ よー 。 アイドル だろ う と 何 だろ う と 、 どうせ やる なら オンリー ワン より ナンバーワン に なり たい ! って こと で 、 一緒 に トップ アイドル 、 目指そ う ね !
シッカリ 働け 。 ボーナス が 大きい ぞ

上記のコードを実行すると以下のようになる. 1行目の1.0はカテゴリカル分布の制約(確率分布なので総和が1.0)を満たしていることの確認. 2行目以降は各単語とその頻度,その単語の確率値を出力してる. 当然だけど,頻度が高いほど高くなる. 最後のはこの文書群の生成確率を計算している.

1.0
う 3 0.0625
ボーナス 1 0.020833333333333332
嘉 1 0.020833333333333332
どうせ 1 0.020833333333333332
美 1 0.020833333333333332
働け 1 0.020833333333333332
って 1 0.020833333333333332
こと 1 0.020833333333333332
シッカリ 1 0.020833333333333332
一緒 1 0.020833333333333332
★ 1 0.020833333333333332
だ 1 0.020833333333333332
、 3 0.0625
オンリー 1 0.020833333333333332
ぞ 1 0.020833333333333332
が 1 0.020833333333333332
で 1 0.020833333333333332
大きい 1 0.020833333333333332
ワン 1 0.020833333333333332
たい 1 0.020833333333333332
なら 1 0.020833333333333332
だろ 2 0.041666666666666664
に 2 0.041666666666666664
。 2 0.041666666666666664
何 1 0.020833333333333332
なり 1 0.020833333333333332
と 2 0.041666666666666664
よー 1 0.020833333333333332
より 1 0.020833333333333332
ナンバーワン 1 0.020833333333333332
城ヶ崎 1 0.020833333333333332
トップ 1 0.020833333333333332
目指そ 1 0.020833333333333332
やる 1 0.020833333333333332
アイドル 2 0.041666666666666664
! 2 0.041666666666666664
ね 1 0.020833333333333332
はじめまして 1 0.020833333333333332
docs pro:  5.963594180307814e-75