ナイーブベイズ再考

 ナイーブベイズは単純ベイズともいうそうな.ナイーブのウムラウトが気になるのかね.


 さて,以前非常に冗長な表現でナイーブベイズを説明しましたが,
今度はシンプルに,実装したときに思ったことなどを.


 昨日は休日だったので,遊びでComplement Naive Bayesも組みました.
こいつは補集合を使うナイーブベイズです.



 さて,ナイーブベイズはこんなposteriorを推定する問題でした.

p(class | \mathbf{words})\propt p(\mathbf{words} | class)p(class)





1.priorをどうしよう


 上の式で言えば,p(class)のところ.他の人たちはどういう設定をしているのか気になった.
軽く調べたところ,実装のためになりそうな記述はあまりありませんでした.

集合知プログラミング

集合知プログラミング

この本には,「簡単だぜジョニー.クラスに属するドキュメント数÷総ドキュメント数さ」
みたくさらっと書かれていたけれど(悪意はないです)


 気に入らん.ドキュメント中の単語数はクラスに大きく依存する可能性もあるのだから,ここは,


クラスに属する単語数÷総単語数


という計算で行いました.比較実験はとくにしていませんので実験的な裏づけは特に無いです.






2.スムージングをどうしよう


 テストデータを,あるクラスに属するかどうか判定するときのお話.
そのクラスでは一度も出現したことの無い単語が現れた場合,確率が0になりますね.
そうすると,テストデータの確率が丸ごと0になりますね.


 これがゼロ頻度問題です.


 そして,そのような頻度ゼロのデータについても
ある程度の確率値を割り当てておくという操作がスムージングです.


 話はわかるのだが,そもそも僕はノンパラベイズの人なので,
ヒューリスティックなスムージングは,通り一遍の手法しか知りません
良い機会なので実装してみました.
参考書は,もう僕のバイブルになっている北さんの確率的言語モデル

言語と計算 (4) 確率的言語モデル

言語と計算 (4) 確率的言語モデル


 とりあえず,加算スムージング法を実装しました.以下説明.


 ある単語がk回出現する場合,普通は確率値を
\frac{k}{n}
と計算するところですが,加算スムージングしたいときは
\frac{k+\alpha}{n + V\alpha}
とします.
Vは総語彙数で,αは実数.


 ナイーブベイズでは,Vをどうするか微妙に悩むところですが,
トレーニングデータとテストデータこれまで出てきた総語彙数でいいと思います.
存在しうるすべての単語にprior(みたいなもの)が乗っていて欲しいところですし.


 αが1のときはラプラススムージングといいます.
それを実数に一般化したのがリッドストーンスムージング,または加算スムージング.
日本では一緒くたにされてラプラススムージングといわれているみたいですね.
http://en.wikipedia.org/wiki/Additive_smoothing


 α値は適当に,0.5あたりで.





3.いろいろモデルがあるぞ


 普通,ナイーブベイズで検索すると出てくるナイーブベイズは,
テストデータに複数同じ単語が出てきた場合,その確率を出てきた回数だけ
掛け算してデータの確率を計算します.


 でも,出た,出ないという情報だけ用いて,
回数については問わないモデルもあるみたいです.


 前者を多項モデル(Multinomial model),
後者を多変数ベルヌーイモデル(Multivariate Bernoulli model)というみたいです.

 直感的には前者の方が性能よさそうですが,僕の実験では大差ありませんでした.
比較した論文によると,語彙数が増えるに従い,多項モデルの方が,
多変数ベルヌーイモデルに比べ性能が高くなるらしいです.


 語彙数の少ないことが明らかな環境では,
計算量的にベルヌーイの方が高速なのでいいかもしれませんね.


 あと,ComplementNaiveBayesモデルは,あるクラス以外のクラスの情報すべてを使い,
そのクラスにデータが属さない確率を計算するだけ.




4.で,何に使おう


 これが一番困った.ひとしきり遊んで,F値計算するルーチンまで書いたけど,どうしよう.


とりあえずテストしたい.何かコーパスはないのか.
探してみると,こんなすばらしいものが.
http://spamassassin.apache.org/publiccorpus/


 easy_spamとhamでトレーニングして,別なeasy_spamとhamで評価してみた.
F=0.9くらい.バグかな.ヘッダ情報とかも乗ってるにしても,良すぎる.


 で,相変わらず,どうしようこれ.ソース公開しても仕方が無いので,とりあえず放置.





 というわけで,なかなか面白かったのですが,やはりスムージングの部分が気に入らなすぎます.
p(class | \mathbf{words})\propt p(\mathbf{words} | class)p(class)


 これって結局Unigram(Bag of words)確率の積をとっているだけだから,
UnigramをDirichlet Process,もしくはPitman-Yor Processで表現したモデルにすることができるし,
そうすればスムージングのあれこれも解決するなぁ.


 あと,Unigramだけでなく一般のn-gramにも拡張できるなぁ.
さらに,どの単語が"効いているのか"の推定とかやっても面白そう.
でもきっと,誰かがやっているんでしょうが…





 その内暇ができたらやります.



 あ,あと役に立った参考文献.
このくらいの話なら論文が一番分かりやすい気がします.
情報の信頼性も高いし.


多項モデル,多変数ベルヌーイモデルについて
http://www.cs.cmu.edu/~knigam/papers/multinomial-aaaiws98.pdf


Complement Naive Bayesについて
http://people.csail.mit.edu/jrennie/papers/icml03-nb.pdf
朱鷺の杜もわかりやすいなぁ
http://ibisforest.org/index.php?complement%20naive%20Bayes


スムージングについては,上で挙げた北さんの本.