大分前にやったのですが、復習もかねて書いてみる。
#このレッスンの概要
Naive(単純) Bayes分類器は教師あり学習の一つで、決定境界(Decision boundary)を決めるもの。
実装が簡単で計算効率がいいらしい。
このレッスンの前半では、入力データを学習用データとテスト用データに分けたり、分類器の性能を図るためにsklearn.metrics.accuracy_scoreを使ったりします。
Video22からは、Naive Bayes文類器の中身を、ガン検査(Cancer Test)を使って解説してくれます。個人的にはこれが大変わかりやすかった。
前提として下記のようなガン検査があると仮定します。
#単純ベイズ分類器の中身説明
<ガン検査の前提>
前提1:ガンにかかっている人は90%陽性(Positive)
前提2:ガンにかかっていない人は90%陰性(Negative)
前提3:ガン罹患率P(c)は0.01(1%)
図にするとこんな感じ。
上の条件で自分が検査を受けて陽性だった場合の、実際に癌にかかっている率は実は8%に過ぎない。どうしてそうなるか見ていく。図の斜線のエリアが検査陽性の集団。この中で、実際に癌にかかっている集団が赤色。直感的にすごく小さいのがわかると思う。
ベイズルールでは
事前確率*テストエビデンス→事後確率
となる。
◆STEP1:事前準備◆
事前確率:P(c) = 0.01 1引く→ P(notc) = 0.99
P(pos|c) = 0.9 1引く→ P(neg|c) = 0.1
P(neg|notc) = 0.9 1引く→ P(pos|notc) = 0.1
※P(pos|c) はprobability of positive given c。c(ガン)の時にpositiveとなる確率という意味。縦棒の後にある事象が起こった場合の縦棒の前の現象(この場合陽性)が起こる確率という意味。
◆STEP2:条件付確率の計算◆
条件付確率を計算すると。。。
P(c, pos) = P(c)P(pos|c) = 0.010.9 = 0.009・・・①
P(notc, pos) = P(notc)P(pos|notc) =0.990.1 = 0.099・・・②
◆STEP3:Normalizerによる事後確率計算◆
条件付確率で、
ⅰ)検査陽性、かつ、ガンにかかっている確率
と、
ⅱ)検査陽性、かつ、ガンにかかっていない確率
Normalizer : P(pos)=P(c|pos)+P(notc|pos) = 0.108・・・③
求めたいのはP(c|pos)
P(c|pos) = ①/③ = 0.0833
P(notc|pos) = ②/③ = 0.9167
上記を足すと1になる。
なぜ、Normalizerで割れるのかというと、検査陽性の場合はP(c|pos)、P(notc|pos)で網羅できているから。
これで、もし検査陽性だとしても、ガンである確率は0.08(8%)であることがわかる。上記図の斜線部分をみると直感的にわかる(比率はすみません)
つまり、
事後確率P(c|pos) = \frac{P(pos,c)}{P(pos)} = \frac{P(c)*P(pos|c)}{P(pos)}
#単純ベイズ分類器の応用~texis learning~
クリスとサラがいて、彼らが使うLove, Deal, Lifeの確率はそれぞれわかっている場合、"Love Deal"の文章は、クリスかサラのどちらが書いたか分類したい場合。
単純ベイズ分類器を使うと下記のようになる。
余談だが、なぜ**単純(甘い)**ベイズ分類器なのかは、語順を無視している為らしい。
#Mini project
事前にPreprocessされたメールデータを学習して、クリスの文章か、サラの文章化に分類する。preprocessについては下記参照。
コード
#########################################################
### your code goes here ###
import numpy as np
from sklearn.naive_bayes import GaussianNB
from sklearn.metrics import accuracy_score
clf = GaussianNB()
t0 = time()
clf.fit(features_train, labels_train)
print "training time:", round(time()-t0,3),"s"
t1 = time()
pred = clf.predict(features_test)
print "predicting time:", round(time()-t1,3),"s"
accuracy = accuracy_score(labels_test, pred)
print(accuracy)
<出力>
no. of Chris training emails: 7936
no. of Sara training emails: 7884
training time: 3.9 s
predicting time: 0.752 s
0.9732650739476678
学習よりも分類のほうが圧倒的に早いね。
features_trainは15820行、3785列の行列。
features_testは1758行、3785列の行列。
3785列は出現した全単語の数。
行列の中身は各単語の重みづけ(重要度)が入っている(0.632とか)
つまり、全email 15820+1758 = 17578のメールの中に記述された各単語が3785個あるということですね。
この辺の処理は、Lesson11: Text Learning まとめ みればどんなのがわかるかも!
ドキュメンテーション:sklearn.naive_bayes.GaussianNBはご参考
#感想
Lesson2をまとめたのがLesson11をまとめた後だったので、事前処理も含めて復習になってよかった。ベイズルールも何となく釈然としないまま日々を過ごしていたけど、理解できた気がする。