見出し画像

短単位自動解析用辞書を作る(1)

モチベーション

問題意識、問題提起もしくは Issue とも言いますが、スタートとなったモチベーションはこの2つ。

1. 最新版の短単位自動解析用辞書『UniDic』のサイズを小さくしたい
2. 最新版『解析用UniDic』に問題があるので手元で直したい

短単位自動解析用、すなわち『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.def22MB です。
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.def5.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』に問題があるので手元で直したい、です。
判明しているのは、

  1. rewrite.def で left と right が逆。

  2. 同梱されている 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つのモチベーション、これをどうやって解決していったか。
次回に続きます。


この記事が気に入ったらサポートをしてみませんか?