0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

MeCabの解析結果をそのままMeCabの学習に使ってエラーが出る原因と対処(UniDicの場合)

Last updated at Posted at 2023-04-07

MeCab の解析結果をそのまま MeCab の学習(mecab-cost-train)に使おうとして下のようになってしまうという "あるある" の原因と解決法。
avn.png

上の図だと、

  • 解析結果を学習に使うということは CSV に登録されているはずなのに、adding virtual node が大量発生
  • 解析結果が未知語(処理の出力)になった行で rewrite.def の記載のパターンとマッチせずにエラー出して終了(↓)
feature_index.cpp(278) [rewrite_.rewrite2(path->rnode->feature, &ufeature2, &lfeature2, &rfeature2)]  cannot rewrite pattern: 補助記号,一般,,,,

adding virtual node の説明はこれ(↓)

adding virtual node: 未知語処理を行なっても処理できなかった 形態素で, 学習の際便宜的に追加される形態素です.

adding virtual node 起きても、別に学習は動くのだけど。virtual node 作るたびにメモリガンガン消費して、そこそこ大きいデータで学習しようとしたらすぐメモリ足りなくなるので、ちゃんと辞書に載ってる(未知語でない)なら、起きないのがベスト。

原因は単に MeCab の出力結果と学習時の CSV がマッチしていないだけ、なのだけど、
前回のように、ミニデータ作ってちゃんと確認してみる。

使うデータ

前回作ったミニデータを再利用する。

adding virtual node をなくす

ミニデータの final に入ってる辞書は「車で待つ」「くるまで待つ」くらいしか解析できないけれど、まずはそれを実行する。

解析するテキストを用意。

raw_text.txt
車で待つ
くるまで待つ

前回の作った final はバイナリ化していなかったのでディレクトリに入って mecab-dict-index でバイナリ化。

$ cd final/

final$ mecab-dict-index
./pos-id.def is not found. minimum setting is used
reading ./unk.def ... 35
emitting double-array: 100% |###########################################|
./pos-id.def is not found. minimum setting is used
reading ./mini_lex.csv ... 6
emitting double-array: 100% |###########################################|
reading ./matrix.def ... 15x16
emitting matrix      : 100% |###########################################|

done!

final$ cd ../

この final 使って raw_text.txt を解析。

$ mecab -d final raw_text.txt > mecab_output_corpus.mecab

MeCab の -d オプションで final を辞書指定している。

$ cat mecab_output_corpus.mecab
車      名詞,普通名詞,一般,,,,クルマ,車,車,クルマ,車,クルマ,和,"ク濁","基本形","","","","",体,クルマ,クルマ,クルマ,クル マ,"0","C2","",2895297651024384,10533
で      助詞,接続助詞,,,,,テ,て,で,デ,で,デ,和,"","","","","","",接助,デ,デ,デ,デ,"","動詞%F1,形容詞%F2@-1","",6837330270888448,24874
待つ    動詞,一般,,,五段-タ行,終止形-一般,マツ,待つ,待つ,マツ,待つ,マツ,和,"","","","","","",用,マツ,マツ,マツ,マツ,"1","C1","",9848884062986923,35830
EOS
くるま  名詞,普通名詞,一般,,,,クルマ,車,くるま,クルマ,くるま,クルマ,和,"ク濁","基本形","","","","",体,クルマ,クルマ,クルマ,クルマ,"0","C2","",2895297718133248,10533
で      助詞,接続助詞,,,,,テ,て,で,デ,で,デ,和,"","","","","","",接助,デ,デ,デ,デ,"","動詞%F1,形容詞%F2@-1","",6837330270888448,24874
待つ    動詞,一般,,,五段-タ行,終止形-一般,マツ,待つ,待つ,マツ,待つ,マツ,和,"","","","","","",用,マツ,マツ,マツ,マツ,"1","C1","",9848884062986923,35830
EOS

解析はできたので、早速この結果を学習に使ってみる。

$ cd seed/
seed$ mecab-cost-train ../mecab_output_corpus.mecab model
reading corpus ...adding virtual node: 名詞,普通名詞,一般,,,,クルマ,車,車,クルマ,車,クルマ,和,"ク濁","基本形","","","","",体,クルマ,クルマ,クルマ,クルマ,"0","C2","",2895297651024384,10533
adding virtual node: 助詞,接続助詞,,,,,テ,て,で,デ,で,デ,和,"","","","","","",接助,デ,デ,デ,デ,"","動詞%F1,形容詞%F2@-1","",6837330270888448,24874
adding virtual node: 動詞,一般,,,五段-タ行,終止形-一般,マツ,待つ,待つ,マツ,待つ,マツ,和,"","","","","","",用,マツ,マツ, マツ,マツ,"1","C1","",9848884062986923,35830
adding virtual node: 名詞,普通名詞,一般,,,,クルマ,車,くるま,クルマ,くるま,クルマ,和,"ク濁","基本形","","","","",体,クル マ,クルマ,クルマ,クルマ,"0","C2","",2895297718133248,10533
adding virtual node: 助詞,接続助詞,,,,,テ,て,で,デ,で,デ,和,"","","","","","",接助,デ,デ,デ,デ,"","動詞%F1,形容詞%F2@-1","",6837330270888448,24874
adding virtual node: 動詞,一般,,,五段-タ行,終止形-一般,マツ,待つ,待つ,マツ,待つ,マツ,和,"","","","","","",用,マツ,マツ, マツ,マツ,"1","C1","",9848884062986923,35830

Number of sentences: 2
Number of features:  52
eta:                 0.00005
freq:                1
eval-size:           10
unk-eval-size:       4
threads:             1
charset:             UTF-8
C(sigma^2):          1.00000

iter=0 err=0.50000 F=0.50000 target=4.38203 diff=1.00000
iter=1 err=0.00000 F=1.00000 target=2.12781 diff=0.51442
iter=2 err=0.00000 F=1.00000 target=1.98969 diff=0.06491
iter=3 err=0.00000 F=1.00000 target=1.97815 diff=0.00580
iter=4 err=0.00000 F=1.00000 target=1.97697 diff=0.00060
iter=5 err=0.00000 F=1.00000 target=1.97687 diff=0.00005
iter=6 err=0.00000 F=1.00000 target=1.97687 diff=0.00000
iter=7 err=0.00000 F=1.00000 target=1.97687 diff=0.00000

Done! writing model file ...

自分の解析結果のくせに adding virtual node しますね。
まずこれは dicrc で指定してる MeCab の解析出力指定の一部が悪くて、

node-format-unidic22 = %m\t%f[0],%f[1],%f[2],%f[3],%f[4],%f[5],%f[6],%f[7],%f[8],%f[9],%f[10],%f[11],%f[12],"%f[13]","%f[14]","%f[15]","%f[16]","%f[17]","%f[18]",%f[19],%f[20],%f[21],%f[22],%f[23],"%f[24]","%f[25]","%f[26]",%f[27],%f[28]\n

この行の

"%f[13]","%f[14]","%f[15]","%f[16]","%f[17]","%f[18]",%f[19],%f[20],%f[21],%f[22],%f[23],"%f[24]","%f[25]","%f[26]",

このあたりのダブルクォーテーション(")でくくってるカラムには、アクセント関係の値が入るのだけど。例えば「"動詞%F1,形容詞%F2@-1"」みたいに 1 カラムにカンマ(,)区切りで複数値が入ってくることがあって。何もしてないと、CSV 的にはまずい。だけど複数値が入る場合だけダブルクォーテーションでくくるとかそういう複雑、dicrc では設定できない。なので苦肉の策で値が 1 個でも空でもとりあえず全部ダブルクォーテーションでくくっている。

空の場合「,"",」みたいになってしまうけれど、CSV のルール的には空要素扱いで特に問題はない。

ただ mini_lex.csv では、アクセント用のカラムに入る値が 1 個の時はダブルクォーテーションではくくっていないし、0 個の時はアスタリスク(*)が入る。

空の時にアスタリスク(*)が入るのは他のカラムでも同様。

mini_lex.csv
くるま,0,0,0,名詞,普通名詞,一般,*,*,*,クルマ,車,くるま,クルマ,くるま,クルマ,和,ク濁,基本形,*,*,*,*,体,クルマ,クルマ,クルマ,クルマ,0,C2,*,2895297718133248,10533
車,0,0,0,名詞,普通名詞,一般,*,*,*,クルマ,車,車,クルマ,車,クルマ,和,ク濁,基本形,*,*,*,*,体,クルマ,クルマ,クルマ,クルマ,0,C2,*,2895297651024384,10533
くる,0,0,0,動詞,非自立可能,*,*,カ行変格,終止形-一般,クル,来る,くる,クル,くる,クル,和,*,*,*,*,*,*,用,クル,クル,クル,クル,1,C1,*,2891174448865963,10518
まで,0,0,0,助詞,副助詞,*,*,*,*,マデ,まで,まで,マデ,まで,マデ,和,*,*,*,*,*,*,副助,マデ,マデ,マデ,マデ,*,"名詞%F2@1,形容詞%F2@1,動詞%F2@1",*,9865651581755904,35891
で,0,0,0,助詞,接続助詞,*,*,*,*,テ,て,で,デ,で,デ,和,*,*,*,*,*,*,接助,デ,デ,デ,デ,*,"動詞%F1,形容詞%F2@-1",*,6837330270888448,24874
待つ,0,0,0,動詞,一般,*,*,五段-タ行,終止形-一般,マツ,待つ,待つ,マツ,待つ,マツ,和,*,*,*,*,*,*,用,マツ,マツ,マツ,マツ,1,C1,*,9848884062986923,35830

というわけで、

  • 1 カラムに値が 0 or 1 つしか入っていないのにダブルクォーテーションでくくってあるカラムからくくってるダブルクォーテーションを除去
  • 空のカラムはアスタリスクで埋める

を実施したのがこちら(↓)。

$ cat mecab_output_corpus_2.mecab
車      名詞,普通名詞,一般,*,*,*,クルマ,車,車,クルマ,車,クルマ,和,ク濁,基本形,*,*,*,*,体,クルマ,クルマ,クルマ,クルマ,0,C2,*,2895297651024384,10533
で      助詞,接続助詞,*,*,*,*,テ,て,で,デ,で,デ,和,*,*,*,*,*,*,接助,デ,デ,デ,デ,*,"動詞%F1,形容詞%F2@-1",*,6837330270888448,24874
待つ    動詞,一般,*,*,五段-タ行,終止形-一般,マツ,待つ,待つ,マツ,待つ,マツ,和,*,*,*,*,*,*,用,マツ,マツ,マツ,マツ,1,C1,*,9848884062986923,35830
EOS
くるま  名詞,普通名詞,一般,*,*,*,クルマ,車,くるま,クルマ,くるま,クルマ,和,ク濁,基本形,*,*,*,*,体,クルマ,クルマ,クルマ,クルマ,0,C2,*,2895297718133248,10533
で      助詞,接続助詞,*,*,*,*,テ,て,で,デ,で,デ,和,*,*,*,*,*,*,接助,デ,デ,デ,デ,*,"動詞%F1,形容詞%F2@-1",*,6837330270888448,24874
待つ    動詞,一般,*,*,五段-タ行,終止形-一般,マツ,待つ,待つ,マツ,待つ,マツ,和,*,*,*,*,*,*,用,マツ,マツ,マツ,マツ,1,C1,*,9848884062986923,35830
EOS

さっそく、mecab-cost-train

seed$ mecab-cost-train ../mecab_output_corpus_2.mecab model
reading corpus ...
Number of sentences: 2
Number of features:  52
eta:                 0.00005
freq:                1
eval-size:           10
unk-eval-size:       4
threads:             1
charset:             UTF-8
C(sigma^2):          1.00000

iter=0 err=0.50000 F=0.50000 target=0.69315 diff=1.00000
iter=1 err=0.00000 F=1.00000 target=0.50293 diff=0.27442
iter=2 err=0.00000 F=1.00000 target=0.29234 diff=0.41873
iter=3 err=0.00000 F=1.00000 target=0.29495 diff=0.00894
iter=4 err=0.00000 F=1.00000 target=0.17163 diff=0.41809
iter=5 err=0.00000 F=1.00000 target=0.17105 diff=0.00337
iter=6 err=0.00000 F=1.00000 target=0.17077 diff=0.00164
iter=7 err=0.00000 F=1.00000 target=0.17077 diff=0.00000
iter=8 err=0.00000 F=1.00000 target=0.17077 diff=0.00000

Done! writing model file ...

adding virtual node 回避。

ちなみにこういうふう(↓)に、空のカラムをアスタリスクで埋めなかったり、値が 1 個なのにダブルクォーテーションでくくってたり、ダブルクォーテーションでくくった空要素があると、CSV 側のアスタリスクで埋めてあるカラムと一致せず、もれなく adding virtual node 行き。

mecab_output_corpus_3.mecab
車      名詞,普通名詞,一般,,,,クルマ,車,車,クルマ,車,クルマ,和,ク濁,基本形,*,*,*,*,体,クルマ,クルマ,クルマ,クルマ,0,C2,*,2895297651024384,10533
で      助詞,"接続助詞",*,*,*,*,テ,て,で,デ,で,デ,和,*,*,*,*,*,*,接助,デ,デ,デ,デ,*,"動詞%F1,形容詞%F2@-1",*,6837330270888448,24874
待つ    動詞,一般,"",*,五段-タ行,終止形-一般,マツ,待つ,待つ,マツ,待つ,マツ,和,*,*,*,*,*,*,用,マツ,マツ,マツ,マツ,1,C1,*,9848884062986923,35830
EOS
くるま  名詞,普通名詞,一般,*,*,*,クルマ,車,くるま,クルマ,くるま,クルマ,和,ク濁,基本形,*,*,*,*,体,クルマ,クルマ,クルマ,クルマ,0,C2,*,2895297718133248,10533
で      助詞,接続助詞,*,*,*,*,テ,て,で,デ,で,デ,和,*,*,*,*,*,*,接助,デ,デ,デ,デ,*,"動詞%F1,形容詞%F2@-1",*,6837330270888448,24874
待つ    動詞,一般,*,*,五段-タ行,終止形-一般,マツ,待つ,待つ,マツ,待つ,マツ,和,*,*,*,*,*,*,用,マツ,マツ,マツ,マツ,1,C1,*,9848884062986923,35830
EOS
seed$ mecab-cost-train ../mecab_output_corpus_3.mecab model
reading corpus ...adding virtual node: 名詞,普通名詞,一般,,,,クルマ,車,車,クルマ,車,クルマ,和,ク濁,基本形,*,*,*,*,体,ク ルマ,クルマ,クルマ,クルマ,0,C2,*,2895297651024384,10533
adding virtual node: 助詞,"接続助詞",*,*,*,*,テ,て,で,デ,で,デ,和,*,*,*,*,*,*,接助,デ,デ,デ,デ,*,"動詞%F1,形容詞%F2@-1",*,6837330270888448,24874
adding virtual node: 動詞,一般,"",*,五段-タ行,終止形-一般,マツ,待つ,待つ,マツ,待つ,マツ,和,*,*,*,*,*,*,用,マツ,マツ,マツ,マツ,1,C1,*,9848884062986923,35830

Number of sentences: 2
Number of features:  52
eta:                 0.00005
freq:                1
eval-size:           10
unk-eval-size:       4
threads:             1
charset:             UTF-8
C(sigma^2):          1.00000

iter=0 err=0.50000 F=0.50000 target=2.77259 diff=1.00000
iter=1 err=0.00000 F=1.00000 target=1.74502 diff=0.37062
iter=2 err=0.00000 F=1.00000 target=1.54654 diff=0.11374
iter=3 err=0.00000 F=1.00000 target=1.43054 diff=0.07501
iter=4 err=0.00000 F=1.00000 target=1.42481 diff=0.00400
iter=5 err=0.00000 F=1.00000 target=1.42397 diff=0.00059
iter=6 err=0.00000 F=1.00000 target=1.42393 diff=0.00003
iter=7 err=0.00000 F=1.00000 target=1.42393 diff=0.00000
iter=8 err=0.00000 F=1.00000 target=1.42393 diff=0.00000

Done! writing model file ...

同梱の SQL ファイルを読めばわかるけど、UniDic はver. 2.2.0 以降、DB から CSV を export する際に、空のカラムには必ずアスタリスクを入れているし、カラムに値が 2 つ以上入る場合のみ、ダブルクォーテーションでくくっている。

さらに補足だが、今回使っているミニデータでは feature.def でアクセント周りの素性は基の UniDic から削除して使っている。
なので実は、アクセント周りのカラムは空だろうが、ダブルクォーテーションでくくってあろうがなかろうが、問題なく動いたりする。

$ cat mecab_output_corpus_4.mecab
車      名詞,普通名詞,一般,*,*,*,クルマ,車,車,クルマ,車,クルマ,和,ク濁,基本形,*,*,*,*,体,クルマ,クルマ,クルマ,クルマ,0,C2,*,2895297651024384,10533
で      助詞,接続助詞,*,*,*,*,テ,て,で,デ,で,デ,和,*,*,*,*,*,*,接助,デ,デ,デ,デ,*,"動詞%F1,形容詞%F2@-1",*,6837330270888448,24874
待つ    動詞,一般,*,*,五段-タ行,終止形-一般,マツ,待つ,待つ,マツ,待つ,マツ,和,*,*,*,*,*,*,用,マツ,マツ,マツ,マツ,1,C1,*,9848884062986923,35830
EOS
くるま  名詞,普通名詞,一般,*,*,*,クルマ,車,くるま,クルマ,くるま,クルマ,和,ク濁,基本形,*,*,*,"",体,クルマ,クルマ,クルマ, クルマ,0,C2,*,2895297718133248,10533
で      助詞,接続助詞,*,*,*,*,テ,て,で,デ,で,デ,和,*,*,*,*,*,*,接助,デ,デ,デ,デ,,"動詞%F1,形容詞%F2@-1",*,6837330270888448,24874
待つ    動詞,一般,*,*,五段-タ行,終止形-一般,マツ,待つ,待つ,マツ,待つ,マツ,和,*,*,*,*,*,*,用,マツ,マツ,マツ,マツ,1,"C1",*,9848884062986923,35830
EOS
seed$ mecab-cost-train ../mecab_output_corpus_4.mecab model
reading corpus ...
Number of sentences: 2
Number of features:  52
eta:                 0.00005
freq:                1
eval-size:           10
unk-eval-size:       4
threads:             1
charset:             UTF-8
C(sigma^2):          1.00000

iter=0 err=0.50000 F=0.50000 target=0.69315 diff=1.00000
iter=1 err=0.00000 F=1.00000 target=0.50293 diff=0.27442
iter=2 err=0.00000 F=1.00000 target=0.29234 diff=0.41873
iter=3 err=0.00000 F=1.00000 target=0.29495 diff=0.00894
iter=4 err=0.00000 F=1.00000 target=0.17163 diff=0.41809
iter=5 err=0.00000 F=1.00000 target=0.17105 diff=0.00337
iter=6 err=0.00000 F=1.00000 target=0.17077 diff=0.00164
iter=7 err=0.00000 F=1.00000 target=0.17077 diff=0.00000
iter=8 err=0.00000 F=1.00000 target=0.17077 diff=0.00000

Done! writing model file ...

ポイントなのは feature.def で使用しているカラムの中身がコーパスと CSV で同じ形で書かれていることだったりする。

未知語処理された行でエラーになるのに対応

ミニデータの CSV にはカタカナ表記の「クルマ」は入っていないので、

final raw_text_2.txt
クルマで待つ

を作って、

$ mecab -d final raw_text_2.txt > mecab_output_corpus_5.mecab
mecab_output_corpus_5.mecab
ク      名詞,普通名詞,一般,,,
ル      名詞,普通名詞,一般,,,
マ      名詞,普通名詞,一般,,,
で      助詞,接続助詞,,,,,テ,て,で,デ,で,デ,和,"","","","","","",接助,デ,デ,デ,デ,"","動詞%F1,形容詞%F2@-1","",6837330270888448,24874
待つ    動詞,一般,,,五段-タ行,終止形-一般,マツ,待つ,待つ,マツ,待つ,マツ,和,"","","","","","",用,マツ,マツ,マツ,マツ,"1","C1","",9848884062986923,35830
EOS

これを訓練データにする。

seed$ mecab-cost-train ../mecab_output_corpus_5.mecab model
reading corpus ...adding virtual node: 名詞,普通名詞,一般,,,
adding virtual node: 名詞,普通名詞,一般,,,
adding virtual node: 名詞,普通名詞,一般,,,
adding virtual node: 助詞,接続助詞,,,,,テ,て,で,デ,で,デ,和,"","","","","","",接助,デ,デ,デ,デ,"","動詞%F1,形容詞%F2@-1","",6837330270888448,24874
adding virtual node: 動詞,一般,,,五段-タ行,終止形-一般,マツ,待つ,待つ,マツ,待つ,マツ,和,"","","","","","",用,マツ,マツ, マツ,マツ,"1","C1","",9848884062986923,35830
feature_index.cpp(278) [rewrite_.rewrite2(path->rnode->feature, &ufeature2, &lfeature2, &rfeature2)]  cannot rewrite pattern: 名詞,普通名詞,一般,,,

これ実は rewrite.def の書き換えパターンにマッチしない(列数が足りてない)って怒られているだけで。
列数は実際足りているのだけど、カンマ(,)の直後に改行が入ると、カンマ直後のカラムを「ない」と判断しているだけなので。こういうふうに改行直前に値を入れてあげるだけで解決する。

mecab_output_corpus_6.mecab
ク      名詞,普通名詞,一般,,,*
ル      名詞,普通名詞,一般,,,*
マ      名詞,普通名詞,一般,,,*
で      助詞,接続助詞,,,,,テ,て,で,デ,で,デ,和,"","","","","","",接助,デ,デ,デ,デ,"","動詞%F1,形容詞%F2@-1","",6837330270888448,24874
待つ    動詞,一般,,,五段-タ行,終止形-一般,マツ,待つ,待つ,マツ,待つ,マツ,和,"","","","","","",用,マツ,マツ,マツ,マツ,"1","C1","",9848884062986923,35830
EOS
$ /work/oka/bin/mecab0996/libexec/mecab/mecab-cost-train ../mecab_output_corpus_5.mecab model
reading corpus ...adding virtual node: 名詞,普通名詞,一般,,,*
adding virtual node: 名詞,普通名詞,一般,,,*
adding virtual node: 名詞,普通名詞,一般,,,*
adding virtual node: 助詞,接続助詞,,,,,テ,て,で,デ,で,デ,和,"","","","","","",接助,デ,デ,デ,デ,"","動詞%F1,形容詞%F2@-1","",6837330270888448,24874
adding virtual node: 動詞,一般,,,五段-タ行,終止形-一般,マツ,待つ,待つ,マツ,待つ,マツ,和,"","","","","","",用,マツ,マツ, マツ,マツ,"1","C1","",9848884062986923,35830

Number of sentences: 1
Number of features:  32
eta:                 0.00005
freq:                1
eval-size:           10
unk-eval-size:       4
threads:             1
charset:             UTF-8
C(sigma^2):          1.00000

iter=0 err=1.00000 F=-nan target=7.45703 diff=1.00000
iter=1 err=0.00000 F=1.00000 target=4.06693 diff=0.45462
iter=2 err=0.00000 F=1.00000 target=3.24484 diff=0.20214
iter=3 err=0.00000 F=1.00000 target=3.22770 diff=0.00528
iter=4 err=0.00000 F=1.00000 target=3.22755 diff=0.00004
iter=5 err=0.00000 F=1.00000 target=3.22753 diff=0.00001
iter=6 err=0.00000 F=1.00000 target=3.22753 diff=0.00000

Done! writing model file ...

これで解決。

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?