VibratoをWindows・Pythonで動かす 高速な形態素解析器Vibrato。 MeCabと同じ解析結果でMeCabの2倍速いらしい。
Windows・Pythonで使用している例が見つからなかったので実験。 簡単に動いた。
加えて速度比較。 MeCabより速いことは明らかなので、普段よく使うGinzaと比較。
結果、 超速い。
1. 実験準備 Vibratoを動かすためには、
辞書ファイルのダウンロード ライブラリのインストール が必要。
1.1. 辞書ファイルダウンロード・展開 事前に辞書ファイルをダウンロードして手元に準備する必要がある。
https://github.com/daac-tools/vibrato/releases
にあるipadic-mecab-2_7_0.tar.xz
をダウンロード。
最近はWindowsでもtarが使えるので以下コマンドで展開。
1 tar -xJf ipadic-mecab-2_7_0.tar.xz
できない。
1 tar: Error opening archive: Can't initialize filter; unable to run program "xz -d -qq"
xz展開用のプログラムが無いらしい、面倒なので7zipで展開する。 GUI最強。
展開されたipadic-mecab-2_7_0の中にあるsystem.dic.zst(7.67MB)が辞書ファイル。
1.2. ライブラリインストール Anacondaにvibratoが無かったのでpipでインストール
1 pip install vibrato zstandard
2. 実験結果 VibratoとGinzaの性能を比較。 コードは後に記す。
2.1. 分かち書き結果比較 以下の10テキストを分かち書き。 VibratoとGinzaのそれぞれの結果を比較。
1 2 3 4 5 6 7 8 9 10 "青眼の白龍", "復讐のソード・ストーカー", "ブラック・ローズ・ドラゴン", "ロード・オブ・ドラゴン-ドラゴンの支配者-", "人造人間-サイコ・ショッカー", "大盤振舞侍", "ブラック・マジシャン・ガール", "ファラオのしもべ", "ラーの翼神竜", "オシリスの天空竜",
1 2 3 4 5 6 7 8 9 10 ['青眼', 'の', '白', '龍'] ['復讐', 'の', 'ソード・ストーカー'] ['ブラック', '・', 'ローズ', '・', 'ドラゴン'] ['ロード', '・', 'オブ', '・', 'ドラゴン', '-', 'ドラゴン', 'の', '支配', '者', '-'] ['人造', '人間', '-', 'サイコ・ショッカー'] ['大盤振舞', '侍'] ['ブラック・マジシャン・ガール'] ['ファ', 'ラオ', 'の', 'しも', 'べ'] ['ラー', 'の', '翼', '神', '竜'] ['オシ', 'リス', 'の', '天空', '竜']
1 2 3 4 5 6 7 8 9 10 ['青眼', 'の', '白龍'] ['復讐', 'の', 'ソード', '・', 'ストーカー'] ['ブラック', '・', 'ローズ', '・', 'ドラゴン'] ['ロード', '・', 'オブ', '・', 'ドラゴン', '-', 'ドラゴン', 'の', '支配者', '-'] ['人造', '人間', '-', 'サイコ', '・', 'ショッカー'] ['大盤振舞', '侍'] ['ブラック', '・', 'マジシャン', '・', 'ガール'] ['ファラオ', 'の', 'しもべ'] ['ラー', 'の', '翼', '神竜'] ['オシリス', 'の', '天空', '竜']
結果に違いはあるが良し悪しは無いように思う。
2.2. 速度比較 分かち書きがいくら早くてもライブラリ準備に時間がかかったら意味がないため、
インポート時間(import 〇〇 にかかる時間) モデル読み込み時間 分かち書き時間(さっきの遊戯王カード名を各100回分かち書き) の3つに分けて計測。
ライブラリ インポート時間(秒) モデル読み込み時間(秒) 分かち書き時間(秒) Vibrato 0.039 0.213 0.005 Ginza 1.320 0.804 9.245
あまりにも差が大きくて不安になる。 Ginzaがimport spacy
の処理をしている間に、 Vibratoはインポート、辞書読み込み、分かち書きを全て終えてしまった。
(Ginzaはspacyごとインストールしているので分かち書き以外の機能もたくさんある。)
3. まとめ Vibrato優秀。 Ginzaは高機能で便利だけど重い。
使うのが簡単だからGinzaばかり使っていたが乗り換える。
4. コード 実験に使用したコード。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 import time # ライブラリ読み込み時間の計測 start = time.time() import vibrato import zstandard print(f"Import Time: {time.time() - start}") # モデル読み込み時間の計測 start = time.time() dctx = zstandard.ZstdDecompressor() with open('ipadic-mecab-2_7_0/system.dic.zst', 'rb') as fp: with dctx.stream_reader(fp) as dict_reader: tokenizer = vibrato.Vibrato(dict_reader.read()) print(f"Load Time: {time.time() - start}") textlist = [ # 分かち書きテスト用のテキスト "青眼の白龍", "復讐のソード・ストーカー", "ブラック・ローズ・ドラゴン", "ロード・オブ・ドラゴン-ドラゴンの支配者-", "人造人間-サイコ・ショッカー", "大盤振舞侍", "ブラック・マジシャン・ガール", "ファラオのしもべ", "ラーの翼神竜", "オシリスの天空竜", ] # 分かち書き時間の計測 start = time.time() for i in range(100): for text in textlist: tokens = tokenizer.tokenize(text) tokens = [token.surface() for token in tokens] # print(tokens) print(f"Tokenize Time: {time.time() - start}")
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import time # ライブラリ読み込み時間の計測 start = time.time() import spacy print(f"Import Time: {time.time() - start}") # モデル読み込み時間の計測 start = time.time() nlp = spacy.load('ja_ginza') print(f"Load Time: {time.time() - start}") textlist = [ # 分かち書きテスト用のテキスト "青眼の白龍", "復讐のソード・ストーカー", "ブラック・ローズ・ドラゴン", "ロード・オブ・ドラゴン-ドラゴンの支配者-", "人造人間-サイコ・ショッカー", "大盤振舞侍", "ブラック・マジシャン・ガール", "ファラオのしもべ", "ラーの翼神竜", "オシリスの天空竜", ] # 分かち書き時間の計測 start = time.time() for i in range(100): for text in textlist: doc = nlp(text) tokens = [token.text for token in doc] # print(tokens) print(f"Tokenize Time: {time.time() - start}")
5. 参考 https://github.com/daac-tools/vibrato https://github.com/daac-tools/python-vibrato