形態素解析器「sudachi」を使ってみた


自然言語処理として今までmecabやjuman++を使って来ましたが、「sudachi」が良いという話を聞いて一回使ってみました。


日本語の文章の分け方をショート・ミドル・ロングといった形で指定して分けることが出来るのが特徴です。（特徴は他にもあると思いますが…）

引用
>Sudachi provides three modes of splitting. In A mode, texts are divided into the shortest units equivalent to the UniDic short unit. In C mode, it extracts named entities. In B mode, into the middle units.
A：カンヌ/国際/映画/祭
B：カンヌ/国際/映画祭
C：カンヌ国際映画祭

詳しくはこちら参照してください
https://github.com/WorksApplications/Sudachi
http://www.lrec-conf.org/proceedings/lrec2018/summaries/8884.html


#sudachiPyのインストール
では実際に使ってみます。私の環境は以下の通りです。

```環境
macOS High Sierra 10.13
Python 3.6.5
```

sudachiPyのインストールは下記のサイトの方法に従って行えば簡単に出来ました。サイトにも記載されていますが、最初は辞書が入っていない状態ですので別途ダウンロードして```resources```ディレクトリに名前を```system.dic```として入れておくことが必要です。

SudachiPy
https://github.com/WorksApplications/SudachiPy

#使ってみる
元々juman++を使っていましたので、両方の形態素解析器を使えるようにしています。python初心者ですのでお恥ずかしいソースですいません。
処理スピードはjumann++は遅いと言われていた通り遅いのですが、sudachiは早かったです。（感覚的に）


```
#テキストデータからリスト型の形態素解析データを作成する
import pandas as pd
from tqdm import tqdm_notebook as tqdm
#Juman++
from pyknp import Jumanpp
#sudachi
import json
from sudachipy import tokenizer
from sudachipy import dictionary
from sudachipy import config

#オブジェクトを作る
jumanpp = Jumanpp()
with open(config.SETTINGFILE, "r", encoding="utf-8") as f:
    settings = json.load(f)
tokenizer_obj = dictionary.Dictionary(settings).create()

#csvファイルに読み込んで一旦データフレームに入れる
file_df = pd.read_csv("hoge.csv")
wakati_list=[]


def wakati_by_jumanpp(text):
    """
    juman++を使った分かち書き
    """
    result = jumanpp.analysis(text)
    word_list = []
    for mrph in result.mrph_list():
        hinsi = mrph.hinsi
        if hinsi in  ["名詞", "動詞", "形容詞"]:  # 対象とする品詞
            word = mrph.midasi
            word_list.append(word)
    return " ".join(word_list) #スペースで繋げていく


def wakati_by_sudachi(text):
    """
    sudachiを使った分かち書き
    """
    mode = tokenizer.Tokenizer.SplitMode.C #モードCの一番長い形で分ける
    results =[m.surface() for m in tokenizer_obj.tokenize(mode, text)]
    word_list = []
    for mrph in results:
        if not (mrph == ""): #何故か分かち書きの結果として空白データ（''）ができたための省く処理
            seikika = tokenizer_obj.tokenize(mode,mrph)[0].normalized_form() #正規化（標準化？）してなるべく言葉の揺れを無くす　e.g. 打込む → 打ち込む かつ丼 → カツ丼
            hinsi = tokenizer_obj.tokenize(mode,seikika)[0].part_of_speech()[0]
            if hinsi in  ["名詞", "動詞", "形容詞"]:  # 対象とする品詞を指定
                word = tokenizer_obj.tokenize(mode,seikika)[0].dictionary_form()
                word_list.append(word)
    return " ".join(word_list) #スペースで繋げていく

#データをそれぞれ分かち書きしていく
for lines in tqdm(file_df["___テキストデータが入っているカラム__"]):
    #wakati_list.append(wakati_by_jumanpp(lines)) # 分かち書きはjuman++を利用したい時はこちら
    wakati_list.append(wakati_by_sudachi(lines)) # 形態素解析はsudachiを利用したい時はこちら
    
#分かち書きしたデータは元のcsvファイルにくっ付ける形で保存
file_df['wakati'] = wakati_list
file_df.to_csv("hoge_wakati.csv")
```

#結果
分かち書きした結果を見てみます。何個か違いが出た単語を挙げます。
なお、sudachiのみ正規化などをして単語を一定の形に成形しています。

<table>
	<tr>
		<td>元の単語</td>
		<td>sudachi(modeC)</td>
		<td>juman++</td>
	</tr>
	<tr>
		<td>オールインワン</td>
		<td>オール イン ワン</td>
		<td>オールインワン</td>
	</tr>
	<tr>
		<td>差し込み</td>
		<td>差し込み</td>
		<td>差 込</td>
	</tr>
	<tr>
		<td>取扱説明書</td>
		<td>取り扱い 説明書</td>
		<td>取扱 説明 書</td>
	</tr>
</table>

オールインワンなんかはモードCなら分かれないかなと思うのですが、分れた形になりました。全体的に1文字の漢字に分れているものがsudachiは少なかったのでなかなか良い気がします。（個人の感想です）

<HR>
元々、mecabを含め形態素解析はやり始めたばかりですので、何が良いとか正直わかっておりませんが、sudachiは使いやすく早かったし単語も10年間は更新するとも記載がありましたのでこれを使ってword2vecなどをやっていきたいと思います。