どん底から這い上がるまでの記録

どん底から這い上がりたいけど這い上がれない人がいろいろ書くブログ(主にプログラミング)

gensimのWord2Vecを使ってみる。

gensimのWord2Vecの使ってみたので、そのメモ。

今回はWikipediaの文章を使ってやってみますが、すぐに学習結果を知りたかったので少ないデータで学習をしています。

 

環境

MeCabWindowsにインストールするには

https://www.pytry3g.com/entry/2018/04/24/143934#Windows

データの用意

ライブラリのインポート

必要なライブラリのインポートをします。

import MeCab
import codecs
import urllib.parse as parser
import urllib.request as request
from bs4 import BeautifulSoup

Wikipediaの記事をダウンロード

Wikipediaから学習データを取ってきます。今回はいくつかの戦国大名に関する記事を学習データとして使います。

urllibを使ってWikipediaの記事をダウンロードします。

参考リンク

tagger = MeCab.Tagger("-Owakati")
link = "https://ja.wikipedia.org/wiki/"
keyword = ["織田信長", "徳川家康", "豊臣秀吉",
           "伊達政宗", "武田信玄", "上杉謙信",
           "明智光秀", "島津義弘", "北条氏康",
           "長宗我部元親", "毛利元就", "真田幸村",
           "立花宗茂", "石田三成", "浅井長政"]

corpus = []
for word in keyword:
    # 戦国大名の記事をダウンロード
    with request.urlopen(link + parser.quote_plus(word)) as response:
        # responseはhtmlのformatになっている
        html = response.read().decode('utf-8')

 

BeautifulSoup

urillibを使って受け取ったresponseを読み込むと、HTMLのformatになっているので、BeautifulSoupを使っていらないタグを取り除きます。

参考リンク

        soup = BeautifulSoup(html, "lxml")
        # <p>タグを取得
        p_tags = soup.find_all('p')
        for p in p_tags:
            corpus.append(tagger.parse(p.text).strip())

上でやっていることはHTML形式の文字列から<p></p>で囲まれているところを取り出し、形態素解析して分かち書きしたものをcorpusに追加しています。

その後、corpusのそれぞれの要素の末尾に改行文字を加え、pwiki.txtというファイルにして保存しています。これを学習データとして使います。

with codecs.open("pwiki.txt", "w", "utf-8") as f:
    f.write("\n".join(corpus))

Word2Vec

ライブラリのインポート

import codecs
from gensim.models import word2vec

学習する

with codecs.open("pwiki.txt", "r", "utf-8") as f:
    corpus = f.read().splitlines()

corpus = [sentence.split() for sentence in corpus]
#モデルを作る
model = word2vec.Word2Vec(corpus, size=200, min_count=20, window=10)

データの用意のところで作成したpwiki.txtを読み込んで、Word2Vecに渡しています。

corpusの中身は以下のようになっていて、リストの中に単語が入ったリストがあります。

[
['織田', '信長', '(', 'おだ', 'のぶ', 'な', 'が', ')', 'は', '、', '戦国', '時代', 'から', '安土', '桃山', '時代', 'にかけて', 'の', '武将', '・', '戦国', '大名', '。', '三', '英傑', 'の', '一', '人', '。'],

['尾張', '国', '(', '現在', 'の', '愛知', '県', ')', 'の', '古渡', '城主', '・', '織田', '信秀', 'の', '嫡男', '[', '注釈', '5', ']。']
]

モデルの保存と読み込み

# モデルを保存
model.save("pwiki.model")
# モデルを読み込む
model = word2vec.Word2Vec.load("pwiki.model")

単語のベクトルを見る

# 単語のベクトルを見る
word_vector = model.wv["尾張"]

型はnumpy

ある単語と類似している単語を見る

# 尾張と類似している単語を見る
similar_words = model.wv.most_similar(positive=["尾張"], topn=9)
print(*[" ".join([v, str("{:.2f}".format(s))]) for v, s in similar_words], sep="\n")

similar_wordsにはリストになっていて、その要素はtupleとなっている。

tupleは単語と類似度の組になっている。

において 1.00
信虎 1.00
斎藤 1.00
原 1.00
立花 1.00
乱 1.00
河 1.00
川中島 1.00
尼子 1.00

2つの単語の類似度を計算

# 2つの単語の類似度を計算。
similarity = model.wv.similarity(w1="尾張", w2="天正")

vocab

vocab = model.wv.vocab

辞書になっていて、中身はkeyは単語、valueはgensim.models.keyedvectors.Vocabになっている。

index2word

index2word = model.wv.index2word

リストになっていて、要素は単語が入っている。

syn0

word_vectors = model.wv.syn0

全ての単語のベクトルを返す。

ソースコード

ソースコード① データの用意

import MeCab
import codecs
import urllib.parse as parser
import urllib.request as request
from bs4 import BeautifulSoup


tagger = MeCab.Tagger("-Owakati")
link = "https://ja.wikipedia.org/wiki/"
keyword = ["織田信長", "徳川家康", "豊臣秀吉",
           "伊達政宗", "武田信玄", "上杉謙信",
           "明智光秀", "島津義弘", "北条氏康",
           "長宗我部元親", "毛利元就", "真田幸村",
           "立花宗茂", "石田三成", "浅井長政"]

corpus = []
for word in keyword:
    # 戦国大名の記事をダウンロード
    with request.urlopen(link + parser.quote_plus(word)) as response:
        # responseはhtmlのformatになっている
        html = response.read().decode('utf-8')
        soup = BeautifulSoup(html, "lxml")
        # <p>タグを取得
        p_tags = soup.find_all('p')
        for p in p_tags:
            corpus.append(tagger.parse(p.text).strip())

with codecs.open("pwiki.txt", "w", "utf-8") as f:
    f.write("\n".join(corpus))

ソースコード② Word2Vec

import codecs
from gensim.models import word2vec

with codecs.open("pwiki.txt", "r", "utf-8") as f:
    corpus = f.read().splitlines()

corpus = [sentence.split() for sentence in corpus]
#モデルを作る
model = word2vec.Word2Vec(corpus, size=200, min_count=20, window=10)
# モデルを保存
model.save("pwiki.model")
# モデルを読み込む
model = word2vec.Word2Vec.load("pwiki.model")

# 単語のベクトルを見る
word_vector = model.wv["尾張"]

# 尾張と類似している単語を見る
similar_words = model.wv.most_similar(positive=["尾張"], topn=9)

# 2つの単語の類似度を計算。
similarity = model.wv.similarity(w1="尾張", w2="天正")

vocab = model.wv.vocab

index2word = model.wv.index2word

word_vectors = model.wv.syn0