wikipediaデータを綺麗にしてからWord2vecやってみた
今更な感じですが色々とあってWord2Vecで類義語分析とか表記ゆれとかできないかと思ってお勉強兼実験しました。もう一人のボクのためにその時のメモを置いておきます。データ加工してからword2vec使って関連する語出すとこまでです。相変わらずほぼコピペだけどね。そしてcorpusのつづりを間違えているのはお約束です。へぼすぎだな(笑)
2.関連ライブラリインストール
4.サンプル
・コマンドラインの後ろに調べたい言葉入れると結果が返ってくる。
・実験用プログラム(word2vecsample.py)
数学が赤点な自分には詳しい仕組みはわかりませんが、矢印を2個くっつけてその間にある角度が小さかったら近しいとか、文字に数字をくっつけて座標軸上にそれを置いて計算できるようにしたとかそんな感じらしい。論文あるそうですが英語も赤点だったのでとてもではないですが読めません。興味ある方はどうぞ
https://arxiv.org/abs/1301.3781
https://arxiv.org/abs/1310.4546
https://arxiv.org/abs/1402.3722
https://arxiv.org/abs/1411.2738
他にも文書をエイやっとするdoc2vecなるものもあるらしい。どちらかというとこちらの方が用途的にはより近しいのかもしれないかなぁと思いつつ、まぁ使い方はほぼ同じみたいだが、、、、word2vecとどこがどう違うんだ?とか思いました。
■参考サイト
・ダウンロードしたデータから記事本文抽出(約2時間10分)
・抽出した記事本文のクリーニング(約15分)
・記事データを1ファイルにマージ(約5分)
・モデル学習(約2時間)
4.サンプルで遊ぶ
■実際のコマンドやプログラムなど
1.ディスク容量拡張
Hyper-Vのディスク容量が20GB程度しかなくwikipediaのデータが
2GBほどあるとのことなのでディスク容量に余裕を持たせるために
ディスクを拡張した。仮想マシンが上がっていない状態で容量拡張
・Hyper-Vマネージャからディスクの編集で容量を拡張
・Hype-Vマシンを起動後に以下のコマンドでUbuntu上で拡張
$ sudo fdisk -l $ sudo parted GNU Parted 3.2 /dev/sda を使用 GNU Parted へようこそ! コマンド一覧を見るには 'help' と入力してください。 (parted)print ~中略~ 修正/Fix/無視(I)/Ignore? Fix 番号 開始 終了 サイズ ファイルシステム 名前 フラグ 1 1049kB 538MB 537MB fat32 EFI System Partition boot, esp 2 538MB 21.5GB 20.9GB ext4 ~中略~ (parted) resizepart 2 警告: パーティション /dev/sda2 は使用中です。それでも実行しますか? はい(Y)/Yes/いいえ(N)/No? Y 終了? [21.5GB]? 50GB ~中略~ (parted) print ~中略~ (parted) quit $ sudo resize2fs /dev/sda2
2.関連ライブラリインストール
データの前処理で必要となるので追加ライブラリをpipで導入
3.コーパス準備
・コーパスを準備するためのコマンド類
・データクリーニング用のプログラム(datacleaning.py)
・モデル生成用プログラム(modelmake.py)
$ sudo apt-get -y install nkf $ pip3 install scipy $ pip3 install gensim $ pip3 install wikipedia2vec $ pip3 install neologdn $ pip3 install emoji
3.コーパス準備
・コーパスを準備するためのコマンド類
#Wikipediaの日本語ダンプをダウンロード $ mkdir copas $ cd copas $ curl https://dumps.wikimedia.org/jawiki/latest/jawiki-latest-pages-articles.xml.bz2 -o jawiki-latest-pages-articles.xml.bz2 #ダウンロードしたデータから記事本文抽出 $ git clone https://github.com/attardi/wikiextractor $ python3 wikiextractor/WikiExtractor.py jawiki-latest-pages-articles.xml.bz2 #抽出した記事本文のクリーニング $ python3 ../src/datacleaning.py text #記事データを1ファイルにマージ $ cat text/*/* > jawiki.txt #形態素解析して分かち書きに変換 $ mecab -d /usr/lib/x86_64-linux-gnu/mecab/dic/mecab-ipadic-neologd -Owakati jawiki.txt -o data.txt -b 16384 $ nkf -w --overwrite data.txt #モデル学習 $ python3 ../src/modelmake.py
・データクリーニング用のプログラム(datacleaning.py)
import os import re import sys import time import traceback import emoji import neologdn def strnormaraizer(str): """ wikipediaデータの日本語を正規化する """ try: s = neologdn.normalize(str) s = re.sub( r'(http|https)://([-\w]+\.)+[-\w]+(/[-\w./?%&=]*)?', "",s ) s = re.sub("<.*?>","",s) s = re.sub(r'(\d)([,.])(\d+)', r'\1\3', s) s = re.sub(r'[!-/:-@[-`{-~]', r' ', s) s = re.sub(u'[■-♯]', ' ', s) s = re.sub(r'(\d)([,.])(\d+)', r'\1\3', s) s = re.sub(r'\d+', '0', s) s = ''.join(['' if c in emoji.UNICODE_EMOJI else c for c in s]) return s except Exception as e: t, v, tb = sys.exc_info() print(traceback.format_exception(t,v,tb)) print(traceback.format_tb(e.__traceback__)) def main(): """ 主処理 第1引数で指定されたディレクトリ配下のファイルをすべて処理する。 """ try: start_t = time.perf_counter() rootdir = sys.argv[1] i=0 for root, dirs, files in os.walk(rootdir): i +=1 j = 0 for root, dirs, files in os.walk(rootdir): if j > 0: print('処理ディレクトリ{0}/{1}'.format(j,i-1)) file_count = len(files) print('処理対象ファイル数{0}'.format(file_count)) j +=1 for file_ in files: input_file = os.path.join(root, file_) with open(input_file,'r') as inf: s =inf.read() o = strnormaraizer(s) with open(input_file,'w') as outf: outf.write(o) end_t = time.perf_counter() process_time = end_t - start_t print('処理時間は:{0}秒です。'.format(process_time)) except Exception as e: t, v, tb = sys.exc_info() print(traceback.format_exception(t,v,tb)) print(traceback.format_tb(e.__traceback__)) if __name__ == '__main__': main()
・モデル生成用プログラム(modelmake.py)
from gensim.models import word2vec import logging logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO) sentences = word2vec.Text8Corpus('./data.txt') model = word2vec.Word2Vec(sentences, size=200, min_count=20, window=15) model.save("./ja_wiki.model")
4.サンプル
・コマンドラインの後ろに調べたい言葉入れると結果が返ってくる。
$ python3 word2vecsample.py 織田信長 ('信長', 0.8410834670066833) ('羽柴秀吉', 0.8160404562950134) ('明智光秀', 0.7978937029838562) ('豊臣秀吉', 0.7927731275558472) ('徳川家康', 0.7548580169677734) ('毛利元就', 0.7484856843948364) ('今川義元', 0.7425110936164856) ('浅井長政', 0.7422305345535278) ('織田氏', 0.7414403557777405) ('武田信玄', 0.7356137633323669)
・実験用プログラム(word2vecsample.py)
from gensim.models import word2vec import sys word = sys.argv[1] model = word2vec.Word2Vec.load("../copas/ja_wiki.model") results = model.wv.most_similar(positive=[word]) for result in results: print(result)
数学が赤点な自分には詳しい仕組みはわかりませんが、矢印を2個くっつけてその間にある角度が小さかったら近しいとか、文字に数字をくっつけて座標軸上にそれを置いて計算できるようにしたとかそんな感じらしい。論文あるそうですが英語も赤点だったのでとてもではないですが読めません。興味ある方はどうぞ
https://arxiv.org/abs/1301.3781
https://arxiv.org/abs/1310.4546
https://arxiv.org/abs/1402.3722
https://arxiv.org/abs/1411.2738
他にも文書をエイやっとするdoc2vecなるものもあるらしい。どちらかというとこちらの方が用途的にはより近しいのかもしれないかなぁと思いつつ、まぁ使い方はほぼ同じみたいだが、、、、word2vecとどこがどう違うんだ?とか思いました。
■参考サイト
・Hyper-Vディスク拡張
・Word2vec関連
・前処理
コメント