2012年06月05日

形態素解析で中黒(・)ってカタカナと記号、どっちで扱った方がいいのかな

と、ふと思った。

例えばMeCabで「ナカグ・ロー」という未知語を形態素解析すると、1つの単語として解析される。(IPA辞書使用)

$ echo ナカグ・ロー | mecab
ナカグ・ロー	名詞,固有名詞,組織,*,*,*,*

「ナカグ」と「ロー」を繋ぐのが中黒ではなくイコールだった場合は、下記のように分割される。

$ echo ナカグ=ロー | mecab
ナカグ	名詞,一般,*,*,*,*,*
=	記号,一般,*,*,*,*,=,=,=
ロー	名詞,固有名詞,人名,姓,*,*,ロー,ロー,ロー
EOS

中黒を使った場合でも、未知語じゃない場合はこんな風になる。

$ echo ジョン・ドウ | mecab
ジョン	名詞,固有名詞,人名,名,*,*,ジョン,ジョン,ジョン
・	記号,一般,*,*,*,*,・,・,・
ドウ	名詞,固有名詞,組織,*,*,*,*

上記を見て分かる通り、中黒はIPA辞書的には「記号,一般」で登録されている。


なぜ「カタカナ - 中黒 - カタカナ」が一語になり、「カタカナ - イコール - カタカナ」が分割されるのか。

理由は、中黒がUnicode的にはカタカナのブロックに登録されているから。具体的には0x30FB。長音(0x30FC)「ー」の1つ手前に登録されている。

IPA辞書のchar.defを見てみると、以下のような定義がある。

0x30A1..0x30FF  KATAKANA

0x30A1〜0x30FFはカタカナとして扱われるらしい。0x30FBはこの中に含まれている。これを下記のように変更すれば、中黒は記号扱いになる。

0x30A1..0x30FA	KATAKANA
0x30FB	SYMBOL
0x30FC..0x30FF	KATAKANA

試しに上記のようにchar.defを書き換えて、再度辞書を入れ直してみたところ、下記のように結果が分割されるようになった。

$ echo ナカグ・ロー | mecab
ナカグ	名詞,一般,*,*,*,*,*
・	記号,一般,*,*,*,*,・,・,・
ロー	名詞,固有名詞,人名,姓,*,*,ロー,ロー,ロー
EOS

個人的にはナカグ・ローは記号として扱って分割して欲しい気がする。ただ、未知語をまとめる際に、ひとつなぎにまとめてしまいたいこともある。一般的にはどうなんだろ。


2012/06/05追記

他の形態素解析器とか辞書を使ってみたところ、下記のうような結果になった。

IPA辞書
表層文字組成情報種類
 BOS/EOS,*,*,*,*BOS
ナカグ・ロー名詞,固有名詞,組織,*,*未知語
 BOS/EOS,*,*,*,*EOS

NAIST辞書
表層文字組成情報種類
 BOS/EOS,*,*,*,*BOS
ナカグ・ロー名詞,一般,*,*,*未知語
 BOS/EOS,*,*,*,*EOS

UniDic現代語版
表層文字組成情報種類
 BOS/EOS,*,*,*,*BOS
ナカグ・ロー名詞,普通名詞,一般,*,*未知語
 BOS/EOS,*,*,*,*EOS

UniDic近代文語版
表層文字組成情報種類
 BOS/EOS,*,*,*,*BOS
ナカグ・ロー名詞,固有名詞,人名,一般,*未知語
 BOS/EOS,*,*,*,*EOS

JUMAN辞書
表層文字組成情報種類
 BOS/EOS,*,*,*,*BOS
ナカグ名詞,人名,*,*,*未知語
特殊,記号,*,*,・0
ロー名詞,組織名,*,*,*未知語
 BOS/EOS,*,*,*,*EOS

Yahoo形態素解析
表層文字組成情報種類
ナカグ名詞,名詞,*,ナカグ,ナカグ 
特殊,単漢,*,・,・ 
ロー名詞,名形,*,ロー,ろー 

lucene-gosen
表層文字組成情報種類
ナカグ未知語 
記号-一般 
ロー名詞-固有名詞-人名-姓 

Kuromoji
表層文字組成情報種類
ナカグ名詞,一般未知語
記号-一般 
ロー名詞-固有名詞-人名-姓 

Gomoku
表層文字組成情報種類
ナカグ・ロー名詞,固有名詞,組織,*,*,* 

KyTea
表層文字組成情報種類
ナカグ名詞 
補助記号 
ロー名詞 

Yahoo形態素解析、lucene-gosen、Kuromojiあたりは記号として扱っているらしい。

じゃ、自分も大手を振って記号として扱ってしまえばいいか。


ちなみにJUMAN辞書のchar.defには「0x30FB NUMERIC」と指定してあった。SYMBOLでなくNUMERICなんだ。

lucene-gosenでは下記のように明示的に0x0FBを除外しているコードを見かけた。

c >= 0x30A0 && c <= 0x30FF && c != 0x30FB

Kuromojiもやはり個別に0x03FBをKATAKANAから除外している箇所があった。

if (codePoint == 0x30FB) {
  characterClassName = "SYMBOL";
}