日本のWikipediaのデータを使ったWord2vecでの類似語表示とngramで文生成 (1)
まともに使ったことがなかったWord2vecを使っていきます。
データを手に入れる
まず、Wikipediaのデータはここから拾ってきます。
Wikipedia:データベースダウンロード - Wikipedia
基本は最新の全ページを拾ってくればいいと思います。
英語を使いたい人は少し前処理を変える必要がありますが、普通にいけると思います。
wgetで拾います。容量が大きいので要注意。
wget https://dumps.wikimedia.org/jawiki/latest/jawiki-latest-pages-articles.xml.bz2
前処理
データが大きいので分割して処理します。
wikiextractorをcloneして使いましょう。
git clone https://github.com/attardi/wikiextractor.git cd wikiextractor
extractというフォルダに、1ファイル50Mずつで分割して出力します。
python WikiExtractor.py -b 50M -o extract jawiki-latest-pages-articles.xml.bz2
正規化
こちらのコードを使わせていただきました。
umiushizn.blogspot.jp
normalize_neologd.py
# encoding: utf8 from __future__ import unicode_literals import re import unicodedata def unicode_normalize(cls, s): pt = re.compile('([{}]+)'.format(cls)) def norm(c): return unicodedata.normalize('NFKC', c) if pt.match(c) else c s = ''.join(norm(x) for x in re.split(pt, s)) s = re.sub('-', '-', s) return s def remove_extra_spaces(s): s = re.sub('[ ]+', ' ', s) blocks = ''.join(('\u4E00-\u9FFF', # CJK UNIFIED IDEOGRAPHS '\u3040-\u309F', # HIRAGANA '\u30A0-\u30FF', # KATAKANA '\u3000-\u303F', # CJK SYMBOLS AND PUNCTUATION '\uFF00-\uFFEF' # HALFWIDTH AND FULLWIDTH FORMS )) basic_latin = '\u0000-\u007F' def remove_space_between(cls1, cls2, s): p = re.compile('([{}]) ([{}])'.format(cls1, cls2)) while p.search(s): s = p.sub(r'\1\2', s) return s s = remove_space_between(blocks, blocks, s) s = remove_space_between(blocks, basic_latin, s) s = remove_space_between(basic_latin, blocks, s) return s def normalize_neologd(s): s = s.strip() s = unicode_normalize('0-9A-Za-z。-゚', s) def maketrans(f, t): return {ord(x): ord(y) for x, y in zip(f, t)} s = re.sub('[˗֊‐‑‒–⁃⁻₋−]+', '-', s) # normalize hyphens s = re.sub('[﹣-ー—―─━ー]+', 'ー', s) # normalize choonpus s = re.sub('[~∼∾〜〰~]', '', s) # remove tildes s = s.translate( maketrans('!"#$%&\'()*+,-./:;<=>?@[¥]^_`{|}~。、・「」', '!”#$%&’()*+,-./:;<=>?@[¥]^_`{|}〜。、・「」')) s = remove_extra_spaces(s) s = unicode_normalize('!”#$%&’()*+,-./:;<>?@[¥]^_`{|}〜', s) # keep =,・,「,」 s = re.sub('[’]', '\'', s) s = re.sub('[”]', '"', s) return s if __name__ == "__main__": assert "0123456789" == normalize_neologd("0123456789") assert "ABCDEFGHIJKLMNOPQRSTUVWXYZ" == normalize_neologd("ABCDEFGHIJKLMNOPQRSTUVWXYZ") assert "abcdefghijklmnopqrstuvwxyz" == normalize_neologd("abcdefghijklmnopqrstuvwxyz") assert "!\"#$%&'()*+,-./:;<>?@[¥]^_`{|}" == normalize_neologd("!”#$%&’()*+,-./:;<>?@[¥]^_`{|}") assert "=。、・「」" == normalize_neologd("=。、・「」") assert "ハンカク" == normalize_neologd("ハンカク") assert "o-o" == normalize_neologd("o₋o") assert "majikaー" == normalize_neologd("majika━") assert "わい" == normalize_neologd("わ〰い") assert "スーパー" == normalize_neologd("スーパーーーー") assert "!#" == normalize_neologd("!#") assert "ゼンカクスペース" == normalize_neologd("ゼンカク スペース") assert "おお" == normalize_neologd("お お") assert "おお" == normalize_neologd(" おお") assert "おお" == normalize_neologd("おお ") assert "検索エンジン自作入門を買いました!!!" == \ normalize_neologd("検索 エンジン 自作 入門 を 買い ました!!!") assert "アルゴリズムC" == normalize_neologd("アルゴリズム C") assert "PRML副読本" == normalize_neologd(" PRML 副 読 本 ") assert "Coding the Matrix" == normalize_neologd("Coding the Matrix") assert "南アルプスの天然水Sparking Lemonレモン一絞り" == \ normalize_neologd("南アルプスの 天然水 Sparking Lemon レモン一絞り") assert "南アルプスの天然水-Sparking*Lemon+レモン一絞り" == \ normalize_neologd("南アルプスの 天然水- Sparking* Lemon+ レモン一絞り")
conv.py
import sys import normalize_neologd as nneo import re for line in sys.stdin: line = line.replace("。","。\n") line = re.sub(r'<[^\]]*>', '', line) print(nneo.normalize_neologd(line))
全ファイルに対して処理をすると重いので、今回は1ファイルだけ使います。
mecabで-bオプションをつけないとうまくいきませんでした。
cat extract/AA/wiki | python conv.py | mecab -b 100000000 -Owakati -d /usr/local/lib/mecab/dic/ipadic/ > wiki.txt
ここから生成したテキストを処理していきます。