matobaの学んだこと

とあるPythonエンジニアのブログ。ソフトウェア開発、執筆活動、ライフログ。

word2vec はじめの一歩

word2vecに興味があったので調べた。

この記事は、そのメモです。

そもそも、word2vecが何か、という話は、今のところよくわかってません。とりあえず、ライブラリとかサンプルソースはありそうな雰囲気なので、動かしつつ理解していく。というのが今回の趣旨です。

ざっくり調べた感じ

  • Pythonでgensimというword2vecできるライブラリがある。
  • 日本語を分ち書きに分割して、word2vecに食わせたら、いいらしい。

ということがわかりました。

分ち書き自体は、mecabでやってるパターンが多いですが、今回は、インストールがめんどくさいのでjanomeでやってみようと思います。(パフォーマンスがきつかったらmecabに変えるのを考える。)

インストールはpipでいけます。

$ pip install janome gensim

テストデータについて

日本語データとして、青空文庫を使ってる人がいました。

Python で「老人と海」を word2vec する · m0t0k1ch1st0ry

僕も初めて知りましたが、青空文庫著作権切れの本を集めたWebサイトらしいですね。

青空文庫 Aozora Bunko

いい感じです。今回はここから学習用のテキストデータを集めてくることにします。

今回は、ここにある「学問のすすめ」を使うことにします。

図書カード:学問のすすめ

あと、概ねやり方は先ほどのWebサイトの人のやり方を参考に進めます。

準備

テキストデータは、読み込みやすいようにnkfを使ってUFT-8に変換します。

$ nkf -w --overwrite gakumonno_susume.txt
$ nkf -g gakumonno_susume.txt
UTF-8

あと、作品情報がテキストファイルの先頭と末尾にあったので、今回は、手で削除しました。

分ち書き変換

こんな感じで分ち書き変換して見ました。

from janome.tokenizer import Tokenizer

t = Tokenizer()

input_path = './gakumonno_susume.txt'
output_path = './output.txt'

# ファイルを読み込む
with open(input_path, 'r') as f:
    data = f.read()

# 分ち書きで出力する。
with open(output_path, 'w') as f:
    for token in t.tokenize(data):
        f.write(token.base_form)
        f.write(' ')

word2vecで学習する

参考にした記事と同じようにword2vecで学習して、モデルファイルを吐き出します。

from gensim.models import word2vec

input_path = './output.txt'
output_path = './word2vec.model'

sentences = word2vec.LineSentence(input_path)

model = word2vec.Word2Vec(
            sentences,
            sg=1,
            size=100,
            min_count=1,
            window=10,
            hs=1,
            negative=0
        )

model.save(output_path)

できた。

結果を見る

similar.py

import argparse
from gensim.models import word2vec

model_path = "word2vec.model"

model = word2vec.Word2Vec.load(model_path)

def refer_word2vec(word):
    results = model.most_similar(positive=word, topn=10)
    for result in results:
        print(result[0], '\t', result[1])

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('word', type=str,help='調べる文字列')
    refer_word2vec(parser.parse_args().word)
(venv) $ python similar.py 学問
活用   0.7960875034332275
読書   0.7560952305793762
要は   0.7431116104125977
等しい    0.704820454120636
常に   0.6892731189727783
論弁   0.6820701956748962
学ぶ   0.6797835826873779
視察   0.6770681738853455
言葉   0.6735968589782715
緊要   0.6723955869674683
(venv) $ python similar.py 読書
場所   0.8720929622650146
活用   0.8591458201408386
幸福   0.8259488344192505
目的   0.8245638608932495
論弁   0.8156751394271851
働く   0.8014976382255554
情      0.7961012125015259
等しい    0.7914588451385498
付合い    0.7890169620513916
徳義   0.7665766477584839

とりあえず動いている様子。

なんかわかるようなわからないような感じがするので、もう少しデータを整理してやってみようかなという気持ち。