Wikipediaから日本語コーパスを利用してSentencePieceでトークナイズ(分かち書き)

ディープラーニング

Wikipediaから日本語の大量の文章をダウンロードする

https://dumps.wikimedia.org/jawiki/latest/jawiki-latest-pages-articles.xml.bz2から日本語コンテンツをダウンロードする(1時間ぐらいかかった)。

jawiki-latest-pages-articles.xml.bz2

がダウンロードしたファイル。

圧縮状態で2.78GB、解凍すると11.64GBとかなり大きいです。

wikiextractorでxmlタグを削除して文書を切り出す

内容はxml形式なのでそのままでは使えないので(タグがたくさん入っている)、

wikiextractorで文章のみ切り出す。

git clone https://github.com/attardi/wikiextractor.git
cd wikiextractor/
python setup.py install
python WikiExtractor.py jawiki-latest-pages-articles.xml

textフォルダにAA, ABといったフォルダが作成され、これらのフォルダ内にwiki_00~wiki_99というテキストファイルが作成される。

この大量のテキストファイルをひとつのwiki.txtに統合する。

find text/ | grep wiki | awk '{system("cat "$0" >> wiki.txt")}'
wiki.txtの容量は約5.5GBあって、
wcコマンドで行数と文字数をチェックしてみると、
wc -ml wiki.txt
24616931 1083640118 wiki.txt

2461万行で10億文字あるみたいですね。

ファイルの中身を見てみると、

<doc id="3141550" url="https://ja.wikipedia.org/wiki?curid=3141550" title="あしたのニュース">
あしたのニュース
『あしたのニュース』は、フジテレビ系列で2015年(平成27年)3月30日から2016年(平成28年) 4月2日まで、(月曜日から金曜日)の最終版に生放送されていた報道・情報番組である。後続のスポーツニュース番組『すぽると!』とコンプレックス枠を形成されていた(ビデオリサーチの視聴率公表上の放送枠、EPG、ネット各局の公式ウェブサイトの番組表のみ。新聞では『あしたのニュース』と『すぽると!』はそれぞれ単独番組扱い)。

のようになっていて、docタグ内にコンテンツが入っています。

ファイルを一定行数ごとに分割する

大きなデータを扱っていると、よく出会うエラーがOOM (out of memory)エラーです。

メモリーに載せきることができませんでした。

みたいなエラーです。

これを避けるには、ファイルを分割することが必要です。

ファイルを分割するにはsplitコマンドが便利です。

split -l 100000 wiki.txt wiki_
とすると、wiki.txtというファイルを100000行ごとに分割してwiki_aaみたいなファイルに保存してくれます。ちなみに100000行ごとに分割するとwiki.txtは224ファイルに分割されました。

sedを使ってdocタグを取り除く

<doc>タグを取り除きたい場合は、

cat wiki.txt | sed '/^<[^>]*>$/d' > wiki_removed_doc_tag.txt

sedと正規表現を使って取り除けます。

catでwiki.txtを開いてパイプ( | )でsedに送って正規表現でdocタグを除去して、wiki_removed_doc_tag.txtに書き出しています。

簡単sed講座

sed '/^<[^>]*>$/d'

dはdelete(削除する)という意味

/ / で囲われた部分は正規表現を意味していて、あるパターンに基づいて文章を抜き出したりするのに使われます。

sed '/^<[^>]*>$/d'

今回の例では、/ / で囲われた正規表現を使って抽出して削除(delete)するということになります。

正規表現で使われるメタ文字

^ 文頭

$ 文末

ただし、[ ] 内で使われると

[^・・・・・]

否定という意味になる。

[^0-9] 数字以外

[^a-z] 小文字のアルファベット以外という意味

[^>] は >以外の文字という意味で、

[^>]* と*(アスタリスク)がつくと0文字以上の繰り返しという意味。

なので、^<[^>]*>$は

文頭が<で始まり、文末が>で終わり <>の中は>以外の任意の文字列という意味。

つまり<doc>や<html>や<div>などのタグですね。

今回は<doc>を取り除いています。

sentencepieceで分かち書きするためのモデルを作成する

pip install sentencepiece
Wikipediaの全文でsentencepieceモデルを作成する。
spm_train.py
import sentencepiece as spm
spm.SentencePieceTrainer.Train('--input=wiki.txt, --model_prefix=m --character_coverage=1.0 --vocab_size=32000')

iMacで2時間ぐらいかかった。

--character_coverage=1.0にすることですべての文字をカバーしてくれる。

デフォルトは0.9995なので、0.05%の文字がカバーされない。マイナーな漢字が無視されるということですね。一万文字あたり、5文字だが、今回はそれは困るので1.0にしました。

--model_prefix=mにより接頭辞がmのm.modelとm.vocabというファイルが作成される。

spm_segmentation.py

import sentencepiece as spm
sp = spm.SentencePieceProcessor()
sp.Load("m.model")
print(sp.EncodeAsPieces("アメリカ南部一致ルーテル教会()の宣教師を中心とする宣教師社団在日本アメリカ南部福音ルーテル教会ユナイテッド・シノッド宣教師社団の名称で発足。民法第34条に基づき文部大臣の認可を得て社団法人として創設された。教育機関や福祉施設の設立・維持支援に取り組んだ。"))

これを実行すると、

python spm_segmentation.py
Output ['▁アメリカ', '南部', '一致', 'ルー', 'テル', '教会', '(', ')', 'の', '宣教師', 'を中心とする', '宣教師', '社', '団', '在', '日本', 'アメリカ', '南部', '福音', 'ルー', 'テル', '教会', 'ユナイテッド', '・', 'シ', 'ノ', 'ッド', '宣教師', '社', '団', 'の名称で', '発足', '。', '民法', '第', '34', '条', 'に基づき', '文部大臣', 'の', '

分かち書きができるようになる。そこそこ良さそうですね。

コメント