wikipediaのデータからword2vecコーパスを作成する
GitHub
この記事のコードは全て以下のリポジトリにあります。
仮想環境の作成
conda create -n wikiw2v python=3.10
conda activate wikiw2v
wikiのデータダウンロード
curl https://dumps.wikimedia.org/jawiki/latest/jawiki-latest-pages-articles.xml.bz2 -o jawiki-latest-pages-articles.xml.bz2
約15分で完了した。
wikiデータの解凍
WikiExtractor
で解凍する。
pip install git+https://github.com/prokotg/wikiextractor
以下コマンドで解凍を実行する。
python -m wikiextractor.WikiExtractor jawiki-latest-pages-articles.xml.bz2
[出力]
INFO: Preprocessing 'jawiki-latest-pages-articles.xml.bz2' to collect template definitions: this may take some time.
INFO: Preprocessed 100000 pages
INFO: Preprocessed 200000 pages
INFO: Preprocessed 300000 pages
INFO: Preprocessed 400000 pages
INFO: Preprocessed 500000 pages
INFO: Preprocessed 600000 pages
INFO: Preprocessed 700000 pages
INFO: Preprocessed 800000 pages
INFO: Preprocessed 900000 pages
INFO: Preprocessed 1000000 pages
INFO: Preprocessed 1100000 pages
INFO: Preprocessed 1200000 pages
INFO: Preprocessed 1300000 pages
INFO: Preprocessed 1400000 pages
INFO: Preprocessed 1500000 pages
INFO: Preprocessed 1600000 pages
INFO: Preprocessed 1700000 pages
INFO: Preprocessed 1800000 pages
INFO: Preprocessed 1900000 pages
INFO: Preprocessed 2000000 pages
INFO: Preprocessed 2100000 pages
INFO: Preprocessed 2200000 pages
INFO: Preprocessed 2300000 pages
INFO: Preprocessed 2400000 pages
INFO: Preprocessed 2500000 pages
INFO: Preprocessed 2600000 pages
INFO: Preprocessed 2700000 pages
INFO: Loaded 98635 templates in 682.9s
INFO: Starting page extraction from jawiki-latest-pages-articles.xml.bz2.
INFO: Using 11 extract processes.
INFO: Finished 11-process extraction of 2204987 articles in 980.6s (2248.6 art/s)
Mecabのインストール
https://taku910.github.io/mecab/#win からインストール。
windowsなので、Binary package for MS-Windows
を選択してダウンロードし、実行すると辞書とともにインストール完了。辞書の文字コードはUTF-8
を選択した。
このとき、パスが通っていなかったので、環境変数に追加した。
pip install mecab-python3
Pythonのライブラリもインストールしておく。
ファイルの結合と分かち書き
解凍されたデータでは、AA
,AB
のようにフォルダに分かれて入っているので、フォルダごとに分かち書きをしてテキストを結合し、さらに一つのテキストファイルに結合する。
import glob
import logging
import os
import MeCab
if not os.path.exists("./wakati"): # ディレクトリが無かったら作成
os.mkdir("wakati")
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
logger = logging.getLogger(__name__)
tagger = MeCab.Tagger("-Owakati")
AllData = ''
Folders = glob.glob('text\*') # textディレクトリ内のフォルダを取得
start_num = 0 # 開始するフォルダの番号を指定
# 一度で実行する場合は0,途中で止まった後に再開するときはその番号
f = open(f"wakati/wiki_data_{Folders[start_num][5:7]}.txt", 'r', encoding='UTF-8') # 読み込むので"r",UTF-8を指定
AllData = f.read()
for FolderName in Folders[start_num+1:]:
files = glob.glob(f"{FolderName}\*") # フォルダの中身を取得
for file in files:
f = open(file, 'r', encoding='UTF-8') # 読み込むので"r",UTF-8を指定
data = f.read()
#AllData += data + '\n'
wakatiData = tagger.parse(data)
AllData += wakatiData + '\n'
logger.info(file)
f.close()
#wf = open(f'data/wiki_data_{FolderName[5:7]}.txt', 'w', encoding='UTF-8')
wf = open(f'wakati/wiki_data_{FolderName[5:7]}.txt', 'w', encoding='UTF-8')
wf.write(AllData)
wf.close
wf = open('wiki_data.txt', 'w', encoding='UTF-8')
wf.write(AllData)
wf.close()
これには2時間程度かかり、途中経過も保存しているためストレージを50GB以上くらい使用するので注意。
途中で止まった場合、wakati
フォルダ内に途中のデータがあるため、そこから再開できる。その際はstart_num
の値を変更する。
タグと記号の除去
wikiデータは<doc></doc>
で囲まれた部分があったり、記号がまだ含まれているのでそれを除去する。
import re
import MeCab
f = open("wiki_data.txt", 'r', encoding='UTF-8')
data = f.read()
f.close()
# 最初にあるタグを消す
data = re.sub(r"<.*?>", r"", data)
# 半角記号削除
data = re.sub(r'[!"#$%&\'\\\\()*+,-./:;<=>?@[\\]^_`{|}~「」〔〕“”〈〉『』【】&*・()$#@。、?!`+¥%]', '', data)
# 全角記号削除
data = re.sub("[\uFF01-\uFF0F\uFF1A-\uFF20\uFF3B-\uFF40\uFF5B-\uFF65\u3000-\u303F]", '', data)
# print(data[0:10000])
#ファイルに書き込み
wf = open('wiki_tag_removed_data.txt', 'w', encoding='UTF-8')
wf.write(data)
wf.close()
単語のベクトル化
from gensim.models import word2vec
import logging
logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
sentences = word2vec.Text8Corpus('./wiki_wakati.txt')
model = word2vec.Word2Vec(sentences, vector_size=200, min_count=20, window=15)
model.wv.save_word2vec_format("./wiki.model", binary=True)
これでコーパス(モデル)を作成する。
ここでは200次元、20回以上出現する単語を使用、単語間の最大距離15としている。
使ってみる
類似単語検索
from gensim.models import KeyedVectors
wv = KeyedVectors.load_word2vec_format('wiki.model', binary=True)
results = wv.most_similar(positive='日本')
for result in results:
print(result)
単語を入力
>>> ご飯
('味噌汁', 0.8243885636329651)
('御飯', 0.8029778003692627)
('おかず', 0.7956658005714417)
('炊き込み', 0.7943350672721863)
('汁物', 0.790287435054779)
('チャーハン', 0.7815099358558655)
('おにぎり', 0.7813826203346252)
('米飯', 0.7800269722938538)
('目玉焼き', 0.775774359703064)
('お茶漬け', 0.763556182384491)
いい感じ。
類似度計算
from gensim.models import KeyedVectors
wv = KeyedVectors.load_word2vec_format('wiki.model', binary=True)
jpkr = wv.similarity('日本', '韓国')
print(f'日本と韓国の類似度 : {jpkr}')
日本と韓国の類似度 : 0.3739430904388428