fastTextで自然言語(日本語)の学習モデルを生成する手順まとめのイメージ画像

fastTextで自然言語(日本語)の学習モデルを生成する手順まとめ

  • 公開日:2018/11/03
  • 更新日:2020/10/07
  • 投稿者:n bit

Facebookが開発したfastTextを利用して自然言語(Wikipediaの日本語全記事)の機械学習モデルを生成するまでの手順を解説。また生成した学習モデルを使って類語抽出や単語ベクトルの足し算引き算等の演算テストを行う方法までコード付きで紹介します。

  • Python

この記事は約 分で読めます。(文字)

fastTextで日本語を機械学習させる手順

Facebook発表の『fastText』利用して日本語の機械学習モデルを生成する手順を解説していきます。

Wikipediaの全記事のダンプデータ取得

学習本の文章にはWikipediaを利用します。下記URLから、最新のWikipedia全記事ダンプデータをダウンロードしましょう。取得データはXML形式の圧縮ファイルになっています。

任意のディレクトリに保存してください。

Wikipediaのダンプデータから文章のみを抽出

WikiExtractorを使用してXMLから文章のみを抽出します。WikiExtractorは、Wikipediaデータベースのダンプデータから文章を抽出するPythonスクリプトです。

cdコマンドで任意のディレクトリに移動してGitからcloneします。

$ cd 任意のインストール先ディレクトリ

$ git clone https://github.com/attardi/wikiextractor.git

出力結果

Cloning into 'wikiextractor'...

remote: Enumerating objects: 523, done.
remote: Total 523 (delta 0), reused 0 (delta 0), pack-reused 523
Receiving objects: 100% (523/523), 454.22 KiB | 366.00 KiB/s, done.
Resolving deltas: 100% (297/297), done.

スクリプトは直接起動することもできますので下記コマンドを実行して直接処理を行います。

  • python wikiextractor/WikiExtractor.py -b 500M -o [出力先ディレクトリ] [ダンプデータ]
$ python wikiextractor/WikiExtractor.py -b 500M -o wikiextractor_output/corpus jawiki_dump/jawiki-20181020-pages-articles-multistream.xml.bz2

出力結果




INFO: Finished 11-process extraction of 1125721 articles in 4737.9s (237.6 art/s)

結構処理が重たいのか処理中ファンが全開で回っています。処理完了までに80分程度かかりました。

ダンプデータとWikiExtractorを使って文章抽出した後のデータを比較すると以下のようになります。

元データ

Wikipediaの全文ダンプデータ

WikiExtractor実行後のデータ

Wikipediaの全文コーパス

出力先ディレクトリに指定したwikiextractor_output/corpus/AAディレクトリ内に連番ファイルが複数生成されます。今回は6つのファイルが生成されました。

  • wiki_00:524.2MB
  • wiki_01:524.2MB
  • wiki_02:524.2MB
  • wiki_03:524.2MB
  • wiki_04:524.2MB
  • wiki_05:175.3MB

複数生成された連番ファイルをcatコマンドで1つのファイルに結合しておきます。

$ cd /Users/xx/wikiextractor_output/corpus/AA

$ cat wiki_00 wiki_01 wiki_02 wiki_03 wiki_04 wiki_05 >wiki_20181020

合計で約2.7GBの『wiki_20181020』ファイルが作成されました。

コーパスの結合結果

文章のみ抽出したデータを分かち書き

文章として連なったままのテキストデータではベクトルの計算を行うことができませんので事前に分かち書きを行っておきましょう。MeCabと新語辞書mecab-ipadic-NEologdを使用して文章のみ抽出したデータを分かち書きします。

MeCabと新語辞書mecab-ipadic-NEologdの環境構築がまだ完了していない方は下記のページを参考にしてインストールしておいてください。

分かち書きを実行するには下記のコマンドを入力してください。

  • mecab -O wakati -d [辞書ディレクトリ] [対象テキストファイル] -o [出力先ファイル]
$ mecab -O wakati -d /usr/local/lib/mecab/dic/mecab-ipadic-neologd wiki_20181020 -o wiki_wakati_20181020

そのまま実行するとバッファサイズが足りないとエラーが出ました。

  • input-buffer overflow. The line is split. use -b #SIZE option.

仕方ないのでバッファサイズを指定するオプションを使って対応しておきましょう。今回は適正値を探すのが大変なのでいきなり上限まで(最大8192 * 640)引き上げて指定します。

オプションを使った実行には下記のコマンドを入力してください。

$ mecab -O wakati -d /usr/local/lib/mecab/dic/mecab-ipadic-neologd -b 5242880 wiki_20181020 -o wiki_wakati_20181020

今度はエラーが出ず無事に分かち書きできました。分かち書きの実行処理はわりと早く20分程度で完了です。さすがMeCab!

今回指定したMeCabのオプションコマンド

今回実行時に指定したMeCabのオプションコマンドについて下記にまとめておきます。

オプションフルコマンド指定値説明
-O--output-format-typeTYPE出力フォーマットの形式を指定
・dump
・wakati
-b--input-buffer-sizeINT入力文字列のバッファサイズを指定
・最大8192 * 640の値まで
-d--dicdirDIR使用する辞書を指定
-o--outputFILE出力先ファイルを指定

分かち書きデータからfastTextで機械学習する

『fastText』はFacebookが開発した自然言語の機械学習ツールです。Googleが開発したWord2Vecよりも学習速度が高速で精度も高いので多く利用されています。

fastTextのインストール

任意のディレクトリにcdコマンドで移動してfastTextをGitからcloneします。

$ cd 任意のインストール先ディレクトリ

$ git clone https://github.com/facebookresearch/fastText.git

出力結果

Cloning into 'fastText'...

remote: Enumerating objects: 1, done.
remote: Counting objects: 100% (1/1), done.
remote: Total 2629 (delta 0), reused 0 (delta 0), pack-reused 2628
Receiving objects: 100% (2629/2629), 7.63 MiB | 476.00 KiB/s, done.
Resolving deltas: 100% (1637/1637), done.

『make』コマンドで自動的にコンパイルします。

$ cd fastText

$ make

出力結果

c++ -pthread -std=c++0x -march=native -O3 -funroll-loops -c src/args.cc

c++ -pthread -std=c++0x -march=native -O3 -funroll-loops -c src/dictionary.cc
c++ -pthread -std=c++0x -march=native -O3 -funroll-loops -c src/productquantizer.cc
c++ -pthread -std=c++0x -march=native -O3 -funroll-loops -c src/matrix.cc
c++ -pthread -std=c++0x -march=native -O3 -funroll-loops -c src/qmatrix.cc
c++ -pthread -std=c++0x -march=native -O3 -funroll-loops -c src/vector.cc
c++ -pthread -std=c++0x -march=native -O3 -funroll-loops -c src/model.cc
c++ -pthread -std=c++0x -march=native -O3 -funroll-loops -c src/utils.cc
c++ -pthread -std=c++0x -march=native -O3 -funroll-loops -c src/fasttext.cc
c++ -pthread -std=c++0x -march=native -O3 -funroll-loops args.o dictionary.o productquantizer.o matrix.o qmatrix.o vector.o model.o utils.o fasttext.o src/main.cc -o fasttext

fastTextで機械学習する

MeCabと新語辞書mecab-ipadic-NEologdを使用して分かち書きしたWikipediaの文章のみ抽出データをfastTextで学習させてモデルを生成します。

学習時のベクトル次元数のパラメータはパラメータの目安は以下のように言われています。

  • 小規模コーパス(〜50M words):100次元
  • 中規模コーパス(〜200M〜 words):200次元
  • 大規模コーパス(300M〜 words):300次元

今回はWikipediaの全文を利用して学習しますので大規模コーパスに該当するでしょう。ベクトルの次元数としては300次元を設定します。

  • $ ./fasttext skipgram -input [学習対象ファイル] -output model [出力先ファイル] -dim [ベクトルの次元数]
$ ./fasttext skipgram -input ../wikiextractor_output/corpus/AA/wiki_wakati_20181020 -output model_20181020 -dim 300

スタートすると学習対象ファイルの概要が表示されます。

  • Read 541M words
  • Number of words:  980734
  • Number of labels: 0

『Read 541M words』になっていますので300次元でそのまま行きます。

出力結果

Progress:   0.0% words/sec/thread:     504 lr:  0.050000 loss:  4.159913 ETA: 12

Progress: 0.0% words/sec/thread: 2137 lr: 0.049999 loss: 4.155802 ETA: 2
Progress: 0.0% words/sec/thread: 3993 lr: 0.049998 loss: 4.149930 ETA: 1
Progress: 0.0% words/sec/thread: 5677 lr: 0.049997 loss: 4.144916 ETA: 1
Progress: 0.0% words/sec/thread: 7154 lr: 0.049996 loss: 4.139351 ETA:



Progress: 100.0% words/sec/thread: 38567 lr: 0.000002 loss: 0.229509 ETA:
Progress: 100.0% words/sec/thread: 38567 lr: 0.000001 loss: 0.229505 ETA:
Progress: 100.0% words/sec/thread: 38567 lr: -0.000000 loss: 0.229502 ETA:
Progress: 100.0% words/sec/thread: 38567 lr: 0.000000 loss: 0.229502 ETA:
0h 0m

学習の計算が始まると学習時間の目安が表示されます。私の環境では1h37mと表示されました。実行処理中はファンも周りっぱなしで結構負担がかかっていそうですが『iStats』でチェックする限りは心配しすぎるほどでもないと思います。

fastText学習中のCPUを利用状況

fastText学習中のメモリを利用状況

iStatsの利用状況概要

iStatsの利用状況システム温度

『iStats』を使ったMacBook Proの管理方法は下記のページで解説しています。

学習の計算が完了すると『model_20181020.vec』と『model_20181020.bin』が出力されます。

バイナリファイルの生成

.vec(model_20181020.vec)はテキストファイルのためモデルのロードにかなりの時間がかかります。バイナリファイルであればインポート時間をかなり高速化することができますので.vecファイルから専用のバイナリファイル(.bin)を生成しておきましょう。

Note

fastTextから自動生成されているバイナリファイル『model_20181020.bin』はエンコード問題が発生したので利用しません

バイナリファイルに変換するため下記のコードを利用します。

import gensim


# model.vecをload
model = gensim.models.KeyedVectors.load_word2vec_format('model_20181020.vec', binary=False)

# バイナリファイルとして保存
model.save_word2vec_format("fasttext_wiki_20181020.bin", binary=True)

『fasttext_wiki_20181020.bin』が生成されましたらfastTextを使った学習モデルの生成は全て完了です。モデルを使ってテストしてみましょう。

fastTextの機械学習モデルで類語抽出や演算テスト

fastTextの学習モデルを使い類語の抽出や単語の足し引きなどの演算テストをおこないます。テストにはgensimとpprintが必要です。まだインストールが済んでいない方は先にインストール作業を済ませておいてください。

gensimのインストール

$ pip install gensim

pprintのインストール

$ pip install pprint

gensimのインストール方法は下記のページでも解説しています。

類語の抽出テスト

類語抽出のテスト用のコードは以下の通りです。

import gensim

import pprint

model = gensim.models.KeyedVectors.load_word2vec_format('./fastText_output/fasttext_wiki_20181020.bin', binary=True)

pprint.pprint(model.most_similar(positive=['SEO']))

類語の抽出にはmost_similar()関数を使います。most_similar()関数は学習モデル内で引数に渡した単語の単語ベクトルとより近い単語ベクトルをもつ単語を抽出してくれる関数です。

model.most_similar(positive=['類語判定させる単語'])

出力結果

類語判定させる単語に『SEO』を渡して抽出した結果です。

[('検索エンジン最適化', 0.7309184670448303),

('検索エンジンマーケティング', 0.7129291296005249),
('検索連動型広告', 0.673938512802124),
('Webマーケティング', 0.6733667850494385),
('インターネットマーケティング', 0.6725453734397888),
('WEO', 0.6664092540740967),
('サーチエンジンマーケティング', 0.6651182174682617),
('ウェブマーケティング', 0.6629313230514526),
('ブラックハットSEO', 0.6582387089729309),
('NAVERブログ', 0.6567591428756714)]

割と想定される結果が返っていると思います。

足し引きなどの演算テスト

単語ベクトルの足し算引き算の演算にもmost_similar()関数を利用します。テスト用のコードは以下の通りです。

import gensim

import pprint

model = gensim.models.KeyedVectors.load_word2vec_format('./fastText_output/fasttext_wiki_20181020.bin', binary=True)

pprint.pprint(model.most_similar(positive=["人間", "スマホ"]))

pprint.pprint(model.most_similar(positive=["人間"], negative=["感情"]))

単語ベクトルの足し算

単語ベクトルを足す場合はpositiveにリスト形式で渡します。

model.most_similar(positive=['足す単語1', '足す単語2'])

出力結果

『人間+スマホ』で単語ベクトルの足し算を行ってみました。

[('アンドロイドアプリ', 0.6502420902252197),

('ながらスマホ', 0.6464501023292542),
('アプリボワゼ', 0.6255478858947754),
('スマートアバター', 0.6236748695373535),
('千歌音', 0.622641384601593),
('スマートフォン', 0.6216732263565063),
('ネット社会', 0.618942379951477),
('バーチャルペット', 0.6157370805740356),
('ネットナビ', 0.6132873892784119),
('人間並', 0.6074398756027222)]

単語が『スマホ』でもそれなりに演算してくれています。『ながらスマホ』などが結果で返ってきているのが面白いですね。

単語ベクトルの引き算

単語ベクトルの引き算を行う場合はnegativeの中に引きたい単語を渡すことで演算されます。

pprint.pprint(model.most_similar(positive=['足す単語'], negative=['引く単語']))

出力結果

『人間−感情』で単語ベクトルの引き算を行ってみました。

[('生物', 0.33645519614219666),

('小型ロボット', 0.3321981430053711),
('人類', 0.331537127494812),
('生き物', 0.32656198740005493),
('知的生命体', 0.3200429081916809),
('動物', 0.31320303678512573),
('獣', 0.3043139576911926),
('喰う', 0.2999400794506073),
('人間社会', 0.29950663447380066),
('生きもの', 0.29651132225990295)]

何となくイメージしやすい演算結果が返ってきています。『人間社会』と言う結果は少し悲しくなりますが・・・。

今日のdot

上記で紹介した以外にも様々な演算テストを行ってみましたが結論としては学習前のコーパスの前処理をもっとしっかりと行う必要がありそうです。前処理によって学習結果にもたらす影響は大きそうです。

あと『fastText』の計算速度はWord2Vecに比べてかなり早いといえます。前処理を複数パターンテストして機械学習を行っても十分に耐えられる速度と言えるでしょう。

今回のfastText』を利用した自然言語機械学習モデル生成手順を元に、前処理を行ったテスト結果もまた後日公開します。