2
5

More than 5 years have passed since last update.

Lesson2:Naive Bayes まとめ Intro to Machine learning@ Udacity

Last updated at Posted at 2019-02-28

大分前にやったのですが、復習もかねて書いてみる。

このレッスンの概要

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%)
図にするとこんな感じ。
NaiveBayes.jpg

上の条件で自分が検査を受けて陽性だった場合の、実際に癌にかかっている率は実は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.01*0.9 = 0.009・・・①
P(notc, pos) = P(notc)*P(pos|notc) =0.99*0.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%)であることがわかる。上記図の斜線部分をみると直感的にわかる(比率はすみません)

アルゴリズムをまとめると下記の図のようになる。
NaiveBayes_アルゴリズム.jpg

つまり、

事後確率P(c|pos) =  \frac{P(pos,c)}{P(pos)} = \frac{P(c)*P(pos|c)}{P(pos)}  

単純ベイズ分類器の応用~texis learning~

クリスとサラがいて、彼らが使うLove, Deal, Lifeの確率はそれぞれわかっている場合、"Love Deal"の文章は、クリスかサラのどちらが書いたか分類したい場合。

単純ベイズ分類器を使うと下記のようになる。

NaiveBayes_text_learning.jpg

余談だが、なぜ単純(甘い)ベイズ分類器なのかは、語順を無視している為らしい。

Mini project

事前にPreprocessされたメールデータを学習して、クリスの文章か、サラの文章化に分類する。preprocessについては下記参照。

コード

nb_author_id.py
#########################################################
### 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をまとめた後だったので、事前処理も含めて復習になってよかった。ベイズルールも何となく釈然としないまま日々を過ごしていたけど、理解できた気がする。

2
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
5