LoginSignup
7
6

More than 3 years have passed since last update.

Python で分かち書き の速度比較 / janome, sudachi, ginza, mecab, fugashi, tinysegmenter

Last updated at Posted at 2020-06-07

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 ってインストールが面倒だと思い込んでた

以上

7
6
12

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
6