yasuokaの日記: 日本語形態素解析エンジンnagisaは古典中国語(漢文)を学習できるのか 2
ネットサーフィンしていたところ、nagisaという日本語形態素解析エンジンを見つけた。端的には、python3のdynetで、日本語の単語切りと品詞付与をおこなうエンジンなのだが、自前でUniversal Dependenciesから機械学習する方法も示されている。だとすると、UD_Classical_Chinese-Kyotoから古典中国語(漢文)を学習する、というのもアリなのではないかと思い、ちょっと試してみることにした。
% pip3 install nagisa
% git clone https://github.com/UniversalDependencies/UD_Classical_Chinese-Kyoto.git
% awk '{if(NF==10&&$1~/^[1-9][0-9]*$/)printf("%s\t%s\n",$2,$5);else if($0=="")printf("EOS\n")}' UD_Classical_Chinese-Kyoto/lzh_kyoto-ud-train.conllu > lzh_kyoto-ud-train.txt
% awk '{if(NF==10&&$1~/^[1-9][0-9]*$/)printf("%s\t%s\n",$2,$5);else if($0=="")printf("EOS\n")}' UD_Classical_Chinese-Kyoto/lzh_kyoto-ud-dev.conllu > lzh_kyoto-ud-dev.txt
% awk '{if(NF==10&&$1~/^[1-9][0-9]*$/)printf("%s\t%s\n",$2,$5);else if($0=="")printf("EOS\n")}' UD_Classical_Chinese-Kyoto/lzh_kyoto-ud-test.conllu > lzh_kyoto-ud-test.txt
% python3
>>> import nagisa
>>> nagisa.fit(train_file="lzh_kyoto-ud-train.txt",dev_file="lzh_kyoto-ud-dev.txt",test_file="lzh_kyoto-ud-test.txt",model_name="lzh_kyoto-nagisa")
Epoch LR Loss Time_m DevWS_f1 DevPOS_f1 TestWS_f1 TestPOS_f1
1 0.100 8.880 0.391 98.56 79.15 99.54 81.40
2 0.100 3.602 0.388 98.60 83.63 99.59 84.91
3 0.100 2.705 0.388 98.79 85.25 99.67 86.37
4 0.050 2.304 0.351 98.73 85.76 99.67 86.37
5 0.050 1.771 0.389 98.87 86.62 99.61 87.40
6 0.050 1.593 0.389 98.94 86.78 99.48 87.91
7 0.025 1.472 0.354 98.81 86.55 99.48 87.91
8 0.025 1.285 0.391 98.94 86.87 99.54 87.97
9 0.012 1.207 0.354 98.87 87.04 99.54 87.97
10 0.006 1.128 0.354 98.83 87.08 99.54 87.97
XPOS(第5フィールド)の機械学習でF1値が87.97だとすると、UDPipeの87.8%と比べても、まあ、遜色ない値だ。とりあえず「不入虎穴不得虎子」を、形態素解析してみよう。
>>> lzh=nagisa.Tagger(vocabs="lzh_kyoto-nagisa.vocabs",params="lzh_kyoto-nagisa.params",hp="lzh_kyoto-nagisa.hp").tagging
>>> s=lzh("不入虎穴不得虎子")
>>> print(s)
不/v,副詞,否定,無界 入/v,動詞,行為,移動 虎/n,名詞,主体,動物 穴/n,名詞,固定物,地形 不/v,副詞,否定,無界 得/v,動詞,行為,得失 虎/n,名詞,主体,動物 子/n,名詞,人,関係
一字ずつ全てが切られていて、品詞も妥当なようだ。次に「有兄子曰甫」を、形態素解析してみよう。
>>> s=lzh("有兄子曰甫")
>>> print(s)
有/v,動詞,存在,存在 兄子/n,名詞,主体,書物 曰/v,動詞,行為,伝達 甫/v,動詞,描写,態度
うーん、「甫」という人名を知らないのは、まあ仕方ないとしても、「兄」の「子」をひとまとめにして「n,名詞,主体,書物」だと思ってるのは、どういう勘違いなのだろう。ならば「若之何子之不言也」を、形態素解析してみよう。
>>> s=lzh("若之何子之不言也")
>>> print(s)
若/v,動詞,行為,分類 之/n,代名詞,人称,止格 何/n,代名詞,疑問,* 子/n,代名詞,人称,他 之/p,助詞,接続,属格 不/v,副詞,否定,無界 言/v,動詞,行為,伝達 也/p,助詞,句末,*
さすがに「何」と「子」がちゃんと分かれていて、しかも「之」の品詞も見分けている。どうやら、品詞を階層処理していない(コンマに意味がない)ようなので、品詞の末尾にLEMMAやGlossを付けておく、といった小技は無理そうだ。とりあえずは「甫」を何とかすべく、外部辞書で人名を大量に教えこみたいところなのだが、 nagisa.fit のdict_fileのフォーマットって、train_fileとかと同じなのかしら?
udkanbunのMeCab辞書 (スコア:2)
udkanbunのMeCab辞書をdict_fileに追加してみたところ、F1値が88.05になって、解析結果が改善されました。
でも、学習がうまくいってないのか、Epoch 2以降でF1値が変化してないのです。うーむ。
nagisa.fitのパラメータ (スコア:2)
dim_tagembとdecayというパラメータを教えていただいた [github.com]ので、とりあえず試してみました。
F1値は90.07に改善されてるのですけど、「有兄子曰甫」については、むしろ悪化してしまいました。うーん、どこかミスったのかな…。