Word Mover's Distance(6)fastWMDの実行環境を整える

Word Mover's Distance (6) Prepare the execution environment for fastWMD


2021/06/03
藤田昭人


本稿では、 前回 紹介したwikiPageSelectorを使って、fastWMDの入力となる 3種のデータファイルを生成するスクリプト wiki-xml-to-txt.py の動作を確認したいと思います。

タイトルを「fastWMD の実行環境を整える」としましたが、 fastWMD ではWMDおよびその派生アルゴリズムの エラー率と実行時間に着目しているため、 Word Mover's Distance に本来必要な 文字列処理(トークン化やストップワードの除去など)を 評価プログラムの外に追い出しています。 なので、fastWMD のコードをベースに Word Mover's Distance のAPIを実装するとなると、 付属スクリプトの処理内容も理解しておく必要があります。


Wikipedia のダンプファイルからデータを抽出する

まずは 前回 と同様に wikiPageSelector を使って Wikipedia のダンプファイルからデータを抽出します。 前々回 紹介した トリプレット・データ を使って必要なページデータを選択できます。

ここでは wikipedia-hand-triplets-release.txt を使う 次のスクリプトを書きました。

$ cat ../run

../wikiPageSelector/wikiPageSelector \
../triplets-data/wikipedia-hand-triplets-release.txt \
~/Wikipedia/enwiki-20210420-pages-articles-multistream.xml > wikipedia-triplets-dump-20210420.xml
$ time ../run
real    111m21.582s
user    110m12.387s
sys 1m3.588s
$ 

手作業で作成されたはずの wikipedia-hand-triplets-release.txt は定義されている URL は比較的少数なのですが、 スクリプトが実行を終えるのに2時間弱かかりました。


スクリプトの実行

次に付属スクリプトwiki-xml-to-txt.py を実行しますが、 その前にちょこっと準備が必要です。

スクリプトを修正する

まず、スクリプトの入力となる3つのデータファイルの定義を修正します。 修正箇所は次のとおりです。

$ diff -u ../wiki-xml-to-txt.py.orig ../wiki-xml-to-txt.py
--- ../wiki-xml-to-txt.py.orig  2021-06-01 00:09:11.000000000 +0900
+++ ../wiki-xml-to-txt.py   2021-06-01 00:22:53.000000000 +0900
@@ -8,7 +8,7 @@
 import xmltodict

 filepaths = [
-   'hand/wikipedia-triplets-dump-20190918203353.xml'
+   'wikipedia-triplets-dump-20210420.xml'
 ]


@@ -66,7 +66,7 @@
 embeddings_batch = []
 embeddings = []
 old_tid2new_tid = dict()
-word_embeddings_path = "<PATH-TO-EMBEDDINGS>/GoogleNews-vectors-negative300.bin"
+word_embeddings_path = "GoogleNews-vectors-negative300.bin"

 # REFERENCE TO READ WORD2VEC BINARY FILE: https://gist.github.com/ottokart/4031dfb471ad5c11d97ad72cbc01b934
 FLOAT_SIZE = 4
@@ -117,7 +117,7 @@
        fp.write("%s %d\n" % (token, idx))

 # DUMP TRIPLETS IN INDEX FORMAT
-with open("hand/wikipedia-triplets-release.txt") as fp, open("wikipedia-triplets.txt", mode='w') as fp_out:
+with open("../triplets-data/wikipedia-hand-triplets-release.txt") as fp, open("wikipedia-triplets.txt", mode='w') as fp_out:
    for line in fp:
        if not line.strip() or line.startswith('#'):
            continue
$ 
実行に必要な Python パッケージをインストールする

次に wiki-xml-to-txt.py が使用している Python パッケージの nltk, numpy, xmltodict をインストールします。

$ pip install nltk
$ pip install numpy
$ pip install xmltodict
$ 

Python パッケージのインストール方法については 他の文献を参考にしてください。

スクリプトを実行する

スクリプトが正常に実行されると 次のように表示されます。

$ python ../wiki-xml-to-txt.py
FILE:  wikipedia-triplets-dump-20210420.xml
NUMBER OF URLS: 448
NUMBER OF TEXTS: 448
NUMBER OF TOKENS (RAW): 217549
NUMBER OF TOKENS (EMBEDDINGS): 128391
NUMBER OF TOKENS (EMBEDDINGS): 128391
NUMBER OF PAPERS: 448
$ ls
GoogleNews-vectors-negative300.bin
wikipedia-embeddings.txt
wikipedia-papers.txt
wikipedia-tokens.txt
wikipedia-triplets-dump-20210420.xml
wikipedia-triplets.txt
$ 

これでwikipedia-hand-triplets-release.txtに対応する データセットが生成できました*1


まとめ

以上、本稿では fastWMD を実行する環境を追ってきました。

文書間距離計算のエラー率と実行速度に注目する fastWMD 論文 の性質上、ベンチマークの核となる fast_wmd コマンドには 文書間距離計算のみが実装されているように見えますが、 Word Mover's Distance アルゴリズムは本来 比較する2つの文書(文字列)を引数に取り 文書間距離を返す関数として実装されるべきです。 fastWMD の実装において文書そのものを取り扱う処理は 付属するスクリプト wiki-xml-to-txt.py で実装しているように見えます。

Wikipedia ページを対象にした wiki-xml-to-txt.py の処理内容は概ね次のようです*2

  1. Wikipedia のダンプデータ(XML)からページデータを抽出しトークン化を行う
  2. トークン毎、ユニークなローカル ID を割り振る
  3. 既存の Word2Vec 学習済みデータからアクティブなトークンのベクトルのみ抽出して wikipedia-embeddings.txt に出力する
  4. アクティブなトークンの ID とトークンの対応表を wikipedia-tokens.txt に出力する
  5. トリプレット・データを読み込み URL → ID 変換を行なって wikipedia-triplets.txt に出力する
  6. Wikipedia ページデータをトークン → ID 変換を行なって、ID列を wikipedia-papers.txt に出力する


都合6回を費やし、ようやく fastWMD 論文 に伴う実装をひと通り把握することができました。 次回からは fastWMD の実装を流用して、 対話システムへの WMD の適用に挑戦したいと思います。

以上

*1:前々回 も紹介したように Dropbox からダウンロードできるのは トリプレット・データ wikipedia_2014_09_27_examples.txt から生成したデータセットのみです。

*2:次のページでは 一般的な自然言語処理における前処理について解説してます。

qiita.com

ご参考まで。