Python で形態素解析 の速度比較
- シンプルに分かち書きだけを期待して
- pip でサクッとインストール終わるヤツ
- 環境
docker pull python:3-slim
比較対象
- janome
- sudachi
- ginza
- mecab
- fugashi
- tinysegmenter
準備
pip install janome
pip install sudachipy
pip install ginza sudachidict_core
pip install mecab-python3
pip install fugashi[unidic-lite]
pip install tinysegmenter
参考:pip freeze
reqirements.txt
blis==0.4.1
catalogue==1.0.0
certifi==2020.4.5.2
chardet==3.0.4
cymem==2.0.3
Cython==0.29.19
dartsclone==0.9.0
fugashi==0.2.3
ginza==3.1.2
idna==2.9
ja-ginza==3.1.0
ja-ginza-dict==3.1.0
Janome==0.3.10
mecab-python3==0.996.5
murmurhash==1.0.2
numpy==1.18.5
plac==1.1.3
preshed==3.0.2
requests==2.23.0
sortedcontainers==2.1.0
spacy==2.2.4
srsly==1.0.2
SudachiDict-core==20200330
SudachiPy==0.4.5
thinc==7.4.0
tinysegmenter==0.4
tqdm==4.46.1
unidic-lite==1.0.6
urllib3==1.25.9
wasabi==0.6.0
コードと実行結果
コードを見る
ma.py
import time
from janome.tokenizer import Tokenizer
from sudachipy import dictionary
import spacy
from MeCab import Tagger as mecab
from fugashi import Tagger as fugashi
import tinysegmenter
def use_janome(s, cache=None):
t = Tokenizer() if cache is None else cache
[token.surface for token in t.tokenize(s)]
return t
def use_sudachi(s, cache=None):
t = dictionary.Dictionary().create() if cache is None else cache
[token.surface() for token in t.tokenize(s)]
return t
def use_ginza(s, cache=None):
t = spacy.load('ja_ginza') if cache is None else cache
[token for token in t(s)]
return t
def use_mecab(s, cache=None):
t = mecab('-Owakati')
[token for token in t.parse(s).split(' ')]
return t
def use_fugashi(s, cache=None):
t = fugashi('-Owakati')
t(s)
return t
def use_tinysegmenter(s, cache=None):
t = tinysegmenter.TinySegmenter()
t.tokenize(s)
return t
def stopwatch(func, times=100):
# 桃太郎 芥川龍之介 https://www.aozora.gr.jp/cards/000879/card100.html
s = 'むかし、むかし、大むかし、ある深い山の奥に大きい桃《もも》の木が一本あった。大きいとだけではいい足りないかも知れない。この桃の枝は雲の上にひろがり、この桃の根は大地《だいち》の底の黄泉《よみ》の国にさえ及んでいた。何でも天地|開闢《かいびゃく》の頃《ころ》おい、伊弉諾《いざなぎ》の尊《みこと》は黄最津平阪《よもつひらさか》に八《やっ》つの雷《いかずち》を却《しりぞ》けるため、桃の実《み》を礫《つぶて》に打ったという、――その神代《かみよ》の桃の実はこの木の枝になっていたのである。'
time_s = time.perf_counter()
cache = None
for i in range(times):
cache = func(s, cache)
time_e = time.perf_counter()
return time_e - time_s
def main():
d = {
'janome': stopwatch(use_janome),
'sudachi': stopwatch(use_sudachi),
'ginza': stopwatch(use_ginza),
'mecab': stopwatch(use_mecab),
'fugashi': stopwatch(use_fugashi),
'tinysegmenter': stopwatch(use_tinysegmenter)
}
d = sorted(d.items(), key=lambda x:x[1])
print('\n'.join(map(str, d)))
if __name__ == '__main__':
main()
結果
('mecab', 0.09558620000007068)
('fugashi', 0.1353556000003664)
('tinysegmenter', 0.655696199999511)
('janome', 3.070499899999959)
('sudachi', 5.18910169999981)
('ginza', 9.577376000000186)
感想
- そら MeCab は Python実装でなくネイティブなんで 圧倒的 、知ってた
- 便利とか精度とかに応じて重くなるだろうと思ってた
- tinysegmenter は目的が分かち書き特化なので Python実装だけど早い
- janome の速さは期待通り、sudachi, ginza と差があるもんなんですね
- 初めて速度比較した
- はじめ tokenizer 初期化をループ中にいれちゃってひどかった
- nagisa, UniDic2UD はインストールしんどいので今回不採用
- (コメントありがとうございます) Windows を主戦場にしてたら MeCab ってインストールが面倒だと思い込んでた
以上