SudachiPyで分かち書きしたきのメモ

# はじめに

SudachiPyで文章を分かち書きしたいことがあったので備忘録も兼ねてメモする。

# 環境

Google ColabのPython3ノートブックを使用。
今回はMeCabとSudachiPyを使うので、2つのライブラリを以下のようにインストールした。

### MeCabのインストール

Google ColabにMeCabをインストールするときにはこちら[^1]を参考にした。
以下のコマンドをコードセルに書いて実行することでインストールは完了。なお、Google Colabとの接続が切れるとその都度コマンドを売ってインストールする必要があった。

```
!apt install aptitude
!aptitude install mecab libmecab-dev mecab-ipadic-utf8 git make curl xz-utils file -y 
!pip install mecab-python3==0.7
```

### SudachiPyのインストール

SudachiPyはライブラリのページ[^2]に沿って、以下のコマンドでインストールした。

```py
!pip install SudachiPy
!pip install https://object-storage.tyo2.conoha.io/v1/nc_2520839e1f9641b08211a5c85243124a/sudachi/SudachiDict_core-20190927.tar.gz
```

# MeCabを使った分かち書き

まず最初にMeCabを使って文章を分かち書きしてみる。
下のように`parse`の引数に文字列を渡すだけでよい。

```py
import MeCab

mecab = MeCab.Tagger("-Owakati")
sample = "SudachiPyで分かち書きしたときのメモ" 
mecab.parse( sample )
# 'SudachiPy で 分かち書き し た とき の メモ \n'
```

このように文章を簡単に分かち書きすることができる。
同様な処理をSudachiPyで行う。


# SudachiPyを使った分かち書き

SudachiPyの場合もまず最初にライブラリをインポート。

```py

from sudachipy import tokenizer 
from sudachipy import dictionary
tokenizer_obj = dictionary.Dictionary().create()
```
SudachiPyの場合は、文字列分割のモードがA、B、Cの3種類ある。
例えば、「国家公務員」をtokenizeすると、それぞれのモードで単語の粒度が異なるような結果を得る。

```py
mode = tokenizer.Tokenizer.SplitMode.C
print( [m.surface() for m in tokenizer_obj.tokenize( sample, mode)] )
# ['国家公務員']

mode = tokenizer.Tokenizer.SplitMode.B
print( [m.surface() for m in tokenizer_obj.tokenize(sample, mode)])
#['国家', '公務員']

mode = tokenizer.Tokenizer.SplitMode.A
print( [m.surface() for m in tokenizer_obj.tokenize(sample, mode)])
#['国家', '公務', '員']
```
Cモードが単語を一番長い単位に分割し、Aモードが一番短い単位に分割する。

SudachiPyの場合、`tokenize`した結果は、Morpheme（モーフィーム；形態素）のリストで返される。`surface()`という関数で、分割した文字列を得ることができる。
ただし、このようにリストで返ってくるので、MeCabと同様な結果を得るために`wakati`関数を作った。

```py
def wakati( sentence ):
  mode = tokenizer.Tokenizer.SplitMode.C
  return " ".join( [m.surface() for m in tokenizer_obj.tokenize(sentence, mode)] )

sample = "SudachiPyで分かち書きしたときのメモ"
print( wakati( sample ) )
# SudachiPy で 分かち書き し た とき の メモ
```

これで確かにMeCabと同様な結果を得ることができた。

### 正規化などのお話

SudachiPyではGitHubに記載があるように、MeCabと違って表現を正規化することで表記ずれを直すことができる。一方で、辞書表記の形にも変換できるので、何が違うのかなと思い、その2つの表現方法について簡単に調べてみた。

上で述べた関数`wakati`の`normalized_form()`版と`dictionary_form()`版を作った。プログラムは次の通り。

```py
def wakati_normalized( sentence ):
  mode = tokenizer.Tokenizer.SplitMode.C
  return " ".join( [m.normalized_form() for m in tokenizer_obj.tokenize(sentence, mode)] )

def wakati_dictionary( sentence ):
  mode = tokenizer.Tokenizer.SplitMode.C
  return " ".join( [m.dictionary_form() for m in tokenizer_obj.tokenize(sentence, mode)] )
```

この関数で文章を分かち書きしたときの結果は次の通り。

```py
sample = "SudachiPyで分かち書きしたときのメモ"

print( "Normalized ==> " + wakati_normalized(sample) )
print( "Dictionary ==> " + wakati_dictionary(sample) )
# Normalized ==> sudachipy で 分かち書き 為る た 時 の メモ
# Dictionary ==> sudachipy で 分かち書き する た とき の メモ

sample = "SudachiPyでわかちがきしたときのめも"

print( "Normalized ==> " + wakati_normalized(sample) )
print( "Dictionary ==> " + wakati_dictionary(sample) )
# Normalized ==> sudachipy で 分かち書き 為る た と 木の芽 も
# Dictionary ==> sudachipy で わかちがき する た と きのめ も
```
これから分かったことは

- 両者とも「SudachiPy」のような英字は全部小文字に変換される。
- `dictionary_form()`の場合、入力文章が平仮名だと、出力も平仮名というように、入力の形と等しいのに対して、`noralized_form()`の場合は、出力は漢字を用いる。

といったところだろうか。
類似文章を見つけたいような時には、`normalized_form()`を使った方が良さそうかなと思うが、用途に応じて使い分けるのが良さそう。

# まとめ
SudachiPyを使った分かち書き処理をやってみた。モードや表記方法については、用途に応じて使い分けるのが良さそう。

P.S.
最初はiPadのみを使って、ブラウザだけでコーディングと記事作成を行ってみよう！と思っていたが、iPadだとGoogle Colabのコードや出力結果をそのままコピーできず、結局PCを使った。。PC使わずにうまくできないものだろうか...


[^1]: https://qiita.com/pytry3g/items/897ae738b8fbd3ae7893
[^2]: https://github.com/WorksApplications/SudachiPy