Python & Sudachiで日本語の形態素解析してみよう

  • #技術ブログ 

皆様、2か月半ぶりです。
コロナの影響により、在宅にてブログを更新しております、うえピーです。

今回はNLTK使って、何を解析しようかな~。
愛読書の「入門 自然言語処理」を眺めながら、
・・・・・

あれ?!ない!

あっ、そっかここ自宅じゃん!!
あちゃー、会社の本棚に置いてあるんだった。

ならば、ということで今回は、いつ英語から日本語に切り替えようかなーと思っていたこともあったので、日本語の解析に切り替えまーす。
早速、使うライブラリをGoogle先生に決めてもらいましょう。
「日本語形態素解析」で検索と。

検索トップは・・・
2019年末版 形態素解析器の比較
この中から、、、

「Sudachi」一番後発でPythonライブラリもあるみたいだからこれに決めます!!

取り合えず、導入手順は今まで経験より、素直にGitHubの公式サイト「SudachiPy」を参考にします。

環境は、
Windows 7(早く更新しないとね)
Python 3.7.7
です。

インストールはちょー、簡単。(とこの時点では思っていた)pipで、

> pip install SudachiPy
> pip install https://object-storage.tyo2.conoha.io/v1/nc_2520839e1f9641b08211a5c85243124a/sudachi/SudachiDict_core-20200330.tar.gz

となります。

それでは、さっそくIPythonでテスト実行してみましょう。

In [1]: from sudachipy import tokenizer
In [2]: from sudachipy import dictionary

ライブラリのimportはうまくいったので、次は辞書の読み込みですね。

In [3]: tokenizer_obj = dictionary.Dictionary().create()
・
・
・
  File "C:\Users\****\AppData\Local\Continuum\anaconda3\lib\site-packages\sudachipy\config.py", line 49, in set_default_dict_package
    dst_path.symlink_to(src_path)

  File "C:\Users\****\AppData\Local\Continuum\anaconda3\lib\pathlib.py", line 1347, in symlink_to
    self._accessor.symlink(target, self, target_is_directory)

OSError: symbolic link privilege not held

えっ~~、今回も開始早々トラブルーーー。

もう、しょうがない。
ふむふむ、シンボリックリンクを作る権限がないと。



なるほど~~って、Windowsってショートカット(問題なく作れる)とシンボリックリンクって別物なの?!!
っと、ここの深堀はまた別の機会に置いておいて、

取り合えず、
ローカルセキュリティポリシーのセキュリティ設定 > ローカルポリシー > ユーザー権利の割り当て > シンボリックの作成にログインユーザーとRemote Desktop Usersを加えて、ログインし直しても効果なしっと。
PCの再起動してもいいけど、再ログインで適用されるはずなのと物理PCは会社なのでここまでにしとこ。
まぁ、リモートデスクトップ接続して使われる想定がないのでしょう。回避策はありそうだけど、この深堀も別で。

こうなったら、シンボリックリンク張ろうとしている config.pyとやらを修正するのが早そう。
問題の箇所は、

def set_default_dict_package(dict_package, output):
    unlink_default_dict_package(output)

    src_path = Path(import_module(dict_package).__file__).parent
    dst_path = src_path.parent / 'sudachidict'
    
    dst_path.symlink_to(src_path)
    print('default dict package = {}'.format(dict_package), file=output)

    return dst_path

取り合えず、print文流し込んで何のシンボリックリンクを張ろうとしているか確認すると、
パッケージ内の「sudachidict_core」を「sudachidict」という別名にしたいらしい。
では、sudachidict_coreを丸々同じ場所にコピーしたsudachidictを作って、
※ショートカットで対処したら、フォルダ辿れないって怒られたので。
存在したらシンボリックリンク作らないようにPythonが良きに計らってくれるかもしれないけど念のため、
※シンボリックリンクの解除処理は、シンボリックリンクがある場合に限定しているプログラムなのは確認済み。

def set_default_dict_package(dict_package, output):
    print('dict_package =', dict_package) # add
    unlink_default_dict_package(output)

    src_path = Path(import_module(dict_package).__file__).parent
    print('src_path =', src_path) # add
    dst_path = src_path.parent / 'sudachidict'
    print('dst_path =', dst_path) # add
    
    # リモートデスクトップで作業したいため、sudachidict_coreをコピー(sudachidict)で対応するためコメントアウト
    #dst_path.symlink_to(src_path)
    print('default dict package = {}'.format(dict_package), file=output)

    return dst_path

どうでしょう・・・

In [4]: tokenizer_obj = dictionary.Dictionary().create()
In [5]: 

いぇい、成功!!
よし、このままテスト実行してみよ。

In [5]: mode = tokenizer.Tokenizer.SplitMode.C
[m.surface() for m in tokenizer_obj.tokenize("国家公務員", mode)]
Out[5]: ['国家公務員']

In [6]: mode = tokenizer.Tokenizer.SplitMode.B
[m.surface() for m in tokenizer_obj.tokenize("国家公務員", mode)]
Out[6]: ['国家', '公務員']

In [7]: mode = tokenizer.Tokenizer.SplitMode.A
[m.surface() for m in tokenizer_obj.tokenize("国家公務員", mode)]
Out[7]: ['国家', '公務', '員']

In [8]: m = tokenizer_obj.tokenize("食べ", mode)[0]

In [9]: m.surface()
Out[9]: '食べ'

In [10]: m.dictionary_form()
Out[10]: '食べる'

In [11]: m.reading_form()
Out[11]: 'タベ'

In [12]: m.part_of_speech()
Out[12]: ['動詞', '一般', '*', '*', '下一段-バ行', '連用形-一般']

In [13]: tokenizer_obj.tokenize("附属", mode)[0].normalized_form()
Out[13]: '付属'

In [14]: tokenizer_obj.tokenize("SUMMER", mode)[0].normalized_form()
Out[14]: 'サマー'

In [15]: tokenizer_obj.tokenize("シュミレーション", mode)[0].normalized_form()
Out[15]: 'シミュレーション'

オッケー、大丈夫そう。

形態素解析は、辞書の出来と定期的に更新されることが肝要なんですって。
今回取り込んだSudachiの辞書は、2020年3月30日なので今後の更新も期待できるよね。

ということで今日はこの辺で。See You~!!