模型评估方法
一、导入第三方库
导入相关第三方库,以及设置横纵坐标属性
import numpy as np
import os
%matplotlib inline
import matplotlib
import matplotlib.pyplot as plt
plt.rcParams['axes.labelsize'] = 14
plt.rcParams['xtick.labelsize'] = 12
plt.rcParams['ytick.labelsize'] = 12
import warnings
warnings.filterwarnings('ignore')
np.random.seed(42)
二、读取数据集
Mnist数据是图像数据:(28,28,1)的灰度图
from sklearn.datasets import fetch_openml
mnist = fetch_openml('mnist_784')
mnist
X,y = mnist['data'], mnist['target']
X.shape
# 输出 (70000, 784)
# (70000 数据集中共70000个样本 每个样本为28*28大小 即 784)
y.shape
# 输出(70000,)
三、数据集切分
X_train, X_test, y_train, y_test = X[:60000], X[60000:], y[:60000], y[60000:] # 选择前6万个样本作为训练集 ,之后的样本作为测试集
由于样本中是按照数字的顺序进行排列,为了减少样本顺序对模型训练的影响,保证样本的独立性,需要对样本进行洗牌操作。
# 洗牌操作
import numpy as np
shuffle_index = np.random.permutation(60000)
X_train, y_train = X_train[shuffle_index], y_train[shuffle_index]
shuffle_index
洗牌后的样本索引
四、交叉验证
y_train_5 = (y_train == 5)
y_test_5 = (y_test == 5)
y_train_5[:10]
True:当前的值是5 False:当前的值不是5
from sklearn.linear_model import SGDClassifier
# 初始化分类器
sgd_clf = SGDClassifier(max_iter=5,random_state=42) # max_iter最大的迭代次数 random_state 随机种子
sgd_clf.fit(X_train,y_train_5)
sgd_clf.predict([X[35000]]) # array([ True]) predict()函数传入测试集的值
y[35000] # 5.0
交叉验证实验分析
方法一:调用
from sklearn.model_selection import cross_val_score
cross_val_score(sgd_clf,X_train,y_train_5,cv=3,scoring='accuracy')
# cv=3 交叉验证3次 计算准确度
# 输出 array([0.9502 , 0.96565, 0.96495])
方法二:手动实现
from sklearn.model_selection import StratifiedKFold
from sklearn.base import clone # 划分数据集
skflods = StratifiedKFold(n_splits=3,random_state=42)
for train_index,test_index in skflods.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_folds = X_train[test_index]
y_test_folds = y_train_5[test_index]
clone_clf.fit(X_train_folds,y_train_folds)
# 计算准确度
y_pred = clone_clf.predict(X_test_folds)
n_correct = sum(y_pred == y_test_folds)
print(n_correct/len(y_pred))
# 输出 0.9502
0.96565
0.96495
五、混淆矩阵
实验分析
from sklearn.model_selection import cross_val_predict
y_train_pred = cross_val_predict(sgd_clf,X_train,y_train_5,cv=3)
y_train_pred.shape # 输出(60000,)
X_train.shape # 输出(60000, 784)
from sklearn.metrics import confusion_matrix
confusion_matrix(y_train_5,y_train_pred)
实验结果
六、Precision and Recall
在sklearn中,有现成的计算精确度、召回率、F1值得方法
from sklearn.metrics import precision_score,recall_score
precision_score(y_train_5,y_train_pred)
# 输出0.7687135020350381
recall_score(y_train_5,y_train_pred)
# 输出0.801328168234643
from sklearn.metrics import f1_score
f1_score(y_train_5,y_train_pred)
# 输出0.7846820809248555
将Precision 和 Recall结合到一个称为F1 score 的指标,调和平均值给予低值更多权重。 因此,如果召回和精确度都很高,分类器将获得高F1分数。
七、阈值对结果的影响
阈值越底,得到的结果精度越底,召回率越高;
阈值越高,得到的结果精度越高,召回率越低。
y_scores = sgd_clf.decision_function([X[35000]])
y_scores # 输出array([43349.73739616])
t = 50000
y_pred = (y_scores > t)
y_pred # 输出array([False])
Scikit-Learn不允许直接设置阈值,但它可以得到决策分数,调用其decision_function()方法,而不是调用分类器的predict()方法,该方法返回每个实例的分数,然后使用想要的阈值根据这些分数进行预测:
y_scores = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3,
method="decision_function")
y_scores[:10]
# 输出
array([ -434076.49813641, -1825667.15281624, -767086.76186905,
-482514.55006702, -466416.8082872 , -311904.74603814,
-582112.5580173 , -180811.15850786, -442648.13282116,
-87710.09830358])
from sklearn.metrics import precision_recall_curve
precisions, recalls, thresholds = precision_recall_curve(y_train_5, y_scores)
y_train_5.shape # 输出(60000,)
thresholds.shape # 输出(59698,)
precisions[:10]
# 输出
array([0.09080706, 0.09079183, 0.09079335, 0.09079487, 0.09079639,
0.09079792, 0.09079944, 0.09080096, 0.09080248, 0.090804 ])
precisions.shape # (59699,)
recalls.shape # (59699,)
def plot_precision_recall_vs_threshold(precisions,recalls,thresholds):
plt.plot(thresholds,
precisions[:-1],
"b--",
label="Precision")
plt.plot(thresholds,
recalls[:-1],
"g-",
label="Recall")
plt.xlabel("Threshold",fontsize=16)
plt.legend(loc="upper left",fontsize=16)
plt.ylim([0,1])
plt.figure(figsize=(8, 4))
plot_precision_recall_vs_threshold(precisions,recalls,thresholds)
plt.xlim([-700000, 700000])
plt.show()
def plot_precision_vs_recall(precisions, recalls):
plt.plot(recalls,
precisions,
"b-",
linewidth=2)
plt.xlabel("Recall", fontsize=16)
plt.ylabel("Precision", fontsize=16)
plt.axis([0, 1, 0, 1])
plt.figure(figsize=(8, 6))
plot_precision_vs_recall(precisions, recalls)
plt.show()
八、ROC curves
receiver operating characteristic (ROC) 曲线是二元分类中的常用评估方法
- 它与精确度/召回曲线非常相似,但ROC曲线不是绘制精确度与召回率,而是绘制true positive rate(TPR) 与false positive rate(FPR)
- 要绘制ROC曲线,首先需要使用roc_curve()函数计算各种阈值的TPR和FPR:
TPR = TP / (TP + FN) (Recall)
FPR = FP / (FP + TN)
from sklearn.metrics import roc_curve
fpr, tpr, thresholds = roc_curve(y_train_5, y_scores)
def plot_roc_curve(fpr, tpr, label=None):
plt.plot(fpr, tpr, linewidth=2, label=label)
plt.plot([0, 1], [0, 1], 'k--')
plt.axis([0, 1, 0, 1])
plt.xlabel('False Positive Rate', fontsize=16)
plt.ylabel('True Positive Rate', fontsize=16)
plt.figure(figsize=(8, 6))
plot_roc_curve(fpr, tpr)
plt.show()
虚线表示纯随机分类器的ROC曲线; 一个好的分类器尽可能远离该线(朝左上角)。
比较分类器的一种方法是测量曲线下面积(AUC)。完美分类器的ROC AUC等于1,而纯随机分类器的ROC AUC等于0.5。 Scikit-Learn提供了计算ROC AUC的函数:
from sklearn.metrics import roc_auc_score
roc_auc_score(y_train_5, y_scores)
# 输出 0.9624496555967156