Word2Vec
テキスト解析して学習して
単語の意味をベクトル表現する方法
モデルは隠れ層と出力層の2層ニューラルネットワークになっている
Word2Vec を使うことで
ある単語や文章と似通った単語や文章を解析できる
例
コーパスにある単語の得微量ベクトルを学習し出力する
python で Word2Vec を使うには
gensim ライブラリをインストールする
1 | pip3 install gensim |
Mecab でコーパスを作成する
Word2Vec で類似語解析するには
テキストデータから
コーパス(基礎資料)を作成する必要がある
今回は明治以降の文学者15人のデータを wiki から取得し学習
まずはライブラリインストール
1 2 3 4 | import MeCab import requests from bs4 import BeautifulSoup |
次にターゲットURL指定
1 |
次に対象人物をリストで宣言
1 2 3 | names = [ "森鴎外" , "夏目漱石" , "島崎藤村" , "与謝野晶子" , "坪内逍遥" , "石川啄木" , "谷崎潤一郎" , "芥川龍之介" , "萩原朔太郎" , "川端康成" , "志賀直哉" , "中原中也" , "太宰治" , "大岡昇平" , "三島由紀夫" ] |
次に Mecab を分かち書きモードでインスタンス生成
コーパス(基礎資料)をいれるリストの宣言
1 2 | m = MeCab.Tagger( "-Owakati" ) corpus = [] |
ループ処理で
URL+キーワード
で項目のHTMLを取得
1 2 3 4 5 6 | 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 に出力
1 2 | with open ( "data.txt" , "w" ) as file : file .write( "\n" .join(corpus)) |
全体ソースは
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | import MeCab import requests from bs4 import BeautifulSoup 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 をインポート
1 | from gensim.models import word2vec |
次にファイルからコーパス(基礎資料)の読み込み
1 | corpus = file .read().splitlines() |
splitlines() を使うと改行コードをリストにするときに入れなくなる
python でファイルを read してリストにする時に、改行コードを入れない
https://qiita.com/suzuki-hoge/items/8eac60f7b68044eea6c1
を参考に
次にコーパス(基礎資料)を元に学習モデルを生成
1 2 | corpus = [sentence.split() for sentence in corpus] model = word2vec.Word2Vec(corpus,size = 200 ,min_count = 20 ,window = 10 ) |
次にモデルを元に似通ったキーワードをsy筒力
今回は文学と似通ったキーワードを出力
1 2 | similar_words = model.wv.most_similar(positive = [ "文学" ], topn = 9 ) print ( * [ " " .join([v , str ( "{:.2f}" . format (s))]) for v, s in similar_words], sep = "\n" ) |
全体ソースは
1 2 3 4 5 6 7 8 9 10 | 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" ) |
結果は
1 2 3 4 5 6 7 8 9 | 物語 0.99 作 0.98 題材 0.98 代表 0.98 時代 0.97 評論 0.97 世界 0.97 描い 0.97 歌 0.96 |
となった
参考書籍とは違ったけど
年数が立っているので誤差範囲
1 | print ( * [ " " .join([v , str ( "{:.2f}" . format (s))]) for v, s in similar_words], sep = "\n" ) |
がわかりにくいので調べてみた
python {:.2f}
で検索したら
{インデックス番号:書式指定}
ということで
意味は下2桁で小数点タイプということ
これは format() の使い方であるということ
Pythonの文字列フォーマット(formatメソッドの使い方)
をみることで解決
なお今回のようにコーパス(基礎資料)作成
モデル構築
類似度の集計まで一気にやらず
モデル構築時点で一度ファイルに出力すれば
計算処理時間が縮小できる
1 | model.save( "data.model" ) |
全体ソースは
1 2 3 4 5 6 7 8 9 10 11 | 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 が作成される
あとは学習済みモデルを読み込むには
1 | model.word2vec.Word2Vec.load( "data.model" ) |
でOKらしいので
word2vecmodel_data.py
を作成し
1 2 3 4 5 6 | 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" ) |
で実行したら
1 2 3 4 5 6 7 8 9 | 物語 0.99 歌 0.99 古典 0.99 海 0.98 時代 0.98 近代 0.98 作 0.98 世界 0.97 歴史 0.97 |
と同じ結果になった
Word2Vecの学習済み日本語モデルを読み込んで使う
を参考に
参考書籍は
なお kindle Fire でみるときには
拡大しなくても見れるので
10インチがおすすめ
カバーがほしい場合には
マグネット機能で閉じたらOFFにしてくれる純正がおすすめ