#TokyoNLP で「∞-gram を使った短文言語判定」を発表しました

TokyoNLP 第8回に のこのこ参加。主催者の id:nokuno さん、発表者&参加者のみなさん、そして会場を提供してくださった EC ナビさん改め VOYAGE GROUP さん& @ajiyoshi さん、お疲れ様でした&ありがとうございました。


今回は「∞-gram を使った短文言語判定」というネタを発表。「短文言語判定」って、要は「このツイートは何語?」ってこと。
こちらが資料。


そして実装したプロトタイプ ldig (Language Detection with Infinity-Gram) とモデル(小)はこちらで公開。


言語判定とは「文章が何語で書かれているか」を当てるタスクで、以前一度 TokyoNLP #2 で language-detection (以降 langdetect)という言語判定 Java ライブラリを発表した。
でも langdetect は twitter のような短い文章が苦手で、またナイーブベイズを使っていたのでメタデータなどの非独立性の高い(というか独立性の読めない)素性を加えにくいという難点があった。
そこで今回は短い文書でも高い精度(99%以上)で言語判定するための方式とそのプロトタイプ実装を作ってみた、という内容になっている。


といっても、なにやら難しげなタイトルに反して機械学習の難しい話は少なめ(ほとんど全部はしょったのでw)。実際、数式も一つも出てこない。特に極大部分文字列のところはなかなかわかりやすく書けたんじゃあないか、とか自画自賛してみるw
また後半はいろんな言語をコンピュータで扱う場合の雑学集みたいなものなので、こちらは本当に何の知識もなくても楽しんでもらえると思う。


今回の ldig では、いくつか飛び道具は使っているものの、多クラスロジスティック回帰という非常にポピュラーで枯れつつある手法がベースになっている。
それでも十分高い精度が出るのは、そこそこの大きさのコーパス(地道にツイートに言語ラベルを振り続けて作った)と、対象言語それぞれに特有な事情を考慮した正規化をきめ細かくやっているから。逆にそれがなければ、どんなに複雑で最新な機械学習アルゴリズムを持ってきても、99% の精度は目指すことも出来ないと思う。
ちょうど同じ TokyoNLP #8 で @zzzelch さんが「機械学習は1割、データが9割」とおっしゃられていたが、その点はまさに同感(機械学習の割合は、もうちょびっとくらい増やしてもいいかもしれないけどw)。


あとは質疑応答や休み時間や懇親会でいただいた質問を、憶えている範囲で……といっても、あんまり憶えてなかったので(すいませんんん!)、nokuno さんのメモを参考にさせていただきつつ。

複数言語を含むツイートを判定すると?

現状は与えられた文章全体で確率を計算している。分割が必要なら ldig を呼ぶ側で行う。
ldig で勝手に「ここまでは○○語、ここからは××語、……」とできたらもちろんいいが(願望)、今のところノーアイデア
仮に素性の傾向を部分的に見て分割するべき可能性を判定するなどのアプローチを考えてみると、例えば you に出てくる -ou という綴りは「英語らしくない」など、単語単位で見たら「その言語らしさ」はかなりのバラツキが出てしまうことがわかっており、おそらくもう1アイデア必要と感じている。

スペルミスがあったら?

実際スペルミスは非常に多いが、1箇所間違っているくらいなら特に問題ない(さすがに絶対間違わないという意味ではなく、99% という精度を目指すレベルで考えても誤差の範囲、ということ)。
それより you => u, for => 4 や末尾の母音を省略するような、ショートメッセージ特有の短縮表現の方がはるかに頻度が高くて問題になっている。現状ではそういった表現ごと学習することで、できるだけ誤判定を減らそうとしているが、それでも間違えてしまう極端な表現(人間が見ても「………………わかるか!」と叫んでしまうくらいw)も少なからずはある。

クエリの言語判定はできる?

手元にデータがないので試してはいないが、クエリはもともと短い上に、固有名詞が多くて機能語が少ない(という印象)ので、正直難しいと思う。いいとこ 90% ってところかと。

現実の言語分布を反映させると精度は上がる? 下がる?

やってみないとわからないが、なんの工夫もしないでそのまま適用したら下がるかもしれない。
というのも、現実の分布では英語がダントツに多いわけだが、実は ldig は、デンマーク語・ノルウェー語ほどではないにしても、英語が少し苦手。原因はおそらく英語の語彙は他のほとんど全ての言語にも出てくるので、英語に与えられる確率が微妙に下がっているせいではないか、と推測している。
もちろん、もともと「英語が多い」といった分布を勘案できるモデルにすれば、精度は上げられると思う(当然だけどね)。そこらへん含め、おもしろい&現実に即した観点だと思うので、できれば確認してみたいと思う。

メタデータを使ったら精度もっと上がるのでは?

メタデータはアプリケーションやドメイン固有のものなので、最初からそれに頼ってしまうと他の分野で使えなくなってしまう。というわけで、今回はあくまで素のテキストからどこまで目指せるか、という点にしぼっている。
今回はロジスティック回帰をベースとしており、そういった非独立性の高い素性を入れたモデルを考えることもできるはずなので、現実の利用シーンではそういったことも考えていくと思う。有用なメタデータを捨てるなんてもったいなさすぎるしね!w

実際の素性の数は? 全部を使うとさすがに多すぎるのでは?

その場では曖昧な記憶の数字を答えてたが、ちゃんと確認したものを記す。
訓練データ(小+大)を食わせたときの「頻度2以上の極大部分文字列」は約1000万。
そこから「頻度が8以上」という足切りをしつつ(この8という数字はいくつか試行錯誤した中から選んだ現時点での閾値)、ラテン文字を含む素性に絞って 90万。
正則化なしの SGD を8周回して、パラメータが有効な範囲(絶対値>10e-7)に入ったのが 70万。
L1 正則化を 2周回して、つぶれなかった残りが 50万。


素性を頻度で足切りしているのは、もちろん素性が多すぎると学習に時間がかかるという理由もあるが、頻度の少ない素性も入れてしまうと配布したモデルから元のツイートが容易に再現できてしまう(というか、まんま入ってしまう)という懸念があるからでもある。

ラベル付きコーパスは配布しないの?

権利問題が……と答えたら、ラベルと ID を配布して、ツイートの取得はそれぞれが行うという手があるよ、と。あーそういえばそうやって配布しているコーパスあったあった。自分もそうすればいいという頭がなかった……。
今まで作ったコーパスはそこら辺の情報捨ててしまってたのでもう無理だけど、今後作る分は ID を保持して「ラベル+ID」で配布できるようにしようと思う。

skip n-gram とかは?

ありだと思う。ただ、有効な素性間の距離がかなり長いことが予想されるので、PMI とか見て有効な素性の組みを探すとかできないかという方向で構想中。

アノテーションってどうやってるの? どんなツール使ってる?

秀丸で。