mk-toolブログ

エンジニアと家のことをごちゃごちゃと書いてます

【機械学習】gensimのチュートリアルをやってみた(その2)

さて、その1の続きを書きます。

ディクショナリーへの登録を行います。
Pythonで辞書をforで作成する際「キーがー存在する場合はバリューを更新」「存在しない場合はキー:バリューを追加」したい場合は標準ライブラリのdefaultdictを使うのが良いそうです。
まずは初期化のおまじないです。

from collections import defaultdict
frequency = defaultdict(int)

現在の変数textsの中身は以下のようになっています。

[['human', 'machine', 'interface', 'lab', 'abc', 'computer', 'applications'],
 ['survey', 'user', 'opinion', 'computer', 'system', 'response', 'time'],
 ['eps', 'user', 'interface', 'management', 'system'],
 ['system', 'human', 'system', 'engineering', 'testing', 'eps'],
 ['relation', 'user', 'perceived', 'response', 'time', 'error', 'measurement'],
 ['generation', 'random', 'binary', 'unordered', 'trees'],
 ['intersection', 'graph', 'paths', 'trees'],
 ['graph', 'minors', 'iv', 'widths', 'trees', 'well', 'quasi', 'ordering'],
 ['graph', 'minors', 'survey']]

この中のそれぞれの文字の出現回数をカウントします。二次元配列なのでfor文を入れ子にします。

for text in texts:
     for token in text:
         frequency[token] += 1

この段階での配列frequencyの中身は以下のようになっています。
文字と出現回数が結びついていますね。

defaultdict(<class 'int'>, {'abc': 1, 'error': 1, 'iv': 1, 'widths': 1, 'testing': 1, 'survey': 2, 'eps': 2, 'opinion': 1, 'intersection': 1, 'time': 2, 'minors': 2, 'machine': 1, 'well': 1, 'interface': 2, 'measurement': 1, 'ordering': 1, 'management': 1, 'graph': 3, 'human': 2, 'user': 3, 'computer': 2, 'applications': 1, 'relation': 1, 'binary': 1, 'generation': 1, 'lab': 1, 'quasi': 1, 'trees': 3, 'unordered': 1, 'response': 2, 'paths': 1, 'engineering': 1, 'random': 1, 'system': 4, 'perceived': 1})

この中で出現回数が1回だけのものは除く処理を行います。

texts = [[token for token in text if frequency[token] > 1] for text in texts]

これで変数textsの中身が以下のようになりました。

[['human', 'interface', 'computer'],
 ['survey', 'user', 'computer', 'system', 'response', 'time'],
 ['eps', 'user', 'interface', 'system'],
 ['system', 'human', 'system', 'eps'],
 ['user', 'response', 'time'],
 ['trees'],
 ['graph', 'trees'],
 ['graph', 'minors', 'trees'],
 ['graph', 'minors', 'survey']]

そして、gensimの特徴語ディクショナリーを作成します。

dictionary = corpora.Dictionary(texts)
dictionary.save('/tmp/deerwester.dict')  # ディクショナリーを保存します
print(dictionary.token2id)

出力される値が以下のように配列textsのキーに対してidが割り振られています。

{'human': 1, 'user': 5, 'computer': 2, 'survey': 4, 'eps': 8, 'time': 7, 'system': 6, 'response': 3, 'interface': 0, 'minors': 11, 'trees': 9, 'graph': 10}

これらの配列をgensimのBug of Wordsで各文の特徴語をカウントして特徴ベクトルを作ります。
先ほど作成した特徴語ディクショナリーにdoc2bowメソッドにより、文の単語に一致するidと出現頻度をタプルで返してくれます。
これにより、類似したcorpusを検索することで、それっぽい言葉を取り出せるものと思う。

corpus = [dictionary.doc2bow(text) for text in texts]
corpora.MmCorpus.serialize('/tmp/deerwester.mm', corpus) #後で使えるように保存(corpusは膨大になってしまうため)
print(corpus)

出力結果は以下のようになります。

[[(0, 1), (1, 1), (2, 1)], [(2, 1), (3, 1), (4, 1), (5, 1), (6, 1), (7, 1)], [(0, 1), (5, 1), (6, 1), (8, 1)], [(1, 1), (6, 2), (8, 1)], [(3, 1), (5, 1), (7, 1)], [(9, 1)], [(9, 1), (10, 1)], [(9, 1), (10, 1), (11, 1)], [(4, 1), (10, 1), (11, 1)]]

よし、これで基本的な動かし方は分かったぞ。。。