Harukaのnote

Linuxやプログラミング,写真,旅行等の記録帳

Gensimを使ったWord2vec

現在研究にてword2vecを用いた単語の類似度の取得をしています。Gensimを用いた方法が割と手軽で、速度もまずまずであったため、残しておきます。
Linuxでの実行を前提にしています。

環境

OS:Manjaro Linux(Arch系)
Python:3.5.1 もしくはAnaconda3

Gensimとは

topic modelingに特化したpythonライブラリです。 一般的に、LDAの手法を用いたテキストマイニングを行うのに使用されるらしいです。

では、早速始めたいと思います。

学習用データ作成

gensimのword2vecにはテキスト形式のファイルを用います。
今回はWikipediaのデータを用いて学習させました。
ある程度の容量があるテキストファイルであれば何でも構いません。

Wikipediaの場合

Index of /jawiki/latest/
上記のURLからjawiki-latest-pages-articles.xml.bz2もしくはjawiki-latest-pages-articles1.xmlなどをダウンロードします。
xml形式のため、テキスト形式に変換します。
後日知ったのですが、WikiExtractorを使う方が便利です。下記のコードは今よりも知識が乏しかった頃に力技でプレーンテキストに変換するために作成したものです^^;

from xml.etree import ElementTree

XMLFILE = "jawiki-latest-pages-articles2.xml"

tree = ElementTree.parse(XMLFILE)  # ファイルから読み込み
root = tree.getroot()

signs = ["[","]","*","{","}","=","|","-","<",">",":",";","'",]

for e in root.getiterator():
  if 'text' in e.tag:
    result = e.text
    for s in signs:
      try:
        result = result.replace(s,"")
      except:
        result = result
    print(result)

これはwikiの各ページのテキストタグを拾い、そこにあるテキストから記号を除いています。記号群を作りreplaceで検証しています。これの出力をリダイレクトもしくはteeコマンドで書き出しました。プログラム内で書き出しをしても良かったのですが、何度か中身から記号が正しく除去されているかを確認するために、標準出力のままにしていたような気がします。

分かち書き

word2vecが学習をやりやすいように単語の合間などに空欄を入れる作業です。
MeCabをインストールしていない場合はインストールします。
ダウンロードはMeCabのサイトから、インストールはMecabのインストールメモがわかりやすく紹介してくれています。
インストールメモのwgetでのミラーは先日リンク切れになっていたため、ダウンロードは上記のサイトから行う方がいいと思われます。
それでは、インストールできたら、分かち書きを行います。
text.txtを読み込みdata.txtとして出力します。
オプションのb 数字 はメモリの指定だったと思います。

$ mecab -b 81920 -Owakati text.txt -o data.txt

各処理はデータ量にもよりますが、時間がかかると思います。

modelの作成

それでは、gensimを用いてmodelを作成します。
まず、必要なライブラリをインストールします。

$ pip install gensim
model作成のプログラム
from gensim.models import word2vec
import logging

# 進捗表示用
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)


data = word2vec.Text8Corpus("data.txt")
model = word2vec.Word2Vec(data, size=200, min_count=20, window=15)
#size:空間サイズ min_count:単語最低登場回数 window:ウインドウ数
# 学習結果を出力する
model.save("sample(size200_mc20_w15).model")

結構時間がかかります。

単語の計算

word2vecのメインである単語の足し引きを行います。

#modelを読み込みます
model = word2vec.Word2Vec.load("sample(size200_mc20_w15).model")

#positiveに王、negativeに男
result = model.most_similar(positive=["王"], negative=["男"])
for r in result:
  print(r)

positiveのみ入力すると、上の例であれば「王」に近似するワード群が集められます。
negativeも入力すると、上の例であれば「王」から「男」が引かれたものが集められます。例えば、私が以前した時は「姫」や「女王」などだったと思います。

以下のサイトを参考にさせていただきました。
tjo.hatenablog.com
antibayesian.hateblo.jp