【机器学习】scikitLearn分类任务以mnist为例,训练二分类器并衡量性能指标:ROC及PR曲线

分类相关导航:
【机器学习】分类任务以mnist为例,数据集准备及预处理
【机器学习】scikitLearn分类任务以mnist为例,训练二分类器并衡量性能指标:ROC及PR曲线
【机器学习】scikitLearn分类:鉴别二分类、多分类、多标签及多输出的分类任务
【机器学习】使用scikitLearn可视化混淆矩阵进行分类误差分析

数据准备详见:
mnist数据准备

# Python ≥3.5 is required
import sys
assert sys.version_info >= (3, 5)

# Is this notebook running on Colab or Kaggle?
IS_COLAB = "google.colab" in sys.modules
IS_KAGGLE = "kaggle_secrets" in sys.modules

# Scikit-Learn ≥0.20 is required
import sklearn
assert sklearn.__version__ >= "0.20"

# Common imports
import numpy as np
import os


from scipy.io import  loadmat
mnist = loadmat('/app/datasets/mnist-original.mat')
mnist.keys()

X, y = mnist["data"], mnist["label"]
#交换两个维度
X=np.swapaxes(X,0,1)
print(X.shape)
y=np.squeeze(y)
print(y.shape)

X_train, X_test, y_train, y_test = X[:60000], X[60000:], y[:60000], y[60000:]
y_train_5 = (y_train == 5)
y_test_5 = (y_test == 5)

构建模型并进行交叉验证:

#引入的随机梯度下降分类:这个分类器的优势是能够有效处理非常大型的数据集。
#这部分是因为SGD独立处理训练实例,一次一个(这也使得SGD非常适合在线学习)
from sklearn.linear_model import SGDClassifier

sgd_clf = SGDClassifier(max_iter=1000, tol=1e-3, random_state=42)
sgd_clf.fit(X_train, y_train_5)
from sklearn.model_selection import cross_val_score
cross_val_score(sgd_clf, X_train, y_train_5, cv=3, scoring="accuracy")
#注意,这里衡量模型使用的是准确率,对于有偏数据集,即对于2分类器来说,
#正负样本不一样多,这不是一个好指标。

array([0.89345, 0.75235, 0.7899 ])

继续结合统计中的分层抽样,可以自定义一个交叉验证器:

from sklearn.model_selection import StratifiedKFold
from sklearn.base import clone

skfolds = StratifiedKFold(n_splits=3, shuffle=True, random_state=42)

for train_index, test_index in skfolds.split(X_train, y_train_5):
    clone_clf = clone(sgd_clf)
    X_train_folds = X_train[train_index]
    y_train_folds = y_train_5[train_index]
    X_test_fold = X_train[test_index]
    y_test_fold = y_train_5[test_index]

    clone_clf.fit(X_train_folds, y_train_folds)
    y_pred = clone_clf.predict(X_test_fold)
    n_correct = sum(y_pred == y_test_fold)
    print(n_correct / len(y_pred))

下面可以应用混淆矩阵继续进行评估:
与cross_val_score()函数一样,cross_val_predict()函数同样执行K-折交叉验证,但返回的不是评估分数,而是每个折叠的预测。

from sklearn.linear_model import SGDClassifier
sgd_clf = SGDClassifier(max_iter=1000, tol=1e-3, random_state=42)
sgd_clf.fit(X_train, y_train_5)
from sklearn.model_selection import cross_val_predict
#重新提供X_train, y_train_5,训练了sgd_clf
y_train_pred = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3)
from sklearn.metrics import confusion_matrix
#提供了预测值及实际值,即提供了绘制混淆矩阵的全部要素
confusion_matrix(y_train_5, y_train_pred)

输出:
array([[44363, 10216],
[ 1070, 4351]])

在这里插入图片描述
公式为:
精度=tp/(tp+fp),也就是ppv
精度是主观的,分母是自己预测出的全部正例
召回率=tp/(tp+fn) ,也就是TPR(灵敏度)
召回率是客观的,分母是全部客观正实例
在这里插入图片描述
F1分数的特点是中庸化,它能选出精度和召回率都较好的模型。
特异度 (specificity,SPE), 又称 真阴性率 (true negative rate,TNR), 即它反映 筛检 试验确定非病人的能力。公式为:TNR= tn / (fp + tn),可以理解为负召回率。

ROC曲线绘制召回率和(1-特异度)=fp / (fp + tn)的关系。
敏感度高=漏诊率低,特异度高=误诊率低。
理想情况下我们希望敏感度和特异度都很高。
之所以用1-特异度是绘图方便考虑,使ROC下的面积直接反映指标好坏。
在这里插入图片描述
ROC曲线下面积一般介于0.45至1之间,0.45时为纯随机分类器。

当正类稀少时用PR曲线作为指标更好,因为精度指标在正类少时更有代表性。
下面附代码:

1.求解精度和召回率:

from sklearn.metrics import precision_score, recall_score
precision_score(y_train, y_train_pred)
recall_score(y_train, y_train_pred)     

2.求解综合的F1分数:

from sklearn.metrics import f1_score
f1_score(y_train_5, y_train_pred)

3.通过决策函数做精度和召回率的权衡及曲线绘制:

from sklearn.linear_model import SGDClassifier
sgd_clf = SGDClassifier(max_iter=1000, tol=1e-3, random_state=42)
#指定method求出决策分数
y_scores = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3,
                        method="decision_function")
from sklearn.metrics import precision_recall_curve
#每个y_scores作为阈值,对应一个precisions和一个recalls:
precisions, recalls, thresholds = precision_recall_curve(y_train_5, y_scores)
def plot_precision_recall_vs_threshold(precisions, recalls, thresholds):
    plt.plot(thresholds, precisions[:-1], "b--", label="Precision", linewidth=2)
    plt.plot(thresholds, recalls[:-1], "g-", label="Recall", linewidth=2)
    plt.legend(loc="center right", fontsize=16) # Not shown in the book
    plt.xlabel("Threshold", fontsize=16)        # Not shown
    plt.grid(True)                              # Not shown
    plt.axis([-50000, 50000, 0, 1])             # Not shown
#以精度0.9取了对应的决策分数及精度值
recall_90_precision = recalls[np.argmax(precisions >= 0.90)]
#实际上是返回第一个为true的值
threshold_90_precision = thresholds[np.argmax(precisions >= 0.90)]
plt.figure(figsize=(8, 4))
#绘制分数阈值与召回率及精度的总图:                                                    
plot_precision_recall_vs_threshold(precisions, recalls, thresholds)  
plt.plot([threshold_90_precision], [0.9], "ro")                                     
plt.plot([threshold_90_precision], [recall_90_precision], "ro")                                                       
plt.show()

绘制的阈值–精度—召回率图如下:
在这里插入图片描述
继续绘制PR图:

plt.plot(recalls, precisions, "b-", linewidth=2)

在这里插入图片描述
根据图像选择合适的分数阈值,如threshold_90_precision,然后再二分类时,求出决策分数,并根据阈值进行分类决策:

#该决策函数默认以决策分数0为分界线:
y_scores = sgd_clf.decision_function([some_digit])

大于阈值是正类,小于阈值是负类

4.绘制ROC曲线及求AUC:

from sklearn.metrics import roc_curve
fpr, tpr, thresholds = roc_curve(y_train_5, y_scores)
plot_roc_curve(fpr, tpr)

在这里插入图片描述
求AUC面积:

from sklearn.metrics import roc_auc_score
roc_auc_score(y_train_5, y_scores)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

颢师傅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值