1.混淆矩陣
接受者操作特征(Receiver Operating Characteristic Curve主届,ROC)曲線是顯示分類器真正率和假正率之間折中
的?種圖形化?法君丁,也是最常?的評估分類模型好壞的可視化圖形绘闷,在介紹ROC曲線之前,先了解下混淆矩陣丑勤。
1.1 原理
混淆矩陣是用來總結(jié)一個分類器結(jié)果的矩陣法竞。對于k元分類强挫,其實它就是一個k x k的表格俯渤,用來記錄分類器的預(yù)測結(jié)果稠诲。 對于最常見的二元分類來說臀叙,它的混淆矩陣是2乘2的。
假設(shè)有一批test樣本渊涝,這些樣本只有兩種類別:正例和反例跨释。機器學(xué)習(xí)算法預(yù)測類別如下圖(左半部分預(yù)測類別為正例鳖谈,右半部分預(yù)測類別為反例)阔涉,而樣本中真實的正例類別在上半部分瑰排,下半部分為真實的反例椭住。 如下圖:
預(yù)測值為正例,記為P(Positive)
預(yù)測值為反例葫掉,記為N(Negative)
預(yù)測值與真實值相同,記為T(True)
預(yù)測值與真實值相反兽肤,記為F(False)
注: F1 score 來源:
1/ ((1/精準(zhǔn)率)+ (1/召回率))
由于精準(zhǔn)率,召回率最大1绪抛,此值最大0.5资铡,會乘2,使其在0-1區(qū)間幢码。
2. ROC曲線
橫坐標(biāo):1-負(fù)樣本的召回率 假正率:負(fù)樣本中預(yù)測成正樣本的概率
縱坐標(biāo):正樣本的召回率 真正率:正樣本中預(yù)測為正樣本的概率
3. 繪制ROC曲線
3.1 導(dǎo)入波士頓房價笤休,獲取X,y
將大于均價的房價映射為1症副,低于映射為0,構(gòu)成分類問題贞铣,并初步用邏輯斯蒂預(yù)測和評分闹啦。
import numpy as np
import pandas as pd
from pandas import Series, DataFrameimport matplotlib.pyplot as plt
%matplotlib inlinefrom sklearn.datasets import load_boston # 獲取波士頓房價數(shù)據(jù)
X, y = load_boston(return_X_y=True) # 獲取特征向量集X和目標(biāo)房價 y
展示y
import seaborn as sns
sns.set()
sns.distplot(y)
根據(jù)均值將y映射為0和1
threshold = np.median(y)
target = Series(y).map(lambda x: (x>threshold)*1)
target.value_counts().plot(kind='bar')
image.png
邏輯斯蒂建模
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split # 獲取拆分函數(shù)
X_train, X_test, y_train, y_test = train_test_split(X, target, test_size=0.2, random_state=1) # 拆分樣本集,拆分比例0.8:0.2辕坝,并做隨機種子窍奋,下次拆分如果還用隨機種子1,可以得到一樣的隨機結(jié)果酱畅。
預(yù)測并評分
lr = LogisticRegression()
lr.fit(X_train, y_train)
y_ = lr.predict(X_test)
y_
from sklearn.metrics import accuracy_score
accuracy_score(y_, y_test) # 0.8725490196078431
準(zhǔn)確率評分琳袄,即預(yù)測正確的占總數(shù)的比例。如果樣本比例不均纺酸,此評分高看不出來對兩種預(yù)測樣本的準(zhǔn)確度窖逗。
比如:99個男生,1個女生餐蔬,預(yù)測為100個男生滑负,準(zhǔn)確率99%,但對女生的預(yù)測率為0用含,所以需要引入其他評分指標(biāo)矮慕。
3.2 繪制混淆矩陣
(1)導(dǎo)包,準(zhǔn)備數(shù)據(jù)
from sklearn.metrics import confusion_matrix # 導(dǎo)入混淆矩陣的包
y_.size # 102
cm = confusion_matrix(y_test, y_)
cm # array([[44, 3], [10, 45]], dtype=int64)
tn, fp, fn, tp = confusion_matrix(y_test, y_).ravel()
(tn, fp, fn, tp) # (44, 3, 10, 45)
(2)繪圖展示
sns.set_style('white') # 設(shè)置全局的圖的背景為白色
def show_cm(y_true, y_test):
tn, fp, fn, tp = confusion_matrix(y_test, y_true).ravel()
plt.imshow(cm, cmap=plt.cm.Blues)
plt.xticks([0,1])
plt.yticks([0,1])
plt.xlabel("Predict")
plt.ylabel("True")plt.text(x=0-0.1, y=0, s="TP:"+str(tp), color='black') # 設(shè)置文本啄骇,位置由x,y確定痴鳄,x,y為相對位置。0-1
plt.text(x=1-0.1, y=0, s="FN:"+str(fn), color='black')
plt.text(x=0-0.1, y=1, s="FP:"+str(fp), color='black')
plt.text(x=1-0.1, y=1, s="TN:"+str(tn), >color='black')查準(zhǔn)率 = tp/(tp + fp)
召回率 = tp/(tp + tn)
print("查準(zhǔn)率:",查準(zhǔn)率)
print("召回率:",召回率)
plt.show()
繪圖
show_cm(y_test, y_)
image.png
(3)對預(yù)測閥值進行修改并展示混淆矩陣
原理缸夹,邏輯斯蒂回歸痪寻,根據(jù)概率判斷正負(fù)樣本螺句,閥值0.5,0的概率大于1時橡类,預(yù)測為0.
對正樣本的預(yù)測閾值進行修改蛇尚,查看變換
y1_ = (lr.predict_proba(X_test)[:,1] > 0.7)*1 #通過predict_proba獲取每個預(yù)測值的概率,如果第2列的概率大于0.7顾画,則為1取劫,小于為0. 即增大正樣本的概率判斷的閾值。
3.3 f1_score評分
3.4 繪制 ROC曲線
3.4.1計算評分
繪制曲線
from sklearn import metrics
def show_roc(y_test, scores, pos_label):
fpr, tpr, thresholds = metrics.roc_curve(y_test, scores, pos_label=pos_label)
plt.plot(fpr, tpr, color='green')
plt.plot(np.linspace(0,1,10), np.linspace(0,1,10), color='red', ls='--')
plt.xlabel("FPR")
plt.ylabel("TPR")
plt.title("LR ROC ")
plt.show()
繪制ROC曲線
繪制不同情況下的ROC曲線
參數(shù)c更小
高斯分布樸素貝葉斯預(yù)測
from sklearn.naive_bayes import GaussianNB
gnb = GaussianNB()
gnb.fit(X_train, y_train)
scores3 = gnb.predict_proba(X_test)[:,1]
show_roc(y_test, scores3, 1)
3.5 繪制ROC曲線
import numpy as np
from sklearn import metrics
y = np.array([1, 1, 2, 2])
scores = np.array([0.1, 0.4, 0.35, 0.8])
fpr, tpr, thresholds = metrics.roc_curve(y, scores, pos_label=2)
fpr, tpr, thresholds # 列方向看研侣,當(dāng)閾值為1,8時谱邪,預(yù)測FPR和TPR的值都為0,當(dāng)閾值為0.8時庶诡,F(xiàn)PR為0惦银,TPR為0.5.
(array([0. , 0. , 0.5, 0.5, 1. ]),
array([0. , 0.5, 0.5, 1. , 1. ]),
array([1.8 , 0.8 , 0.4 , 0.35, 0.1 ]))
import matplotlib.pyplot as plt
%matplotlib inline
plt.plot(fpr, tpr, color='blue', lw=3)
plt.xlabel('FPR')
plt.ylabel('TPR')