Hatena::ブログ(Diary)

Risky Dune

2013-02-12

scikit.learn手法徹底比較! ナイーブベイズ編

scikit.learnの分類手法を比較するこの企画. 今回はナイーブベイズを検証する.

ナイーブベイズはi番目の入力ベクトルの各次元が, クラスラベルが与えられると互いに独立, すなわち

となると仮定する分類手法である. ただし, の次元数, はi番目の入力ベクトルのj個目の要素を指す.

学習段階では訓練データから各クラスjごとに確率分布を学習し, 分類する際にはが最大になるようなクラスに分類する.

scikit.learnが提供するナイーブベイズのクラスは

  • Gaussian Naive Bayes
  • Bernoulli Naive Bayes
  • Multinomial Naive Bayes

の3つがある.

Gaussian Naive Bayesは分布ガウス分布で表現するクラスである. 訓練データからこのガウス分布パラメーターを学習する.
Bernoulli Naive Bayesは入力ベクトルの要素が[0,1]の2値を取る場合のナイーブベイズである. 分布はベルヌーイ分布で表現される.
Multinomial Naive Bayesでは, 入力ベクトルの要素がi番目のデータにおいてj個目の要素が何回出現するか(例えば, ある記事において単語soupが何回出現しているか)を表す. なんかテキスト分類とかに使われているらしい.

今回は入力ベクトルとして各次元が画素の値(0-255)なので使えそうなのはGaussianとBernoulliである. Bernoulliの場合はオプション閾値を設定すると, 入力ベクトルの値が閾値以上の場合は1, 以下なら0として扱う.

なお入力データは正規化している.

Gaussian Naive Bayes

コンストラクタ引数がないシンプルなクラスnaive_bayes.GaussianNBを用いる.

簡単に使えるかと思いきや

/usr/lib/pymodules/python2.7/sklearn/naive_bayes.py:174: RuntimeWarning: divide by zero encountered in log n_ij = - 0.5 * np.sum(np.log(np.pi * self.sigma_[i, :]))

というエラーメッセージが発生し, 真っ当に動作しなかった.

エラーメッセージから察するに, おそらく分散の無い要素(特定のクラスで常に一定の値を取る要素)が存在する場合, 0割りが発生しうまく動作しないのだろう.

そこで, とりあえずの解決策として, 全要素である程度の分散を持つために元のデータにガウス分布から生成したノイズを足しあわせた. その結果正常に動作するようになったが, データ数1万のケースでも分類精度が75%程度でしかもバッドノウハウにも程がある感じだったので, 詳細な検証は取りやめた.

Bernoulli Naive Bayes

調整するパラメーターは次の3つである.

  • fit_prior : 事前分布(クラスごとのデータ数の偏り)を考慮するかどうか
  • alpha : 各次元において1を取る確率に関する事前分布を制御する
  • binarize : 元のデータを2値化するときに用いる閾値

alphaに関しては詳細な説明が必要だろう. alphaを用いることで, クラスcに属するデータのj番目の要素が1となる確率は

と学習される. ここでは学習データにおいてクラスがcである要素の数, は学習データにおいてクラスがcでかつj番目の要素が1となる要素の数である. alphaが小さい程, この確率は純粋なデータ内の比率に近づく.

元のデータのラベル比率が均等に近いためか, fit_priorはTrueにしてもFalseにしてもあまり結果が変わらなかったため, 以下fit_priorはTrueと設定する.

クロスバリデーションによってalphaをnumpy.logspace(-5, 0, 6), binarizeをnp.linspace(-0.2,1.2,6)から選んだ. その選んだパラメーターに対して得られた結果は次の通り.


訓練データ数正答率学習時間(sec)平均予測時間(msec)
10000.81340.03771495820.0484575987
30000.81660.12472295760.0482898951
50000.81520.2213268280.0484192133
100000.81570.44491004940.047160697
200000.81790.9198238850.0482817888

正答率が見事に上がらないw. やはりモデルの仮定に無理があるためか, 2値化の際の情報の損失が激しいのか. 一方, 学習時間はデータ数に対して線形である. また平均予測時間はデータ数に影響を受けない. これらはアルゴリズムを想像すればまあ納得の行く結果である.

クロスバリデーションをして得た感じとしては, 学習時間は全くパラメーターの影響を受けない. また正答率もalphaなら0から1, binarizeなら0から1という常識的な値から選んでいればそこまで変化しなかった.

まとめ

その性能の低さから「論文で負けるためにある分類器」と言われることもあるナイーブベイズさん. この問題でも性能は低かった. だがテキスト分類など一部の分野では使われており, また学習時間も超短いため, 活躍する領域があるんだろう. ナイーブベイズの仮定がうまく効いてくるデータセットでも試してみたい.

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

トラックバック - http://d.hatena.ne.jp/saket/20130212/1360678478