見出し画像

Doc2Vec を使って日本語の Wikipedia を学習する

Doc2Vec を使って日本語の Wikipedia を学習し,そのモデルを使って類似文書の算出や文書ベクトルの計算などをやってみたのでそのコードとデモです.
Doc2Vec についての説明はこのページがわかりやすいです.

なお,有料部分は今回使った学習済みモデルのダウンロードリンクです.

記事を学習させる

Wikipedia の dump データは https://dumps.wikimedia.org/jawiki/latest/ にあるので,このページから jawiki-latest-pages-articles.xml.bz2 をダウンロードしてきます.

gensimdoc2vec を使うので pip でインストールします.

$ pip install gensim

そして次のようなコードで学習させます.

import gensim
from gensim.corpora.wikicorpus import WikiCorpus
from gensim.models.doc2vec import Doc2Vec, Doc2VecVocab, TaggedDocument

wiki = WikiCorpus('jawiki-latest-pages-articles.xml.bz2')

class TaggedWikiDocument(object):
   def __init__(self, wiki):
       self.wiki = wiki
       self.wiki.metadata = True
   def __iter__(self):
       for content, (page_id, title) in self.wiki.get_texts():
           yield TaggedDocument([c for c in content], [title])

document = TaggedWikiDocument(wiki)
model = Doc2Vec(documents=document, dm=1, vector_size=400, window=8, min_count=10, epochs=10, workers=6)
model.save('model/wikipedia.model')

ベクトルは400次元にしました.(vector_size=400)
そこそこハイスペックなマシンでも3時間ほどかかるので終わるまで放置します.

類似記事を調べてみる

実際にできあがったモデルを使って類似記事などを調べてみます.

gensim の import とモデルの読み込み.(結果を見やすくするために pprint も import しています)

>>> import gensim
>>> from pprint import pprint
>>> model = gensim.models.Doc2Vec.load('wikipedia.model')

「バラク・オバマ」の記事と類似度の高い記事を10個取得

>>> pprint(model.docvecs.most_similar(['バラク・オバマ']))
[('ジョージ・W・ブッシュ', 0.6693710684776306),
('ビル・クリントン', 0.6429920196533203),
('ジョー・バイデン', 0.6411311030387878),
('ヒラリー・クリントン', 0.6324282884597778),
('リチャード・ホルブルック', 0.6311899423599243),
('ドナルド・トランプ', 0.6021257638931274),
('アメリカ合衆国の歴史', 0.5982885360717773),
('ロナルド・レーガン', 0.5905283689498901),
('胡錦濤', 0.5833597183227539),
('ティーパーティー運動', 0.5821385383605957)]

「スティーブ・ジョブズ」の記事と類似度の高い記事を10個取得

>>> pprint(model.docvecs.most_similar(['スティーブ・ジョブズ']))
[('アップル (企業)', 0.7481854557991028),
('マイクロソフトの歴史', 0.6602843999862671),
('スティーブ・ウォズニアック', 0.6517555713653564),
('ジェフ・ラスキン', 0.6370124220848083),
('VisiOn', 0.6360085606575012),
('NeXT', 0.6238383054733276),
('ビル・ゲイツ', 0.6187927722930908),
('Microsoft Windows 1.0', 0.6118876934051514),
('BSD', 0.6117375493049622),
('アンドリュー・タネンバウムとリーヌス・トーヴァルズの議論', 0.6040152311325073)]

記事だけでなく単語のベクトルも学習されるのでこちらも試してみます.

「コンピューター」の類似単語を10個取得

>>> pprint(model.most_similar(['コンピューター']))
[('コンピュータ', 0.6648749709129333),
('マルチメディア', 0.5935486555099487),
('フィードバック', 0.583861231803894),
('グラフィックス', 0.5812052488327026),
('アーキテクト', 0.5801048278808594),
('デバイス', 0.5796220302581787),
('インテリジェント', 0.5781210660934448),
('モデリング', 0.5612391233444214),
('インタフェース', 0.5612084865570068),
('ハードウェア', 0.5593206882476807)]

「宇宙」の類似単語を10個取得

>>> pprint(model.most_similar(['宇宙']))
[('地球', 0.6782646179199219),
('うちゅう', 0.6199731826782227),
('未知への大紀行', 0.5930077433586121),
('そら', 0.5706053972244263),
('太陽系', 0.5619747638702393),
('生命', 0.5541218519210815),
('人工衛星', 0.5367318391799927),
('惑星', 0.517905056476593),
('cosmos', 0.5111895799636841),
('億年の旅', 0.5107935070991516)]

言葉の足し算引き算

こちらの論文(https://arxiv.org/abs/1507.07998)で実験しているようにベクトルの足し算引き算もやってみます.
論文では英語 Wikipedia を使って「日本のレディー・ガガ」を調べ, "Lady Gaga" - "American" + "Japanese" = "Ayumi Hamasaki" という結果になっています.

バラク・オバマ - 人類 + 鳥類 = オウム?

>>> vec = [model.docvecs['バラク・オバマ'] - model.docvecs['人類'] + model.docvecs['鳥類']]
>>> pprint(model.docvecs.most_similar(vec))
[('鳥類', 0.7806053161621094),
('バラク・オバマ', 0.701985239982605),
('オウム', 0.6742724180221558),
('アオツラミツスイ', 0.6603245735168457),
('ニオイシュロラン', 0.6487298607826233),
('マカイロドゥス亜科', 0.6485608816146851),
('海水魚', 0.6390255689620972),
('外来種', 0.6386425495147705),
('アレチネズミ亜科', 0.6325357556343079),
('ランフォリンクス', 0.6322495937347412)]

スティーブ・ジョブズ - 人類 + 魚類 = 熱帯魚?
(「頂点捕食者」や「生きている化石」が出てくるのも面白いですね)

>>> vec = [model.docvecs['スティーブ・ジョブズ'] - model.docvecs['人類'] + model.docvecs['魚類']]
>>> pprint(model.docvecs.most_similar(vec))
[('スティーブ・ジョブズ', 0.7406678795814514),
('熱帯魚', 0.7179751396179199),
('頂点捕食者', 0.7126423120498657),
('魚類', 0.7111055850982666),
('生きている化石', 0.705655574798584),
('条鰭綱', 0.7049722671508789),
('セアカゴケグモ', 0.704893171787262),
('ドロマエオサウルス科', 0.704292893409729),
('コエルロサウルス類', 0.7030231952667236),
('アフリカゾウ', 0.7005866765975952)]

文書ベクトル同士だけでなく単語ベクトルとも計算できます.

落合陽一 - 人間 + コンピュータ = RLogin?センサネットワーク?

>>> vec = [model.docvecs['落合陽一'] - model.wv['人間'] + model.wv['コンピュータ']]
>>> pprint(model.docvecs.most_similar(vec))
[('RLogin', 0.4472082853317261),
('RedHawk Linux', 0.40638870000839233),
('センサネットワーク', 0.4047044515609741),
('エンタープライズ・サービス・バス', 0.3979302644729614),
('スーパーコンピュータ技術史', 0.39672616124153137),
('タイル型ウィンドウマネージャ', 0.3891061842441559),
('音声合成', 0.3887993097305298),
('ノベル (企業)', 0.3883364200592041),
('プログラマブルロジックデバイス', 0.38543957471847534),
('端末', 0.38519078493118286)]


有料部分は今回使ったモデルのダウンロードリンクです.自己責任でお使いください.

この続きをみるには

この続き: 389文字

Doc2Vec を使って日本語の Wikipedia を学習する

itabashi

500円

🎃
10
コメントを投稿するには、 ログイン または 会員登録 をする必要があります。