Lesson15: Evaluation Metricsまとめ Intro to Machine learning@Udacity

#Lesson15の概要
このレッスンではどのように機械学習を評価するかを議論していく。

#内容
シンプルMetric

```math
精度 =  \frac{正しいクラスでラベル付けされたitems}{そのクラス内のすべてのitems}
```
だそうですが、どんな場合でも「精度」が評価指標としてよいわけではない。
例えば下記のような場合。

・skewed classの場合
例えば2クラス分類で、片方がごく少数の場合、上の精度の式だと分類しなくても、かなり高い値が出てしまう。なぜなら、数が多いほうのクラスに大半ば分類されるから。

・無実であると推測する人を間違えたい（本当は有罪）場合
間違えるなら、本当は有罪なんだけど、「無実である」と推測を間違えたい。なぜなら、無実である人を「有罪である」と判断したくないから。つまり、「有罪」と判断した人は、ほぼ100%有罪なのに対し、「無実である」と判断した人の中には、多くの「本当は有罪の人」が混じっている。この場合精度を見ただけでは、このようになっているかどうか判断できない。

・有罪であると推測する人を間違えたい（本当は無実）場合
間違えるなら、少しでも可能性のある人は「有罪である」と推測したい。例えば関係可能性者リストを作って、その後さらに調査を進めるときとか。この場合精度を見ただけでは、このようになっているかどうか判断できない。


##混同行列：Confusion Matrix

|||実際のクラス||
|:-:|:-:|:-:|:-:|
|||+|-|
|分類器の予測|+|a(tp)|b(fp)|
||-|c(fn)|d(tn)|

※tp:true positive, fn:false negative, fp:false positive, tn:true negative
fpは真のクラスはnegative
fnは真のクラスはpositive
このfp, fnが混乱しやすいからconfusion matrixなのか笑。

**recall:再現率**・・・実際に陽性な全サンプルのうち、分類器が陽性と判定する率。→インプットがすべて陽性の場合のアウトプット(分類結果)の正しさ。
(sensitivity:感度とも呼ばれる)

```math

recall = \frac{a(tp)}{a(tp)+c(fn)}

```
recallは分子・分母の真のクラスが全部プラス！

**precision：適合率**・・・分類器が陽性と判断したサンプルのうち、実際に陽性なサンプルの率。→アウトプットがすべて陽性の場合のアウトプット(分類結果)の正しさ。


```math

precision = \frac{a(tp)}{a(tp)+b(fp)}

```

Precisionは真のクラスが分母のfpのみマイナス！

[機械学習概論:3.1.3 混同行列を理解する](https://aidemy.net/courses/2010/exercises/Sy2YnLsLeG)を参考にさせていただきました。



#Mini-Project
今回は、[lesson14:Lesson14: Validationまとめ](https://qiita.com/Allovertom/items/1847a7fc9b1e8fca1965)で使った、validate_poi.pyの決定木を使ってPOIを分類したソースコードをevaluation/evaluate_poi_identifier.pyにコピーすることから始まる。

[sklearn.metrics.confusion_matrix](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.confusion_matrix.html)を参照して、下記のようなソースコードを書いた。

```python
import pickle
import sys
sys.path.append("../tools/")
from feature_format import featureFormat, targetFeatureSplit

data_dict = pickle.load(open("../final_project/final_project_dataset.pkl", "r") )

### add more features to features_list!
features_list = ["poi", "salary"]

data = featureFormat(data_dict, features_list)
labels, features = targetFeatureSplit(data)


### your code goes here##
##copied from lesson14
from sklearn import tree
from sklearn.model_selection import train_test_split


X_train, X_test, y_train, y_test = train_test_split(\
	features, labels, test_size=0.3, random_state=42)


clf2 = tree.DecisionTreeClassifier()
clf2 = clf2.fit(X_train, y_train)
score2 = clf2.score(X_test, y_test)
print score2 

##Added in this lesson15
pred = clf2.predict(X_test)
from sklearn.metrics import confusion_matrix
tn, fp, fn, tp = confusion_matrix(y_test, pred).ravel()
print (tp, fn, fp, tn)#Quiz31

```
◆結果◆
0.7241379310344828
(0, 4, 4, 21)

だが結局混乱したので生データ見てみた。
```python

pred, y_test
```

◆結果◆
(array([0., 0., 0., 0., 1., 0., 0., 0., 0., 0., 0., 1., 0., 0., 0., 0., 0.,
        0., 0., 1., 0., 1., 0., 0., 0., 0., 0., 0., 0.]),
 [0.0,
  0.0,
  0.0,
  0.0,
  0.0,
  0.0,
  0.0,
  0.0,
  0.0,
  0.0,
  0.0,
  0.0,
  0.0,
  0.0,
  0.0,
  0.0,
  0.0,
  0.0,
  0.0,
  0.0,
  0.0,
  0.0,
  1.0,
  0.0,
  1.0,
  1.0,
  0.0,
  1.0,
  0.0])

おおー！やっぱりtpはないね。さっきの混同行列はあっていた！

次recallとprecision
参照
[sklearn.metrics.recall_score](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.recall_score.html)
[sklearn.metrics.precision_score](https://scikit-learn.org/stable/modules/generated/sklearn.metrics.precision_score.html)

cmdに下記入力

```python
from sklearn.metrics import recall_score
from sklearn.metrics import precision_score
recall_score(y_test, pred)
precision_score(y_test, pred)
```
◆結果◆
0.0
0.0

よく考えたら、tp=0だから、両方ゼロになって当然だよね。なんで事前にわからなかったんだろう。


###Quiz34~37は下記で対応

```python

from sklearn.metrics import confusion_matrix
true_labels = [0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0]
predictions = [0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1]
tn, fp, fn, tp = confusion_matrix(true_labels, predictions).ravel()

```
Quiz41：勉強になった！
〇〇、△△に当てはまるものをrecall/precisionから選ぶ。
学習した分類器は高い〇〇はないけれど、高い△△はある。意味は、POI(真のクラスが+のデータ)が来たときは、ほとんどすべて検出できる。ただ、悪い点としては、non-POI(真のクラスは-)が来たときは、時々false positive(+と分類)してしまう。

答え：
〇〇：precision
△△：recall

考え方：
precision = tp/(tp+fp)
の式を知っているとfpが↑だと、precisionが小さくなる。fpが↑だとfnが↓だから、
recall = tp/(tp+fn)なので、recallが大きくなる。

#感想
confusion matrixでかなり、混乱した。
fp, fnは真のクラスがnegative, positiveと覚えておこう。

#調べた英単語
skew・・・adj, 斜めの、ゆがんだ、曲がった
err・・・v, (…を)誤る、
shortcoming・・・n, 短所、欠点
increment・・・v, 増加、増大、増進、増殖
quadrant・・・n, 象限
burglary・・・n, 夜盗、侵入盗
quotient・・・n, (割り算の)商