C++ 日本語係り受け解析 J.DepP(ジョニーデップ)のメモ
背景
LLM 向けデータセット構築で, web 文章が自然な日本語かどうか, 精度はいくらか犠牲になってもよいので高速に判定したい(TB 単位のテキストを処理なので, GiNZA とかだとおそすぎる)
高速を謳う J.DepP(ジョニーデップ)を試します!
J.DepP を動かすには POS tagger(mecab とか juman とか)が必要になります.
ビルド
Ubuntu 20.04 を想定します.
形態素解析モジュール
J.DepP 用辞書ビルドのためにも, MeCab or Juman が必要です.
J.DepP の configure が mecab-config
で dict の場所を取得するのですが, Ubuntu package ではこれはいろいろ壊れていて変な場所を dictdir として返してくるので使い物になりません. configure.ac 書き直ししてもいいのですが, めんどいのでとりあえず juman 使います.
$ sudo apt install juman # default? 辞書もインストールされる
京都大学テキストコーパス?
最高精度を求めるなら京都大学テキストコーパス利用がよいとあります.
ただ, これを利用するには毎日新聞CD-ROMが必要です.
(2023/12/24 時点でアクセスしたらサイト落ちてる...)
今回はそんなに精度はいらないので, default で進めます.
configure
デフォだと /usr/local/
に install し, model file も /usr/local/..
がデフォになる(jdepp
実行時に -m
で指定できるが), --prefix
で適当にユーザフォルダを指定しておくとよいでしょう.
$ ./configure --prefix=`pwd`/dist --with-postagger=juman
$ make # jdepp のビルド
$ make model # モデルのビルド
$ make install # optional
使う
jdepp
への入力は, POS Tagger(品詞付与), つまり mecab, juman などにより処理したテキストになります.
適当に入力文を用意します.
# test.sent
吾輩は猫である。名前はまだない。
まず juman で変換します(ここは mecab でもいいかも)
$ juman < test.sent
吾輩 わがはい 吾輩 名詞 6 普通名詞 1 * 0 * 0 "代表表記:我が輩/わがはい カテゴリ:人"
は は は 助詞 9 副助詞 2 * 0 * 0 NIL
猫 ねこ 猫 名詞 6 普通名詞 1 * 0 * 0 "代表表記:猫/ねこ 漢字読み:訓 カテゴリ:動物"
である である だ 判定詞 4 * 0 判定詞 25 デアル列基本形 15 NIL
。 。 。 特殊 1 句点 1 * 0 * 0 NIL
名前 なまえ 名前 名詞 6 普通名詞 1 * 0 * 0 "代表表記:名前/なまえ カテゴリ:抽象物"
は は は 助詞 9 副助詞 2 * 0 * 0 NIL
まだ まだ まだ 副詞 8 * 0 * 0 * 0 "代表表記:まだ/まだ"
ない ない ない 形容詞 3 * 0 イ形容詞アウオ段 18 基本形 2 "代表表記:無い/ない 反義:動詞:有る/ある"
。 。 。 特殊 1 句点 1 * 0 * 0 NIL
EOS EOS EOS 未定義語 15 その他 1 * 0 * 0 NIL
EOS
処理結果を jdepp に渡します.
$ ./src/jdepp -m model/knbc < pos.sent
(input: STDIN [-I 0])
# S-ID: 1; J.DepP
* 0 1D
吾輩 わがはい 吾輩 名詞 6 普通名詞 1 * 0 * 0 "代表表記:我が輩/わがはい カテゴリ:人"
は は は 助詞 9 副助詞 2 * 0 * 0 NIL
* 1 4D
猫 ねこ 猫 名詞 6 普通名詞 1 * 0 * 0 "代表表記:猫/ねこ 漢字読み:訓 カテゴリ:動物"
である である だ 判定詞 4 * 0 判定詞 25 デアル列基本形 15 NIL
。 。 。 特殊 1 句点 1 * 0 * 0 NIL
* 2 4D
名前 なまえ 名前 名詞 6 普通名詞 1 * 0 * 0 "代表表記:名前/なまえ カテゴリ:抽象物"
は は は 助詞 9 副助詞 2 * 0 * 0 NIL
* 3 4D
まだ まだ まだ 副詞 8 * 0 * 0 * 0 "代表表記:まだ/まだ"
* 4 -1D
ない ない ない 形容詞 3 * 0 イ形容詞アウオ段 18 基本形 2 "代表表記:無い/ない 反義:動詞:有る/ある"
。 。 。 特殊 1 句点 1 * 0 * 0 NIL
EOS
J.DepP profiler:
io : 0.0081 ms./trial (0.03242676/4)
dict : 0.2302 ms.
preproc : 0.0147 ms.
chunk : 0.0203 ms.
depnd : 0.0175 ms.
Voila!
ただこれだけだと人間にはわかずらいので, ↑の出力を tools/to_tree.py
で tree 可視化します!
$ python tools/to_tree.py < test.jdep
# S-ID: 1; J.DepP
0: 吾輩は━━┓
1: 猫である。━━┓
2: 名前は━━┫
3: まだ━━┫
4: ない。EOS
Super cool!
日本語の品質判定
品詞やかかり受け具合とかみて, SVO 形式かどうかなど判断すればなんかいけそう?
とりあえずフォーマットは KNP と同じっぽいようなので, KNP をいじいじしたらいろいろとわかるかも.
文境界判定
web 文章でよくある途中で改行になっているもの.
吾輩は猫である♪
明日の天気
は晴れでしょう
bunkai などで文境界判定できますが, 遅すぎるので J.DepP(+ jagger 形態素解析) で高速化できるといいが...
そのままではこんな感じに判定されます.
# S-ID: 1; J.DepP
0: 吾輩は━━┓
1: 猫である♪EOS
# S-ID: 2; J.DepP
0: 明日の━━┓
1: 天気EOS
# S-ID: 3; J.DepP
0: は@@@@━━┓
1: 晴れでしょうEOS
一行にして処理させてもこんな感じ
# S-ID: 1; J.DepP
0: 吾輩は━━┓
1: 猫である♪━━┓ ┃
2: 明日の━━┫ ┃
3: 天気は━━┫
4: 晴れでしょうEOS
文節情報はあるので(tools/to_chunk.py
で chunk(文節)区切り可視化できる)
$ python tools/to_chunk.py < test.jdepp
# S-ID: 1; J.DepP
吾輩 は │ 猫 である ♪ │ 明日 の │ 天気 は │ 晴れ でしょう EOS
文節や品詞情報からいろいろ判断すればいけそうでしょうか...
TODO
- Universal Dependencies あたりの構文ルールを元に, 日本語の自然らしさを判定する
- 文境界判定ができないか調べる
Discussion