Movatterモバイル変換


[0]ホーム

URL:


LoginSignup
144

Go to list of users who liked

124

Share on X(Twitter)

Share on Facebook

Add to Hatena Bookmark

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

PythonでのMeCabを速くするtips

Last updated atPosted at 2015-12-16

ちゃお...Python Advent Calendar 2015 18日目の記事です...

Pythonといったらデータサイエンスに強いし、データサイエンスといったら形態素解析が必要になることがあるし、形態素解析といったらMeCabだし――ということで、今回はPythonでのMeCabの処理を少しでも速くする豆知識を共有したいと思います!

parseToNodeを捨てよ parseを使おう

MeCabの解析結果を得るにはparseparseToNodeの2つのメソッドがあります。

わたしはもっぱらparseToNode使ってたのですが、なんか遅いなーって思って、本当に遅いのか確かめるために処理時間測ってみました。現実的な設定でやった方が実用的だと思ったので、今回は夢野久作のドグラマグラから名詞を抽出することにします。

コード

importMeCabtagger=MeCab.Tagger('-d /usr/local/lib/mecab/dic/ipadic')defpreprocessing(sentence):returnsentence.rstrip()defextract_noun_by_parse(path):withopen(path)asfd:nouns=[]forsentenceinmap(preprocessing,fd):forchunkintagger.parse(sentence).splitlines()[:-1]:(surface,feature)=chunk.split('\t')iffeature.startswith('名詞'):nouns.append(surface)returnnounsdefextract_noun_by_parsetonode(path):withopen(path)asfd:nouns=[]forsentenceinmap(preprocessing,fd):node=tagger.parseToNode(sentence)whilenode:ifnode.feature.startswith('名詞'):nouns.append(node.surface)node=node.nextreturnnouns

結果

  • Py2: Python 2.7.10
  • Py3: Python 3.5.0
  • ASIS:MeCabリポジトリそのまま
  • NEW SWIG: SWIG 3.0.7でMeCabリポジトリのラッパーをつくりなおした場合
  • mecab-python3: PyPIにあるmecab-python3
parseparseToNode
Py2, ASIS531 ms642 ms
Py2, NEW SWIG604 ms630 ms
Py2, mecab-python3547 ms652 ms
Py3, ASIS673 ms1610 ms
Py3, NEW SWIG684 ms1640 ms
Py3, mecab-python3654 ms1610 ms

Python 3のparseToNodeだけ明らかに遅い......!?

原因

詳細なプロファイルを取ってみると、

         1362455 function calls in 2.177 seconds   Ordered by: internal time   ncalls  tottime  percall  cumtime  percall filename:lineno(function)        1    1.162    1.162    2.174    2.174 <ipython-input-5-e12642d808e1>:1(extract_noun_by_parsetonode)   313688    0.372    0.000    0.372    0.000 MeCab.py:35(_swig_setattr_nondynamic)     3416    0.251    0.000    0.262    0.000 {built-in method _MeCab.Tagger_parseToNode}   313688    0.131    0.000    0.629    0.000 MeCab.py:126(<lambda>)   313688    0.126    0.000    0.498    0.000 MeCab.py:48(_swig_setattr)以下省略...

parseToNodeは形態素ごとにNodeインスタンスの生成時にNodeの全ての要素をあらかじめ取得するので、そのときのオーバーヘッドがだいぶ大きいようです。

結論

Python 3でMeCab使うときはparseToNodeじゃなくてparseを使いましょう (バッドノウハウだけど......)

joblibで並列化

さらに速くしたいとなったら並列化が頭をよぎりますよね。でも並列化っていうととっつきにくいイメージがあります。途中で失敗したときにうまくプロセスが死んでくれなかったり、途中でやめたいって思ってもKeyBoardInterruptが効かなかったり、データの分割数どれくらいがわからなかったり、今どれくらい処理してるのか経過わかんなかったり。。。

そこで、scikit-learnも採用しているjoblibというものを使います。joblibはいろいろできるんですけど、ここでは並列処理のjoblib.Parralelに着目します。これはざっくりいうとPython標準のmultiprocessingthreadingを使いやすくしたものです。たとえば、各プロセスにどれくらいの粒度でデータを分割して渡すかを自動で調整したり、KeyBoardInterruptでちゃんと終わってくれたり、途中経過を標準出力とかに流したりできます。かゆいところに手が届く!これなら並列化こわくない!💪😤

比較

並列化するとどれくらい速くなるか比較するために、またドグラマグラから名詞抽出しました。ボリューム大きめのテキストでやった方がわかりやすいので今回は長さを10倍してます。

コード:https://gist.github.com/ikegami-yukino/68a741ef854de68871cc#file-asis_vs_joblib-ipynb

defextract_noun(sentence):nouns=[]sentence=preprocessing(sentence)forchunkintagger.parse(sentence).splitlines()[:-1]:(surface,feature)=chunk.split('\t')iffeature.startswith('名詞'):nouns.append(surface)returnnouns# 並列なし%timeitnouns=[extract_noun(sentence)forsentenceindoc.splitlines()]# 並列ありfromjoblibimportParallel,delayed%timeitnouns=Parallel(n_jobs=-1,pre_dispatch='all')(delayed(extract_noun)(sentence)forsentenceindoc.splitlines())

結果

並列なし1 loops, best of 3: 6.78 s per loop並列あり1 loops, best of 3: 3.72 s per loop

1.8倍くらい速くなりました!

ついでに並列化なしのparseToNodeで同じデータを処理させると

1 loops, best of 3: 1min 18s per loop

並列ありのparseと比べて20倍遅いです😱

総括

Python3でMeCabを使うときはparseToNodeを使うとオーバーヘッドが大きいのでparseを使った方が速く処理できます。さらに並列化するともっと処理時間が短くなります。ワーストケース (Python 3で並列なしでparseToNodeで名詞抽出する場合) 78秒かかる処理が、今回紹介したやり方では3.72秒となり、およそ20倍の差がつきました。小規模のテキストを扱い場合なら誤差の内かもしれませんが、ちょっとした規模の量を処理するときなんかに恩恵を受けると思います^^

144

Go to list of users who liked

124
5

Go to list of comments

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
144

Go to list of users who liked

124

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?


[8]ページ先頭

©2009-2025 Movatter.jp