Python spaCyとGiNZAでユーザー辞書を使った形態素解析

Pythonで自然言語処理に特化したライブラリspaCyと日本語の自然言語処理ライブラリGiNZAを用いて形態素解析を行うことを考えたとき、自分で定義したユーザー辞書を使いたいときがあります。ここでは、ユーザー辞書の作成方法と使い方についてお伝えします。特に、ユーザー辞書の使用を「sudachi.json」を直接編集する方法ではなく、Pythonコードのみで記述する方法をお伝えします。

環境

今回の作業は、Windowsのwslで、python 3.13のdocker上で行っています。

環境構築

spaCyとGiNZAを使えるようにpipでインストールしておきます。


pip install spacy ginza

テストコード

「すだちは、徳島県原産の香酸柑橘類で、爽やかな香りと酸味が特徴です。」を形態素解析してみます。


import spacy

nlp = spacy.load('ja_ginza')

text = 'すだちは、徳島県原産の香酸柑橘類で、爽やかな香りと酸味が特徴です。'

for token in nlp(text):
    print(f'{token.i} {token.text} {token.lemma_} {token.pos_} {token.pos_} {token.tag_}')

0 すだち すだち NOUN NOUN 名詞-普通名詞-一般
1 は は ADP ADP 助詞-係助詞
2 、 、 PUNCT PUNCT 補助記号-読点
3 徳島県 徳島県 PROPN PROPN 名詞-固有名詞-地名-一般
4 原産 原産 NOUN NOUN 名詞-普通名詞-一般
5 の の ADP ADP 助詞-格助詞
6 香酸 香酸 NOUN NOUN 名詞-普通名詞-一般
7 柑橘類 柑橘類 NOUN NOUN 名詞-普通名詞-一般
8 で で ADP ADP 助詞-格助詞
9 、 、 PUNCT PUNCT 補助記号-読点
10 爽やか 爽やか ADJ ADJ 形状詞-一般
11 な だ AUX AUX 助動詞
12 香り 香り NOUN NOUN 名詞-普通名詞-一般
13 と と ADP ADP 助詞-格助詞
14 酸味 酸味 NOUN NOUN 名詞-普通名詞-一般
15 が が ADP ADP 助詞-格助詞
16 特徴 特徴 NOUN NOUN 名詞-普通名詞-一般
17 です です AUX AUX 助動詞
18 。 。 PUNCT PUNCT 補助記号-句点

「香酸」と「柑橘類」が分かれましたが、ここでは「香酸柑橘類」としたいとします。

ユーザー辞書作成

GiNZAは形態素解析部分でSudachiPyを使用しているため、Sudachiのユーザー辞書を作成します。Sudachiのユーザー辞書の内容については、Sudachi本家のSudachi ユーザー辞書作成方法を参照してください。

ユーザー辞書ソースのCSVファイル作成

次の内容をuser_dic.csvとして保存しておきます。


香酸柑橘類,5146,5146,5000,香酸柑橘類,名詞,普通名詞,一般,*,*,*,コウサンカンキツルイ,香酸柑橘類,*,*,*,*,*

ユーザー辞書のビルド

ユーザー辞書をビルドするためにはsystem.dicのファイルパスが必要になります。findコマンドでファイルパスを取得しておきます。


find /usr/local/lib/ -name system.dic

/usr/local/lib/python3.13/site-packages/sudachidict_core/resources/system.dic

このsystem.dicと上記のuser_dic.csvでユーザー辞書user.dicを作成するコマンドは次になります。


sudachipy ubuild -s /usr/local/lib/python3.13/site-packages/sudachidict_core/resources/system.dic user_dic.csv -o user.dic

/notebook/user_dic.csv -> 1 in 0.00 sec
validate -> 1 in 0.00 sec
pos_table -> 2 in 0.00 sec
conn_matrix -> 6 in 0.00 sec
trie -> 1028 in 0.00 sec
word_id table -> 9 in 0.00 sec
word_params -> 10 in 0.00 sec
wordinfo_offsets -> 4 in 0.00 sec
wordinfos (copy only) -> 44 in 0.00 sec

ちなみに、次のようにすれば一行で済みます。


find /usr/local/lib/ -name system.dic | xargs -i sudachipy ubuild -s {} user_dic.csv -o user.dic

/notebook/user_dic.csv -> 1 in 0.00 sec
validate -> 1 in 0.00 sec
pos_table -> 2 in 0.00 sec
conn_matrix -> 6 in 0.00 sec
trie -> 1028 in 0.00 sec
word_id table -> 9 in 0.00 sec
word_params -> 10 in 0.00 sec
wordinfo_offsets -> 4 in 0.00 sec
wordinfos (copy only) -> 44 in 0.00 sec

ユーザー辞書を使った形態素解析

ユーザー辞書を使う指定の方法は、/usr/local/libディレクトリ以下のsudachi.jsonファイルを直接編集する方法やこのsudachi.jsonファイルをどこか適当なディレクトリにコピーしてから編集して使う方法がありますが、ここではPythonコードでjsonファイルを読み込んで、直接指定する方法でユーザー辞書を使うようにします。


import spacy
import sudachipy
import json
from spacy.lang.ja import JapaneseTokenizer

nlp = spacy.load('ja_ginza')

with open(sudachipy._DEFAULT_SETTINGFILE) as f:
    sudachi_json = json.load(f)
sudachi_json['userDict'] = ['user.dic']
japanese_tokenizer = JapaneseTokenizer(nlp.vocab, 'A')
japanese_tokenizer.tokenizer = sudachipy.Dictionary(config_path=json.dumps(sudachi_json)).create('A')
nlp.tokenizer = japanese_tokenizer

text = 'すだちは、徳島県原産の香酸柑橘類で、爽やかな香りと酸味が特徴です。'

for token in nlp(text):
    print(f'{token.i} {token.text} {token.lemma_} {token.pos_} {token.pos_} {token.tag_}')

0 すだち すだち NOUN NOUN 名詞-普通名詞-一般
1 は は ADP ADP 助詞-係助詞
2 、 、 PUNCT PUNCT 補助記号-読点
3 徳島 徳島 PROPN PROPN 名詞-固有名詞-地名-一般
4 県 県 NOUN NOUN 名詞-普通名詞-一般
5 原産 原産 NOUN NOUN 名詞-普通名詞-一般
6 の の ADP ADP 助詞-格助詞
7 香酸柑橘類 香酸柑橘類 NOUN NOUN 名詞-普通名詞-一般
8 で で AUX AUX 助詞-格助詞
9 、 、 PUNCT PUNCT 補助記号-読点
10 爽やか 爽やか ADJ ADJ 形状詞-一般
11 な だ AUX AUX 助動詞
12 香り 香り NOUN NOUN 名詞-普通名詞-一般
13 と と ADP ADP 助詞-格助詞
14 酸味 酸味 NOUN NOUN 名詞-普通名詞-一般
15 が が ADP ADP 助詞-格助詞
16 特徴 特徴 NOUN NOUN 名詞-普通名詞-一般
17 です です AUX AUX 助動詞
18 。 。 PUNCT PUNCT 補助記号-句点

「香酸柑橘類」が一つとして抽出されるようになりました。