け日記

最近はPythonでいろいろやってます

Pythonで形態素解析器Sudachiを使う (SudachiPy)

仕事でSudachiをお試しする機会がありましたので、基本的な使い方を備忘録として整理しておきます。

Sudachi

Sudachiはワークスアプリケーションズさんで開発されたOSSで、日本語に特化した形態素解析器です。分かち書き・品詞付け・正規化を行います。

github.com

大きな特徴は3つです。特に3番目は実務上もどかしい問題です。例えば"焼き肉"と"焼肉"、"醤油"と"しょう油"といった表現の違いを、Sudachiで正規化することで同じ単語であると認識できるようになります。

  • UniDicとNeologdがベースとした豊富な語彙
  • 分割単位を3段階 (辞書単位から固有表現単位まで) から選択可能
  • 送り仮名や字種の違いなども正規化

SudachiPy

SudachiをPythonから使うためのライブラリとしてSudachiPyも開発されています (同じくワークスアプリケーションズさん主体のOSS) 。今回もこれを使います。

github.com

インストール

SudachiPyのインストール -> 辞書のダウンロードと配置 の順番で行います (なおPythonは3.6です) 。

最初にSudachiPyをインストールします。このときインストールしたパスを確認しておきます。

$ pip install -e git+git://github.com/WorksApplications/SudachiPy@develop#egg=SudachiPy
$ pip list | grep sudachipy
SudachiPy                          0.1.0     /Users/ohke/src/sudachipy

次にSudachiのレポジトリから辞書をダウンロードして、SudachiPyのインストールディレクトリに配置します。

  • 上で確認しましたインストールディレクトリ直下のresources配下に"system.dic"に配置します
    • /Users/ohke/src/sudachipy/resources/system.dic
  • 辞書にはcoreとfullの2つがあり、fullの方には雑多な固有表現まで含まれます
    • 今回はcoreを使いますが、fullも同じ手順でOKです
$ wget https://github.com/WorksApplications/Sudachi/releases/download/v0.1.1/sudachi-0.1.1-dictionary-core.zip
$ unzip sudachi-0.1.1-dictionary-core.zip
$ mv system_core.dic /Users/ohke/src/sudachipy/resources/system.dic
$ ls /Users/ohke/src/sudachipy/resources/
char.def        rewrite.def     sudachi.json    system.dic      unk.def

ここまでで準備OKです。

コマンドラインから使う

まずコマンドラインから使ってみます。sudachipyで起動します。

  • -mで分割モード (A, B, C) を指定できます
    • Aは"スカイ"と"ツリー"に名詞として分割されましたが、Cは"スカイツリー"という1つの固有名詞として分割されていることがわかります
$ sudachipy -m A -a
友人・我孫子と東京スカイツリーへ走って向かった。
友人    名詞,普通名詞,一般,*,*,*        友人    友人    ユウジン        0
・      補助記号,一般,*,*,*,*   ・      ・              0
我孫子  名詞,固有名詞,地名,一般,*,*     我孫子  我孫子  アビコ  0
と      助詞,格助詞,*,*,*,*     と      と      ト      0
スカイ  名詞,普通名詞,一般,*,*,*        スカイ  スカイ          0
ツリー  名詞,普通名詞,一般,*,*,*        ツリー  ツリー          0
へ      助詞,格助詞,*,*,*,*     へ      へ      ヘ      0
走っ    動詞,一般,*,*,五段-ラ行,連用形-促音便   走る    走る    ハシッ  0
て      助詞,接続助詞,*,*,*,*   て      て      テ      0
向かっ  動詞,一般,*,*,五段-ワア行,連用形-促音便 向かう  向かう  ムカッ  0
た      助動詞,*,*,*,助動詞-タ,終止形-一般      た      た      タ      0
。      補助記号,句点,*,*,*,*   。      。              0
EOS

$ sudachipy -m C -a
友人・我孫子とスカイツリーへ走って向かった。
友人    名詞,普通名詞,一般,*,*,*        友人    友人    ユウジン        0
・      補助記号,一般,*,*,*,*   ・      ・              0
我孫子  名詞,固有名詞,地名,一般,*,*     我孫子  我孫子  アビコ  0
と      助詞,格助詞,*,*,*,*     と      と      ト      0
スカイツリー    名詞,固有名詞,一般,*,*,*        スカイツリー    スカイツリー            0
へ      助詞,格助詞,*,*,*,*     へ      へ      ヘ      0
走っ    動詞,一般,*,*,五段-ラ行,連用形-促音便   走る    走る    ハシッ  0
て      助詞,接続助詞,*,*,*,*   て      て      テ      0
向かっ  動詞,一般,*,*,五段-ワア行,連用形-促音便 向かう  向かう  ムカッ  0
た      助動詞,*,*,*,助動詞-タ,終止形-一般      た      た      タ      0
。      補助記号,句点,*,*,*,*   。      。              0
EOS

Pythonコードから使う

PythonコードからSudachiPyを使って形態素解析します。

最初にconfig.SETTINGFILEの設定ファイルをJSONでロードします。

  • このファイルがSudachiPyのデフォルトの設定になります
    • このJSONを変更することで、デフォルトの設定からカスタマイズできます
import json
from sudachipy import config
from sudachipy import dictionary

print(config.SETTINGFILE)
# /Users/ohke/src/sudachipy/sudachipy/../resources/sudachi.json

with open(config.SETTINGFILE, 'r', encoding='utf-8') as f:
    settings = json.load(f)
    
print(settings)
# {'systemDict': 'system.dic',
#  'characterDefinitionFile': 'char.def',
#  'inputTextPlugin': [{'class': 'com.worksap.nlp.sudachi.DefaultInputTextPlugin'}],
#  'oovProviderPlugin': [{'class': 'com.worksap.nlp.sudachi.MeCabOovProviderPlugin',
#    'charDef': 'char.def',
#    'unkDef': 'unk.def'},
#   {'class': 'com.worksap.nlp.sudachi.SimpleOovProviderPlugin',
#    'oovPOS': ['補助記号', '一般', '*', '*', '*', '*'],
#    'leftId': 5968,
#    'rightId': 5968,
#    'cost': 3857}],
#  'pathRewritePlugin': [{'class': 'com.worksap.nlp.sudachi.JoinNumericPlugin',
#    'joinKanjiNumeric': True},
#   {'class': 'com.worksap.nlp.sudachi.JoinKatakanaOovPlugin',
#    'oovPOS': ['名詞', '普通名詞', '一般', '*', '*', '*']}]}

そして上の設定を反映したトークナイザを生成し、tokenizeメソッドを呼び出すことで、形態素解析できます。

  • コマンドラインと同様に、tokenizer.Tokenizer.SplitModeの1つを引数に渡すことで分割モードを指定できます (ここではCを使ってます)
  • 結果はMorphemeのリストとなっており、表層形 (surface()) 、品詞 (part_of_speech()) 、読み (reading_form()) 、正規化した表現 (normalized_form()) を取得できます
from sudachipy import tokenizer

tokenizer_obj = dictionary.Dictionary(settings).create()
print(type(tokenizer_obj))
# <class 'sudachipy.tokenizer.Tokenizer'>

text = '友人・我孫子とスカイツリーでスパゲティを食った。'

tokens = tokenizer_obj.tokenize(tokenizer.Tokenizer.SplitMode.C, text)
print(type(tokens))
# <class 'sudachipy.morphemelist.MorphemeList'>

for t in tokens:
    print(t.surface(), t.part_of_speech(), t.reading_form(), t.normalized_form())

形態素解析後の結果を見ると以下のようになります。品詞はリストになっていること、"スパゲティ" -> "スパゲッティ" と正規化されていることに注目してください。

友人 ['名詞', '普通名詞', '一般', '*', '*', '*'] ユウジン 友人
・ ['補助記号', '一般', '*', '*', '*', '*']  ・
我孫子 ['名詞', '固有名詞', '地名', '一般', '*', '*'] アビコ 我孫子
と ['助詞', '格助詞', '*', '*', '*', '*'] ト と
スカイツリー ['名詞', '固有名詞', '一般', '*', '*', '*']  スカイツリー
で ['助詞', '格助詞', '*', '*', '*', '*'] デ で
スパゲティ ['名詞', '普通名詞', '一般', '*', '*', '*']  スパゲッティ
を ['助詞', '格助詞', '*', '*', '*', '*'] ヲ を
食っ ['動詞', '一般', '*', '*', '五段-ワア行', '連用形-促音便'] クッ 食う
た ['助動詞', '*', '*', '*', '助動詞-タ', '終止形-一般'] タ た
。 ['補助記号', '句点', '*', '*', '*', '*']  。

まとめ

SudachiをPythonから使って形態素解析を行いました。