Help us understand the problem. What is going on with this article?

scikit-learn によるナイーブベイズ分類器

More than 1 year has passed since last update.

ナイーブベイズの概要

ナイーブベイズ分類器は特徴ベクトル間に条件付き独立性を仮定したベイズ定理に基づく分類器です。現実の問題では特徴を表す素性同士に何らかの相関が見られるケースが多々ありますが、独立性仮定によって計算量を簡素化・削減し、高速でそこそこの精度を誇る分類器を実装することができます。

ベイジアンとヒューリスティクス

これらを鑑みるとそもそも元より高精度を期待できる分類器ではないですし、諸々の論文等では比較対象として負けるための分類器とまで言う声も聞かれるほどです。多くは独立性を仮定するべきではない問題に適用しているからで当たり前なのですが、筆者の私見としてはナイーブベイズはヒューリスティックな問題に高い実用性を発揮すると思います。例えばテキストマイニングといった完全性を追い求めるのがなかなか難しい分野において、高速である程度の正解率を叩きだす分類器として実用性能が高いでしょう。

ナイーブベイズの亜種

ある程度の独立性を緩和した Semi Naive Bayes といった亜種も多く研究されています。たとえば AODE (Averaged One-Dependence Estimators) などはその代表例です。とはいえ今回はそのような亜種に関する話は他所に置いておきます。

分類器の実装と確率分布

scikit-learn には執筆時点で主に 3 種類のベイズ分類器が実装されています。

ベイズ分類器が仮定する確率分布については前回前々回に書きました。

テストとして 3 つのラベルについてそれぞれ次のような特徴ベクトルを得られたとしましょう。

ラベル 特徴ベクトル
1 [1,2,3,4,5,6,7,8]
2 [1,1,3,4,5,6,6,7]
3 [2,1,2,4,5,8,8,8]

これを教師データとして学習し、テストとして次の特徴ベクトルをラベルに分類します。

テストデータ
[2,2,4,5,6,8,8,8]

正規分布を仮定する

連続変数 x に正規分布 (ガウシアン分布) を仮定する場合、平均を μ 分散を σ^2 とすると分布は次のようになります。

p(x; \mu, \sigma^{2}) = \frac{1}{\sqrt{2\pi\sigma^{2}}}\exp^{\Bigl\{-\frac{(x-\mu)^{2}}{2\sigma^{2}}\Bigr\}}

sklearn.naive_bayes に実装された分類器を利用します。

import numpy as np
from sklearn.naive_bayes import GaussianNB # ガウシアン
X = np.array([[1,2,3,4,5,6,7,8],
              [1,1,3,4,5,6,6,7],
              [2,1,2,4,5,8,8,8]]) # 特徴ベクトル
y = np.array([1, 2, 3]) # そのラベル
t = np.array([2,2,4,5,6,8,8,8]) # テストデータ

clf = GaussianNB() # 正規分布を仮定したベイズ分類
clf.fit(X, y) # 学習をする
clf.predict(t) # => [3]

テストデータは 3 番のラベルに分類されました。

ベルヌーイ分布を仮定する

特徴が 0 と 1 で表されるようなベクトルについてはベルヌーイ分布を仮定します。観測変数が二値であることが前提というわけですね。

p(x;q) = q^{x}(1-q)^{1-x}

実験用のデータはベルヌーイ分布を仮定するのはおかしいですが、あえてコードを書いて動かしてみましょう。

from sklearn.naive_bayes import BernoulliNB
clf = BernoulliNB()
clf.fit(X, y)
clf.predict(t) #=> [1]

多項分布を仮定する

ベルヌーイをコイントスの表と裏に例えるなら、多項分布は複数の面があるダイス (サイコロ) です。すなわち 1, ..., k の数だけ値を取りうるという事になります。ベルヌーイ分布は k=2 の多項分布ととらえても等価です。

from sklearn.naive_bayes import MultinomialNB
clf = MultinomialNB(alpha=1.0, class_prior=None, fit_prior=True)
clf.fit(X, y)
clf.predict([t]) #=> [2]

まとめ

いかがでしたでしょうか。
実際のデータ分析においては、分類器そのものを実装して動かすのは容易であり、実データにフィットする確率分布のモデルを仮定するのが決め手となることがおわかりになったかと思います。

現実的にはうまく確率分布をフィットさせるのはなかなか難しく、特に変化のあるデータについては持続的に観察し分析を継続することが大切です。

dts
コンサルティングから設計、開発、HW/SWの選定、運用、保守までシステムをサポートする総合情報サービス企業です。
http://www.dts.co.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away