短単位自動解析用辞書を作る(1)
モチベーション
問題意識、問題提起もしくは Issue とも言いますが、スタートとなったモチベーションはこの2つ。
短単位自動解析用、すなわち『MeCab』の辞書としての『解析用UniDic』(以降、単に『UniDic』)の現状の最新版は、2023年03月24日公開の -202302。(2023年7月現在)
以下の4つです。
(https://clrd.ninjal.ac.jp/unidic/back_number.html)
unidic-cwj-202302.zip (576MB)
unidic-cwj-202302_full.zip (2.1GB)
unidic-csj-202302.zip (609MB)
unidic-csj-202302_full.zip (2.2GB)
cwj は書き言葉用、csj は話し言葉用です。
_full の圧縮ファイルには、辞書をバイナリ化する前のファイルが含まれており、辞書の中身を見たり、追加学習が行えるようになっています。
_full が付いていないのは、当該の『UniDic』を使って、国語研のコーパスアノテーションと同様の短単位情報を手元のテキストデータに一括付与できればそれで十分な人向けです。身もふたもない言い方をすれば「単語に切れたらそれでいい」というひと向けです。
さて、1つ目のモチベーション、サイズの話です。
形態素解析器『MeCab』のデフォルト解析用辞書『ipadic(mecab-ipadic-2.7.0-20070801.tar.gz)』の圧縮されたダウンロードサイズは 12MB かつ、『UniDic』でいうところの _full 相当のファイルも全部入ってますから、圧縮して 2GB もある最新版の『UniDic』は相当大きいです。
語彙サイズや、より多くの形態論情報のフィールドがあるからというのも原因/理由ですが、それ以上に大きいのが matrix.def という単語同士の連接コストを格納した連接コスト表です。
以降、「単語」という表現に統一しますが、『UniDic』の語彙に載っているのは単語ではなく『短単位』で、『ipadic』に載っているのも「形態素」ではありません。その辺の議論はここか、もしくは下の参考文献を読んでください。
実際に見てみます。まず 『ipadic』。
$ ls -lh mecab-ipadic-2.7.0-20070801.tar.gz
12M Jul 12 12:17 mecab-ipadic-2.7.0-20070801.tar.gz
$ tar -xf mecab-ipadic-2.7.0-20070801.tar.gz
$ cd mecab-ipadic-2.7.0-20070801/
mecab-ipadic-2.7.0-20070801$ mecab-dict-index
reading ./unk.def ... 40
emitting double-array: 100% |###########################################|
./model.def is not found. skipped.
reading ./Noun.adverbal.csv ... 795
reading ./Others.csv ... 2
reading ./Noun.others.csv ... 151
reading ./Adj.csv ... 27210
reading ./Noun.csv ... 60477
reading ./Auxil.csv ... 199
reading ./Prefix.csv ... 221
reading ./Conjunction.csv ... 171
reading ./Noun.place.csv ... 72999
reading ./Adverb.csv ... 3032
reading ./Noun.name.csv ... 34202
reading ./Postp.csv ... 146
reading ./Suffix.csv ... 1393
reading ./Noun.adjv.csv ... 3328
reading ./Noun.nai.csv ... 42
reading ./Adnominal.csv ... 135
reading ./Noun.org.csv ... 16668
reading ./Filler.csv ... 19
reading ./Symbol.csv ... 208
reading ./Verb.csv ... 130750
reading ./Noun.demonst.csv ... 120
reading ./Interjection.csv ... 252
reading ./Postp-col.csv ... 91
reading ./Noun.proper.csv ... 27327
reading ./Noun.number.csv ... 42
reading ./Noun.verbal.csv ... 12146
emitting double-array: 100% |###########################################|
reading ./matrix.def ... 1316x1316
emitting matrix : 100% |###########################################|
done!
mecab-ipadic-2.7.0-20070801$ ls -lh
total 92M
41K Aug 1 2007 aclocal.m4
2.6M Jul 31 2007 Adj.csv
9.0K Jul 31 2007 Adnominal.csv
206K Jul 31 2007 Adverb.csv
141 Jun 10 2007 AUTHORS
14K Jul 31 2007 Auxil.csv
0 Jan 29 2007 ChangeLog
257K Jul 12 12:35 char.bin
4.0K Jul 31 2007 char.def
43K Jan 29 2007 config.guess
31K Jan 29 2007 config.sub
89K Aug 1 2007 configure
1.4K Jul 31 2007 configure.in
11K Jul 31 2007 Conjunction.csv
3.8K Jun 10 2007 COPYING
693 Jul 31 2007 dicrc
3.8K Jul 31 2007 feature.def
968 Jul 31 2007 Filler.csv
7.7K Jun 10 2007 INSTALL
9.0K Jan 29 2007 install-sh
14K Jul 31 2007 Interjection.csv
55K Jul 31 2007 left-id.def
563 Jun 10 2007 Makefile.am
7.3K Aug 1 2007 Makefile.in
3.4M Jul 12 12:35 matrix.bin
22M Jul 31 2007 matrix.def
11K Jan 29 2007 missing
722 Jan 29 2007 mkinstalldirs
0 Jan 29 2007 NEWS
238K Jul 31 2007 Noun.adjv.csv
52K Jul 31 2007 Noun.adverbal.csv
3.8M Jul 31 2007 Noun.csv
7.5K Jul 31 2007 Noun.demonst.csv
3.1K Jul 31 2007 Noun.nai.csv
2.3M Jul 31 2007 Noun.name.csv
2.0K Jul 31 2007 Noun.number.csv
1.7M Jul 31 2007 Noun.org.csv
9.0K Jul 31 2007 Noun.others.csv
5.7M Jul 31 2007 Noun.place.csv
2.1M Jul 31 2007 Noun.proper.csv
801K Jul 31 2007 Noun.verbal.csv
82 Jul 31 2007 Others.csv
1.5K Jan 29 2007 pos-id.def
6.9K Jul 31 2007 Postp-col.csv
7.6K Jul 31 2007 Postp.csv
12K Jul 31 2007 Prefix.csv
61 Jun 10 2007 README
1.5K Aug 1 2007 RESULT
6.1K Jul 31 2007 rewrite.def
55K Jul 31 2007 right-id.def
80K Jul 31 2007 Suffix.csv
9.9K Jul 31 2007 Symbol.csv
37M Jul 12 12:35 sys.dic
1.9K Jul 31 2007 unk.def
5.3K Jul 12 12:35 unk.dic
11M Jul 31 2007 Verb.csv
ダウンロードした状態では辞書がバイナリ化されいなかったので、mecab-dict-index でバイナリ化しています。
ファイルサイズが大きいものを見ると、語彙ファイル (.csv) やそれをバイナリ化した sys.dic (37MB) をのぞくと、バイナリ化する前の matrix.def が 22MB です。
matrix.def の先頭行には、その連接表(行列)のサイズが書いてあります。
mecab-ipadic-2.7.0-20070801$ head matrix.def
1316 1316
0 0 -434
0 1 1
0 2 -1630
0 3 -1671
0 4 24
0 5 111
0 6 -2752
0 7 -589
0 8 -589
『ipadic』では 1,316x1,316 の行列でした。
続いて『UniDic』。cwj の _full を見ます。
$ ls -lh zip/unidic-cwj-202302_full.zip
2.1G Jun 9 12:40 zip/unidic-cwj-202302_full.zip
$ unzip unidic-cwj-202302_full.zip
$ cd unidic-cwj-202302_full/
unidic-cwj-202302$ ls -lh
total 7.6G
257K Feb 21 18:41 char.bin
4.3K Feb 21 18:41 char.def
695 Feb 21 18:42 dicrc
8.6K Feb 21 18:41 feature.def
1.6M Feb 21 18:41 left-id.def
224M Feb 21 18:41 lex.csv
4.0K Jun 9 12:41 license
763M Feb 21 18:41 matrix.bin
5.9G Feb 21 18:42 matrix.def
79M Feb 21 18:42 model.bin
364M Feb 21 18:42 model.def
766 Mar 14 02:16 README_unidic-cwj_full.txt
4.8K Feb 21 18:42 rewrite.def
1.8M Feb 21 18:42 right-id.def
232M Feb 21 18:42 sys.dic
2.4K Feb 21 18:42 unk.def
5.7K Feb 21 18:42 unk.dic
こちらは unzip した状態ですでにバイナリ化されているので mecab-dict-index は不要です。
見てみると、matrix.def の 5.9GB が飛びぬけています。バイナリ化した matrix.bin でも 763MB あります。
連接表のサイズも見てみます。
unidic-cwj-202302_full$ head matrix.def
21202 18859
0 0 0
0 1 -1814
0 2 -1814
0 3 -1814
0 4 -1814
0 5 -1814
0 6 -1814
0 7 -1814
0 8 -1814
21,202x18,859 なので『ipadic』と比べると桁ひとつ違う大きさです。
この連接表を小さくしたいというのが、モチベーションその1 です。
2つめのモチベーションは、最新版『UniDic』に問題があるので手元で直したい、です。
判明しているのは、
rewrite.def で left と right が逆。
同梱されている dicrc が学習時に使用されたものではない。
ひとつ目に関しては 『MeCab』 の設定ファイルのややこしいところで、詳しくはこちらを見てください。
model.def で学習された連接素性を見て気づきました。現状の『UniDic』の連接素性は連濁などの漢字表記内部の読みを当てるために左右非対称な素性を組んでいるのですが、その左右がモデル内部で逆転している。
ふたつ目に関しては eval-size というハイパーパラメータがあるのですが、dicrc には 12。ですが、実際に学習された model.def には 10 と書かれています。
また rewrite.def という(語彙ファイルに書かれた各語を抽象化してまとめ上げる)書き換えルールのファイルがあるのですが、文頭文末記号用の書き換えルールを見ると、dicrc で定義されているものと長さが合わないので、このまま学習していたなら、文頭文末は学習されません。
ですが、model.def をみるとちゃんと学習されているので、明らかに学習後に dicrc が差し代わっています。
unidic/unidic-cwj-202302_full$ head dicrc
dictionary-charset = utf8
config-charset = utf8
cost-factor = 700
max-grouping-size = 10
bos-feature = BOS/EOS,*,*,*,*,*,*,*,*,*,*,*,*,*
eval-size = 12
unk-eval-size = 4
;output-format-type=default
unidic-cwj-202302$ head model.def
eta: 5e-05
freq: 1
C: 1
eval-size: 10
unk-eval-size: 4
charset: UTF-8
-0.3699549369598869 A_A01:0,1,2/0
-0.0043199685966191 A_A01:0,1,2/0,1
0.0000000239862549 A_A01:0,1,2/0,1,2
unidic-cwj-202302$ less rewrite.def
(略)
[unigram rewrite]
BOS/EOS,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,* $1,*,*,*,*,*,*,BOS/EOS,BOS/EOS,BOS/EOS,*,*,BOS/EOS,*,*,*
(略)
[left rewrite]
BOS/EOS,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,* $1,*,*,*,*,*,BOS/EOS,BOS/EOS,BOS/EOS,*,*,*,*,*,*
(略)
[right rewrite]
BOS/EOS,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,* $1,*,*,*,*,*,BOS/EOS,BOS/EOS,BOS/EOS,*,*,*,*,*,*
unidic-cwj-202302$ grep "BOS/EOS" model.def | tail
-0.1151153854874290 W_W01:BOS/EOS/外
0.2806574870025606 W_W01:BOS/EOS/混
0.2299864494459141 W_W01:BOS/EOS/漢
0.3198101667564039 W_W01:BOS/EOS/記号
0.6745702591168128 W_W01:和/BOS/EOS
0.0347456162073289 W_W01:固/BOS/EOS
-0.0864531438693974 W_W01:外/BOS/EOS
0.1310431869549237 W_W01:混/BOS/EOS
0.3649653491536766 W_W01:漢/BOS/EOS
0.3042040670786096 W_W01:記号/BOS/EOS
このあたりの定義ファイルの不具合というのは、使っていると結構よく出くわします。なのでそれを直し、手元で学習を回せる環境を作りたいというのが2つ目のモチベーションです。
では上述した2つのモチベーション、これをどうやって解決していったか。
次回に続きます。