Word2Vec

Word2Vec

テキスト解析して学習して
単語の意味をベクトル表現する方法

モデルは隠れ層と出力層の2層ニューラルネットワークになっている

Word2Vec を使うことで
ある単語や文章と似通った単語や文章を解析できる


コーパスにある単語の得微量ベクトルを学習し出力する

python で Word2Vec を使うには
gensim ライブラリをインストールする

pip3 install gensim

Mecab でコーパスを作成する

Word2Vec で類似語解析するには
テキストデータから
コーパス(基礎資料)を作成する必要がある

今回は明治以降の文学者15人のデータを wiki から取得し学習

まずはライブラリインストール

import MeCab
import requests

from bs4 import BeautifulSoup

次にターゲットURL指定

domain ="https://ja.wikipedia.org/wiki/"

次に対象人物をリストで宣言

names =["森鴎外","夏目漱石","島崎藤村","与謝野晶子","坪内逍遥","石川啄木",
        "谷崎潤一郎","芥川龍之介","萩原朔太郎","川端康成","志賀直哉","中原中也",
        "太宰治","大岡昇平","三島由紀夫"]

次に Mecab を分かち書きモードでインスタンス生成
コーパス(基礎資料)をいれるリストの宣言

m=MeCab.Tagger("-Owakati")
corpus =[]

ループ処理で
URL+キーワード
で項目のHTMLを取得

for name in names:               
    with requests.get(domain + name) as response:
        soup = BeautifulSoup(response.content, "html.parser")
        p_text = soup.find_all("p")
        for p in p_text:         
            corpus.append(m.parse(p.text).strip())

最後にコーパス(基礎資料)の結果を
data.txt に出力

with open("data.txt","w") as file:                      
    file.write("\n".join(corpus))

全体ソースは

import MeCab
import requests
from bs4 import BeautifulSoup

domain="https://ja.wikipedia.org/wiki/"

names =["森鴎外","夏目漱石","島崎藤村","与謝野晶子","坪内逍遥","石川啄木",
        "谷崎潤一郎","芥川龍之介","萩原朔太郎","川端康成","志賀直哉","中原中也",
        "太宰治","大岡昇平","三島由紀夫"]

m=MeCab.Tagger("-Owakati")
corpus =[]

for name in names:
    with requests.get(domain + name) as response:
        soup = BeautifulSoup(response.content, "html.parser")
        p_text = soup.find_all("p")
        for p in p_text:
            corpus.append(m.parse(p.text).strip())

with open("data.txt","w") as file:
    file.write("\n".join(corpus))

となり
実行すると
data.txt が作成される

次に
data.txt を解析し学習モデルを生成

gensim から Word2Vec をインポート

from gensim.models import word2vec

次にファイルからコーパス(基礎資料)の読み込み

corpus = file.read().splitlines()

splitlines() を使うと改行コードをリストにするときに入れなくなる
python でファイルを read してリストにする時に、改行コードを入れない
https://qiita.com/suzuki-hoge/items/8eac60f7b68044eea6c1
を参考に

次にコーパス(基礎資料)を元に学習モデルを生成

corpus =[sentence.split() for sentence in corpus]
model = word2vec.Word2Vec(corpus,size=200,min_count=20,window=10)

次にモデルを元に似通ったキーワードをsy筒力

今回は文学と似通ったキーワードを出力

similar_words = model.wv.most_similar(positive=["文学"], topn=9)
print(*[" ".join([v ,str("{:.2f}".format(s))]) for v, s in similar_words], sep="\n")

全体ソースは

from gensim.models import word2vec

file = open("data.txt")
corpus = file.read().splitlines()

corpus =[sentence.split() for sentence in corpus]
model = word2vec.Word2Vec(corpus,size=200,min_count=20,window=10)

similar_words = model.wv.most_similar(positive=["文学"], topn=9)
print(*[" ".join([v ,str("{:.2f}".format(s))]) for v, s in similar_words], sep="\n")

結果は

物語 0.99
作 0.98
題材 0.98
代表 0.98
時代 0.97
評論 0.97
世界 0.97
描い 0.97
歌 0.96

となった

参考書籍とは違ったけど
年数が立っているので誤差範囲

print(*[" ".join([v ,str("{:.2f}".format(s))]) for v, s in similar_words], sep="\n")

がわかりにくいので調べてみた

python {:.2f}
で検索したら
{インデックス番号:書式指定}
ということで

意味は下2桁で小数点タイプということ

これは format() の使い方であるということ

Pythonの文字列フォーマット(formatメソッドの使い方)

をみることで解決

なお今回のようにコーパス(基礎資料)作成
モデル構築
類似度の集計まで一気にやらず
モデル構築時点で一度ファイルに出力すれば
計算処理時間が縮小できる

model.save("data.model")

全体ソースは

from gensim.models import word2vec

file = open("data.txt")
corpus = file.read().splitlines()

corpus =[sentence.split() for sentence in corpus]
model = word2vec.Word2Vec(corpus,size=200,min_count=20,window=10)
model.save("data.model")

similar_words = model.wv.most_similar(positive=["文学"], topn=9)
print(*[" ".join([v ,str("{:.2f}".format(s))]) for v, s in similar_words], sep="\n")

として実行すると
data.model が作成される

あとは学習済みモデルを読み込むには

model.word2vec.Word2Vec.load("data.model")

でOKらしいので

word2vecmodel_data.py
を作成し

from gensim.models import word2vec

model =word2vec.Word2Vec.load("data.model")

similar_words = model.wv.most_similar(positive=["文学"], topn=9)
print(*[" ".join([v ,str("{:.2f}".format(s))]) for v, s in similar_words], sep="\n")

で実行したら

物語 0.99
歌 0.99
古典 0.99
海 0.98
時代 0.98
近代 0.98
作 0.98
世界 0.97
歴史 0.97

と同じ結果になった

Word2Vecの学習済み日本語モデルを読み込んで使う
を参考に

参考書籍は

なお kindle Fire でみるときには
拡大しなくても見れるので
10インチがおすすめ

カバーがほしい場合には
マグネット機能で閉じたらOFFにしてくれる純正がおすすめ