大抵はgensimの公式に書いてあるけど、日本語の資料はそんなに多くないので、自分がよく使う基本的なやつを初心者向けにまとめときます。
準備(インストール)
pip install gensim
学習データの形成
サイトによって書き方違うんですが、個人的にはこの書き方で落ち着いてます
#coding: UTF-8
from gensim.models.doc2vec import Doc2Vec
from gensim.models.doc2vec import TaggedDocument
f = open('学習データ.txt','r')#空白で単語を区切り、改行で文書を区切っているテキストデータ
#1文書ずつ、単語に分割してリストに入れていく[([単語1,単語2,単語3],文書id),...]こんなイメージ
#words:文書に含まれる単語のリスト(単語の重複あり)
# tags:文書の識別子(リストで指定.1つの文書に複数のタグを付与できる)
trainings = [TaggedDocument(words = data.split(),tags = [i]) for i,data in enumerate(f)]
ちなみに今回学習したのは、読書メーターのレビュー1200万件のデータです。こそこそとスクレイピングで収集しました。1GB超えてるので、メモリに乗っけるのもPCによってはなかなか大変
モデルの学習
# トレーニング(パラメータについては後日)
m = Doc2Vec(documents= trainings, dm = 1, size=300, window=8, min_count=10, workers=4)
# モデルのセーブ
m.save("model/doc2vec.model")
# モデルのロード(モデルが用意してあれば、ここからで良い)
m = Doc2Vec.load('model/doc2vec2.model')
学習データのサイズによってはかなり時間かかるので注意
よく使う機能
学習文書の中で、指定したidの文書と類似度の高い文書を調べる
#引数は文書id
print m.docvecs.most_similar(0)
#文書0と類似している上位10件の文書idと類似度のセットが返ってくる
>> [(55893, 0.6868613362312317), (85550, 0.6866280436515808), (80831, 0.6864551305770874), (61463, 0.6863148212432861), (72602, 0.6847503185272217), (56876, 0.6835699081420898), (80847, 0.6832736134529114), (92838, 0.6829516291618347), (24495, 0.6820268630981445), (45589, 0.679581880569458)]
任意の文書間の類似度を調べる
print m.docvecs.similarity(1,307)
#文書1と文書307の間の類似度
>> 0.279532733106
学習したモデルを使って、新規に与えた文書の同士の類似度を調べる
#例えば、以下の4つの新規文書の、いくつかの組み合わせの類似度を計算してみる
doc_words1 = ["ラスト", "展開" ,"早い" ,"他" ,"作品", "衝撃", "受ける" ,"裏の裏" ,"つく", "トリック" ,"毎度" ,"こと", "脱帽", "する", "読む", "やすい" ,"め" ,"ミステリー"]
doc_words2 = [ "イニシエーション・ラブ", "同様" ,"最後", "数行", "どんでん返し", "いく", "時", "時", "様々", "シーン", "する" ,"れる", "伏線" ,"散りばめる", "られる" ,"いる", "こと", "気づく"]
doc_words3 = ["ラスト", "展開" ,"早い" ,"他" ,"作品", "衝撃", "受ける" ,"裏の裏" ,"つく","ミステリー"]
doc_words4 = ["独特", "世界観", "日常" ,"離れる","落ち着く","時","読む","本"]
print "1-2 sim"
sim_value = m.docvecs.similarity_unseen_docs(m, doc_words1, doc_words2, alpha=1, min_alpha=0.0001, steps=5)
print sim_value
print "1-3 sim"
print m.docvecs.similarity_unseen_docs(m, doc_words1, doc_words3, alpha=1, min_alpha=0.0001, steps=5)
print "1-4 sim"
print m.docvecs.similarity_unseen_docs(m, doc_words1, doc_words4, alpha=1, min_alpha=0.0001, steps=5)
print "2-3 sim"
print m.docvecs.similarity_unseen_docs(m, doc_words2, doc_words3, alpha=1, min_alpha=0.0001, steps=5)
>> 1-2 sim
0.10429317017
1-3 sim
0.472984922936
1-4 sim
-0.02320307339
2-3 sim
0.228117846023
人が見ても、文書1-3とか2-3は似てるし、逆に文書1-4は似てないのは明らかなので、なかなか良い感じに類似度が出てます
新規文書の圧縮ベクトルを出力(学習するときにsizeで指定した次元数のベクトルで出力される)
newvec = m.infer_vector(doc_words1)
print newvec
>> [ 1.19107231e-01 -4.06390838e-02 -2.55129002e-02 1.16982162e-01
-1.47758834e-02 1.07912444e-01 -4.76960577e-02 -9.73785818e-02
#...(中略)
-1.61364377e-02 -9.76370368e-03 4.98018935e-02 -8.88026431e-02
1.34409174e-01 -1.01136886e-01 -4.24979888e-02 7.16169327e-02]
今後追加したいこと
- モデルを学習する際のパラメータの調整
- どんなことに応用できるか
あと、doc2vecのアルゴリズム自体に関して
工学院大学の北山研のブログで説明している記事を見つけました
doc2vec(Paragraph Vector) のアルゴリズム