目次
gensim の チュートリアル 3 を日本語にしてみました。 このチュートリアルのコードサンプルは GitHub: gensim-learning で公開しています。
準備
ログイベントを表示するには次のコードを実行してください。
1 2 |
import logging logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO) |
類似度のインターフェース
先のチュートリアル “コーパスとベクトル空間” と “トピックと変換” で、 コーパスをベクトル空間モデル上で作ることがどういうことなのか、 そしてモデルを異なるベクトル空間に変換するにはどのようにすればいいのかを学びました。 そのような作業をするのは、文書間の類似性を特定したい、またはある文書とその他の文書セットとの類似性(例えばユーザクエリとインデックス付けされた文書)を判断するためです。
gensim でどのように行うかを示すため、 前回の例で使ったものと同じコーパスを使用します (もともとは、 Deerwester らの Indexing by Latent Semantic Analysis” という1990年の記事に端を発するものです) 。
1 2 3 4 5 |
>>> from gensim import corpora, models, similarities >>> dictionary = corpora.Dictionary.load('/tmp/deerwester.dict') >>> corpus = corpora.MmCorpus('/tmp/deerwester.mm') # comes from the first tutorial, "From strings to vectors" >>> print(corpus) MmCorpus(9 documents, 12 features, 28 non-zero entries) |
Deerwester の例に倣って、 まずこの小さなコーパスを用いて 2次元の LSI空間 を定義します。
1 |
>>> lsi = models.LsiModel(corpus, id2word=dictionary, num_topics=2) |
ここで、 ユーザが “Human computer interaction” と入力したと仮定します。 今ある9つのコーパス文書をこのクエリへの関連度合いの降順で並べ替えることを考えます。 現代的なサーチエンジンとは異なり、 ここではそれらのテキスト(言葉)の 明らかな意味的関連による類似性についてのみ考慮します。 ハイパーリンクや、ランダムウォークによるランク付けは用いず、 Yes/No で判定されるキーワードマッチに基づく意味的関連のみです。
1 2 3 4 5 |
>>> doc = "Human computer interaction" >>> vec_bow = dictionary.doc2bow(doc.lower().split()) >>> vec_lsi = lsi[vec_bow] # convert the query to LSI space >>> print(vec_lsi) [(0, -0.461821), (1, 0.070028)] |
加えて、 2つのベクトルの類似度に関してコサイン類似度を考えています。 コサイン類似度はベクトル空間モデルにおける標準的な類似度測定法です。 しかし、 ベクトルが確率分布を表す場合は別の類似度測定法がより適しています。
クエリ構造の初期化
類似度クエリの準備として、比較したい全ての文書を入力しておく必要があリマス。 今回の場合、LSI の学習に使い、2次元のLSA空間に変換された、9つの文書を使います。 しかしこれは偶然で、学習に用いたものとは別のコーパスで完全に索引付けしている場合も考えられます。
1 |
>>> index = similarities.MatrixSimilarity(lsi[corpus]) # transform corpus to LSI space and index it |
注意
similarities.MatrixSimilarity
クラスは全てのベクトルがメモリ内に収まる場合にのみ有効です。 例えば 100万のドキュメントはそのクラスを用いる場合、 256次元の LSI 空間のために 2GB の RAM を必要とします。
2GB の RAM がない場合、 similarities.Similarity
クラスが必要になります。 このクラスは、インデックスをディスク上の複数のファイルに分散し、固定されたメモリで処理を行います。 これをシャーディングと呼びます。 その処理は similarities.MatrixSimilarity
と similarities.SparseMatrixSimilarity
の2クラスを内部的に使用するため、 少し複雑になりますが、まだ速く処理ができます。
クエリ実行
クエリ文書の、9つのインデックス化されたドキュメントに対する類似度を計算します。
1 2 3 4 |
>>> sims = index[vec_lsi] # perform a similarity query against the corpus >>> print(list(enumerate(sims))) # print (document_number, document_similarity) 2-tuples [(0, 0.99809301), (1, 0.93748635), (2, 0.99844527), (3, 0.9865886), (4, 0.90755945), (5, -0.12416792), (6, -0.1063926), (7, -0.098794639), (8, 0.05004178)] |
コサイン類似度は -1 超 1 未満 の間で類似度を計算します。 1つめのドキュメントは、 類似度が 0.99809301 となりました。
標準的な Python の手法でこれらの類似度を降順にします。 そしてクエリ “Human computer interaction” の最終的な答えを得ます。
1 2 3 4 5 6 7 8 9 10 11 |
>>> sims = sorted(enumerate(sims), key=lambda item: -item[1]) >>> print(sims) # print sorted (document number, similarity score) 2-tuples [(2, 0.99844527), # The EPS user interface management system (0, 0.99809301), # Human machine interface for lab abc computer applications (3, 0.9865886), # System and human system engineering testing of EPS (1, 0.93748635), # A survey of user opinion of computer system response time (4, 0.90755945), # Relation of user perceived response time to error measurement (8, 0.050041795), # Graph minors A survey (7, -0.098794639), # Graph minors IV Widths of trees and well quasi ordering (6, -0.1063926), # The intersection graph of paths in trees (5, -0.12416792)] # The generation of random binary unordered trees |
(わかりやすくするために、コメントで文書文字列を追記しています。)
注目するべきは、 2番目の文書 (“The EPS user interface management system”) と 4番目の文書 (“Relation of user perceived response time to error measurement”) が、 標準的なブーリアンの全文検索の結果になっていないことです。 それらは “Human computer interaction” という文書とは共通の単語がありません。 しかしながら、 LSI を適用すると、 それらの極めて高い類似度を得ます(2番目の文書は実際のところ一番類似度が高いです)。 そしてその事実は “computer-human” 関連のトピックをクエリ文書と共有するという我々の直感によく適合しています。 実際のところ、 このように意味を一般化して扱えるようにすることが、 我々が最初に変換を施してトピックモデリングを行う理由です。
次は?
おめでとう、 あなたはチュートリアルを終えました。 あなたはもう gensim がどのように機能するか知っています。 より詳細に理解するためには。 APIドキュメント を見たり、 ウィキペディアの実験や gensim の分散処理についてチェックするのがいいでしょう。
Gensim はよく成熟したパッケージで、 多くの個人や企業に、 ラピッドプロトタイピングおよびプロダクトの両方で上手く使われています。 それは完璧だという意味ではありませんが。
- より効率的に(例えばC言語で)実装可能なパートがありますし、 並列処理(複数のマシンコアによる)をより効果的に使うことができるパートもあります。
- 新しいアルゴリズムは常に公開されています。 議論したりコードをコントリビュートすることで gensim が新しいアルゴリズムを取り入れていけるよう手助消してください。
- フィードバックは大歓迎です(コードだけではありません)。 アイディアの提供、バグレポート、単純にユーザストーリーを考えること、そして一般的な質問があります。
Gensim は NLP (ひいては機械学習) のサブフィールドにおいて 包括的なフレームワークになるという野心を持っていません。 Gensim のミッションは NLP実践者が大規模なデータセットにおいて人気のあるトピックモデリングアルゴリズムを簡単に試して、 研究者が新しいアルゴリズムのプロトタイプ開発を簡単にできるようにすることです。