word2vecをwikipediaコーパスで学習
作業動機
今更ながら練習として映画推薦サービスを作ってみようかなと思った.
とりあえず
をいじってみようと思ってダウンロード.
内容はこんな感じ.
- genome-scores.csv: タグと映画の関連性
- genome-tags.csv: タグID
- links.csv: 別データ・セットとの映画ID対応表
- movies.csv: 映画ID・タイトル・ジャンル(複数)
- ratings.csv: ユーザの,映画に対する評価値(悪0.5~5良)と評価した時刻.
- tags.csv: ユーザが映画に対してつけたtagとその時刻.
ぱっと思い浮かんだのは,ユーザに幾つかの映画に対する評価をしてもらい,ratingから似た評価をしているユーザを取ってきて,そのユーザの評価が高い映画を薦めるという能動学習的な方法.
その方法だときっちりユーザ登録型のWebサイト運営出来てないとキツいと思うので,出来ればその他のTwitterのツイートとか見せてもらうとかしてユーザの趣向を取ってきて,推薦したい(出来なさそうだけどとりあえず).
ということで自然言語処理のノウハウが必要になってくるけど,とりあえずはWord2Vecでお茶を濁す.日本語wikipediaのデータを学習してみる.
参考にしたWebサイトは以下の通り.
作業手順
WikipediaのデータをWord2Vecで使える形式に変換
まずwikipediaのデータを取ってくる.
$ curl https://dumps.wikimedia.org/jawiki/latest/jawiki-latest-pages-articles.xml.bz2 -o jawiki-latest-pages-articles.xml.bz2
このままだとテキストデータではないので,変換する必要がある.
python環境でやっていく予定なので,WikiExtractor.pyが使える.
$ git clone https://github.com/attardi/wikiextractor $ python3 wikiextractor/WikiExtractor.py jawiki-latest-pages-articles.xml.bz2
ここまでやるとtextディレクトリが作成されており,それらの下部には各ページのテキストが保存されている.
それらを一つにまとめるために,以下の処理を行う.
$ cat text/*/* > jawiki.txt
でword2vecに読み込ませる前にWord単位のセグメンテーションを行っておく必要がある.そこで,MeCabをhomebrewで入れてそれを使う.
$ brew install mecab $ mecab -Owakati jawiki.txt -o data.txt
Word2Vecのインストールと実行
$ pip3 install gensim
でipyhtonを使って学習.
from gensim.models import word2vec data = word2vec.Text8Corpus("data.txt") model = word2vec.Word2Vec(data, size=200)
modelが学習されるのに結構時間が掛かりそうなのでとりあえず今はここまで書いておく.
出力
後日,出力の確認をしてみた.
よく知られている例で,イチロー - 野球 + 本田 → サッカーっていう挙動をするってのがあるけど,今回のWikipediaのデータセットのみではそんな出力は出なかったので一応報告.
米googleの研究者が開発したWord2Vecで自然言語処理(独自データ) - Qiita
もちろん上サイトではfacebookデータセットを独自に作ってるみたいなので,挙動が異るのは当たり前.
実際にTwitterとかから映画のレビューを取ってくるときにはそれなりのデータセットを用意する必要がある.
out = model.most_similar(positive=["イチロー", "本田"], negative=["野球"]) for x in out: print(x[0], x[1]) 天谷 0.5703838467597961 中嶋 0.5688130259513855 中澤 0.5668359398841858 赤木 0.565341055393219 青木 0.5472140908241272 梶谷 0.5470311641693115 斉藤 0.5417250990867615 佐山 0.541033923625946 石毛 0.5390052199363708 松井 0.5352978706359863
その他にもいくつか.
out = model.most_similar(positive=["女性", "王"], negative=["男"]) for x in out: print(x[0], x[1]) 王族 0.5936665534973145 国王 0.5321540832519531 王室 0.5042459964752197 君主 0.49709588289260864 スルターン 0.4776388108730316 ムスリム 0.47091352939605713 王妃 0.4708373248577118 異教徒 0.4697801470756531 アノーヤター 0.4674013555049896 諸侯 0.4593404531478882 out = model.most_similar(positive=["イスラム教", "旧約聖書"], negative=["コーラン"]) KeyError: "word '旧約聖書' not in vocabulary"
前半の例では王妃が割りと上位に来てて期待通り.
そうでなくても,"王"関連のワードが出て来るWord2Vecの性能に驚き.
自然言語処理は僕の専門分野ではないので,どの程度の性能がでるのかは知らなかったけど,思っていたよりはよかったかな.
更にデータセット増やせば結構良い結果が得られそう.
一方後半の例ではエラーが発生.
ユダヤ教とかが出てほしかったけど,まさか"旧約聖書"が無いとは...
あれかな.多分MeCabの分かち書きの分割が上手く行っていないorデータセットにそもそも含まれていないって感じだと思う.
前者の方があり得るかな.その辺も勉強しないとな.