
自然言語処理の入門、wikipedia全文データを使ってみる
こんにちは。
AI coordinatorの清水秀樹です。
自然言語処理について何から勉強を始めようかと色々模索していたところ、wikipediaの日本語全文データをダウンロードできることを知り、早速それが使えそうなところから初めてみることにしました。
なんでもWord2Vecとかいうライブラリーを使用すると、単語の意味をベクトルで表現できるらしく、関連する単語や類似度を調べることができるようになるとのこと。
ちょうどデータ量として申し分ないwikipedia日本語全文データも使えることも分かったので、早速それらを組み合わせて勉強してみることにしました。
当記事はその内容の紹介になります。
純粋 – 正義 + 悪 = 邪悪
みたいなことができるようになります。
興味がある方は参考にしてみてください。
開発環境
macOS Sierra
Anaconda3-4.2.0-MacOSX-x86_64
python 3.5.2
参考にさせて頂いた書籍の紹介
書籍名:Pythonによるスクレイピング&機械学習
書籍の詳細についてはこちら
wikipedia日本語全文データモデルの作成方法
以下の手順通りでモデル作成ができます。
wikipedia日本語全文データのダウンロード
以下のサイトからwikipedia日本語全文データをダウンロードできます。
大量にダウンロードリンクがありますが、対象となるダウンロードファイルは”jawiki-latest-pages-articles.xml.bz2″です。
検索で探した方が手っ取り早いと思います。

ダウンロード時点では2.3Gバイトもありました。
ダウンロードが完了したら、解凍してWord2Vecに使える形に変更していきます。
xmlからテキスト形式への変換
解凍したらxml形式のファイルになっていますので、これをテキスト形式に変換する必要があります。
変換には”wp2txt”を使用します。
macなら簡単に以下のコマンドでインストールできます。
sudo gem install wp2txt
インストールが完了したら、以下のコマンドでテキストに変換しましょう。
$ wp2txt --input-file ./jawiki-latest-pages-articles.xml
これには結構な時間(筆者の端末で数時間)がかかりますし、大量のファイルに分割されて保存されます。
筆者が作成した時点では全部で560ファイルできました。
気長に待ちましょう。
ちなみにそれぞれのファイルの中身はこんな感じです。
[[長編小説]]
長編小説・長篇小説(ちょうへんしょうせつ)は文学形式の一種。
==概要==
Novelは古イタリア語の「新しい」という接頭辞からきている。小説のうちその分量が特に多く、構造的に長大なものを指す。
何を以て長編小説とするかについては議論が多いが、根本的な問題として小説はかぎりなく長くすることができる。しかしある程度以下には短くすることができない。長編小説には短編小説のごとき構造上の定式がなく、何をどう書いてもいい部分が多いので、その範疇ははなはだひろく、そこに含まれる作品もきわめて多い。長さも形式も自由であるといえる。
日本では通常、掌編(ショートショート、掌編小説など)、短編小説、中編小説に対立する語としてこの言葉が用いられ、現在では大体原稿用紙300枚以上程度を以て長編の名を用いることが多い。
海外では、短編小説に対する長編小説という区分、対立の意識がつよい。つまり周到なプロットによって最後に読者を驚かせておしまいにするのが短編(例えば、O・ヘンリーの『賢者の贈物』の、夫が時計を売ったことが最後に明かされる仕掛け)であり、そのためには作者の語り口、つまり何を語り何を読者に対して秘密にするかがかなりその自由裁量にまかされている。これに対して、そうしたプロットを用いずに叙述を順次すすめてゆくのが長編小説であると考えられることが多い。このため、「長い短編小説」「短い長編小説」(手法的には短編/長編のそれによっているが分量が手法とは相反する)という
テキスト形式に変換し終わったら1つのファイルにまとめましょう。
以下のコマンドを入力すると、強大なテキストファイル1つになります。
$ cat jawiki-latest-pages-articles-* > wiki.txt
形態素解析で分かち書きの作成
巨大なテキストファイルが出来上がったら形態素解析により、テキストを分かち書きにします。
word2vecで学習モデルを作成するためには、テキストを分かち書きにする必要があります。
形態素解析にはmecabを使用します。
mac環境でのmecabのインストールは、以下のサイトが参考になります。
形態素解析エンジンMeCabをPython3でも使えるようにする(Macの場合)
ubuntuでのmecabのインストールは以下のコマンドでインストールできます。
$ sudo apt-get install -y mecab libmecab-dev mecab-ipadic
$ sudo apt-get install -y mecab-ipadic-utf8
$ sudo apt-get install -y libc6-dev build-essential
$ pip3 install mecab-python3
mecabのインストールが完了したら、分かち書きファイルを作成しましょう。
以下のコマンドを打ち込めば、数十分で分かち書きファイルが作成できます。
$ mecab -b 100000 -Owakati wiki.txt -o wiki_wakati.txt
wikipedia日本語全文データモデルファイルの作成
gensimをインストールしましょう。
gensimは自然言語処理のためのライブラリです。
word2vecの機能もあります。
インストールは以下のコマンドで簡単にできます。
$ conda install gensim
インストールが完了したら以下のソースコードでモデルを作成しましょう。
from gensim.models import word2vec
data = word2vec.Text8Corpus("wiki_wakati.txt")
model = word2vec.Word2Vec(data, size=100)
model.save("wiki.model")
print("ok")
しばらく時間がかかります。
筆者のimacで1時間ぐらいかかりました。
モデルの作成が完了するとファイルが3種類出来上がります。
- wiki.model
- wiki.model.syn1neg.npy
- wiki.model.wv.syn0.npy
wikipediaの日本語全文データモデルで類義語を抽出してみよう
モデルが出来上がったら、類義語抽出を試してましょう。
犬の類義語を試してみます。
>>> from gensim.models import word2vec
>>> model = word2vec.Word2Vec.load('wiki.model')
>>> model.most_similar(positive = ['犬'])
[('柴犬', 0.779923677444458), ('オルトロス', 0.7717503309249878), ('セント・バーナード', 0.752425491809845), ('猟犬', 0.7339364290237427), ('オオカミ', 0.7314455509185791), ('猫', 0.7309228777885437), ('イヌ', 0.7242052555084229), ('トイプードル', 0.7196808457374573), ('マルチーズ', 0.7129760980606079), ('パグ', 0.7109533548355103)]
>>>
なかなか良い結果が出力されています。
続いて、「純粋 – 正義 + 悪」を試してみます。
>>> model.most_similar(positive = ['純粋','悪'],negative = ['正義'])
[('乱雑', 0.6487013101577759), ('貪欲', 0.6414044499397278), ('低級', 0.6392396092414856), ('不潔', 0.6338330507278442), ('複雑', 0.6317843794822693), ('不完全', 0.6273522973060608), ('未熟', 0.6242976188659668), ('暖か', 0.6146796345710754), ('邪悪', 0.6124700307846069), ('陰鬱', 0.6106678247451782)]
>>>
なるほどなるほど。
wikipediaを使った日本語全文データ類義語抽出でした。
—2017/08/20追記—–
筆者用のメモ
必要な情報だけを取り出す方法
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"from gensim.models import word2vec\n",
"import matplotlib.pyplot as plt"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"model = word2vec.Word2Vec.load('wiki.model')"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[('肉体', 0.771949291229248),\n",
" ('地球人', 0.7410997152328491),\n",
" ('生き物', 0.7381985783576965),\n",
" ('吸血鬼', 0.7149309515953064),\n",
" ('自分', 0.6920322179794312),\n",
" ('人体', 0.691782534122467),\n",
" ('人類', 0.6892198324203491),\n",
" ('身体', 0.6879268884658813),\n",
" ('知性', 0.6864863038063049),\n",
" ('他人', 0.6860484480857849)]"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model.most_similar(positive = ['人間'])"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"('人体', 0.691782534122467)"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model.most_similar(positive = ['人間'])[5]"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"'人体'"
]
},
"execution_count": 5,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model.most_similar(positive = ['人間'])[5][0]"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[('肉体', 0.771949291229248),\n",
" ('地球人', 0.7410997152328491),\n",
" ('生き物', 0.7381985783576965),\n",
" ('吸血鬼', 0.7149309515953064),\n",
" ('自分', 0.6920322179794312)]"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model.most_similar(positive = ['人間'])[:5]"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[('肉体', 0.771949291229248),\n",
" ('地球人', 0.7410997152328491),\n",
" ('生き物', 0.7381985783576965),\n",
" ('吸血鬼', 0.7149309515953064),\n",
" ('自分', 0.6920322179794312)]"
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model.most_similar(positive = ['人間'])[:5][:5]"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"['肉体', '地球人', '生き物', '吸血鬼', '自分', '人体', '人類', '身体', '知性', '他人']"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"[w[0] for w in model.most_similar(positive = ['人間'])]"
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[('乱雑', 0.6487013101577759),\n",
" ('貪欲', 0.6414044499397278),\n",
" ('低級', 0.6392396092414856),\n",
" ('不潔', 0.6338330507278442),\n",
" ('複雑', 0.6317843794822693),\n",
" ('不完全', 0.6273522973060608),\n",
" ('未熟', 0.6242976188659668),\n",
" ('暖か', 0.6146796345710754),\n",
" ('邪悪', 0.6124700307846069),\n",
" ('陰鬱', 0.6106678247451782)]"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"model.most_similar(positive = ['純粋','悪'],negative = ['正義'])"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"label = [w[0] for w in model.most_similar(positive = ['純粋','悪'],negative = ['正義'])]"
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"['乱雑', '貪欲', '低級', '不潔', '複雑', '不完全', '未熟', '暖か', '邪悪', '陰鬱']"
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"label"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"cos = [w[1] for w in model.most_similar(positive = ['純粋','悪'],negative = ['正義'])]"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"text/plain": [
"[0.6487013101577759,\n",
" 0.6414044499397278,\n",
" 0.6392396092414856,\n",
" 0.6338330507278442,\n",
" 0.6317843794822693,\n",
" 0.6273522973060608,\n",
" 0.6242976188659668,\n",
" 0.6146796345710754,\n",
" 0.6124700307846069,\n",
" 0.6106678247451782]"
]
},
"execution_count": 13,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"cos"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"anaconda-cloud": {},
"kernelspec": {
"display_name": "Python [conda root]",
"language": "python",
"name": "conda-root-py"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.2"
}
},
"nbformat": 4,
"nbformat_minor": 1
}
それではまた。
コメントはまだありません。