【机器学习】模型评估-手写数字集模型训练与评估


前言

前面我们介绍了模型评估的常用方法和指标,现在我们将训练手写数字集,通过不同的方法对我们模型评估以及更加的去增加我们对模型评估方法和指标的理解

一、数据集的加载

import matplotlib
import pandas as pd
import seaborn as sns
import warnings
warnings.filterwarnings('ignore')
#%%
from sklearn.datasets import load_digits
data=load_digits()
print(data.data.shape)

在这里插入图片描述
共有1797个(8x8)的书写数字图片,我们展示一下看

plt.gray()
plt.figure(figsize=(8,6))
plt.imshow(data.images[0])
plt.show()

在这里插入图片描述
这个图片像素处理过,不过我们还是能明显看到是 0

二、分训练集和测试集,洗牌操作,二分类

这里我们我们将测试集和测试集的比列为7:3

from sklearn.model_selection import train_test_split
X,y=data.data,data.target
X_train,y_train,X_test,y_test=train_test_split(X,y,test_size=0.3,random_state=42)

由于数据集从0到9,具有一定的规律性,两者之间具有相关性,所以我们对训练数据进行洗牌操作

indexs=np.random.permutation(len(X_train))#permutaion的根据给出n长度,生成一个乱的从0到n的数组
X_train,y_train=X_train[indexs],y_train[indexs]

由于数据集有有0到9,10种类型,我们将数据集成二分类集,分为非2数字和2数字

y_train_2=(y_train==2)
y_test_2=(y_test==2)

三、训练模型和预测

我们用sklearn线性模型的梯度下降分类器SGDClassifier

from sklearn.linear_model import SGDClassifier
sgd_clf=SGDClassifier(max_iter=10,random_state=42)
sgd_clf.fit(X_train,y_train_2)
y_prediction=sgd_clf.predict(X[2].reshape(1,-1))
print(y_prediction)

在这里插入图片描述
预测返回为True,我们打印该位置的数字看一下

print(y_prediction)
print(y[2])

在这里插入图片描述
可以看到预测还是成功的

四、模型评估

1.交叉验证

交叉验证是将训练集分为多份,然后取出一份,作为测试集,其他几份作为训练集互相验证,直到分出的每一份都作为验证集被评估,这样方法能对数据集比较少比较友好。cross_val_score 函数可以帮助我们更好地评估模型在数据集上的性能,并选择最优的模型。同时,通过使用交叉验证,我们可以更好地利用有限的数据集,并减少模型的过拟合。

from sklearn.model_selection import cross_val_score
cross_val_scores=cross_val_score(sgd_clf,X_train,y_train_2,cv=3,scoring='accuracy')#切割成3份
print('交叉验证得分 ',cross_val_scores)
print('交叉验证平均分 ',cross_val_scores.mean())
print('交叉验证方差 ',cross_val_scores.std())

在这里插入图片描述

可以看到平均分还是相当高,说明我们的模型比较好

为了更好的分析模型,性能,我们可以用cross_val_predict ,他是 Scikit-learn 中的一个函数,用于执行交叉验证并返回模型的预测结果。
具体来说,cross_val_predict 函数可以接收一个机器学习模型、训练数据、目标变量以及交叉验证的参数,然后返回一个包含每次交叉验证的预测结果的数组。这些预测结果可以用来评估模型在数据集上的性能,并进行后续的分析和处理。
与 cross_val_score 函数不同的是,cross_val_predict 函数返回的是每个样本的预测结果,而不是每次交叉验证的得分。这意味着,我们可以获得更详细的模型性能信息,并进行更深入的分析和调整。

from sklearn.model_selection import cross_val_predict
cross_val_predicts=cross_val_predict(sgd_clf,X_train,y_train_2,cv=3)
print('cross_val_predicts: ',cross_val_predicts)

在这里插入图片描述

2.Confusion Matrix-混淆矩阵

下面指标我们上一篇文章说过,所以就不会做过多的解释

上面我们说过TP,FP,TN,FN现在我们去获取它

from sklearn.metrics import confusion_matrix

confusion_matrixs=confusion_matrix(y_train_2,cross_val_predicts)
print(confusion_matrixs)

在这里插入图片描述
这里简单点表达为

[[TN FN]
[FP TP]]
解释:我们成功识别126个为2的数字,错误将4个非2字识别为2

2.1 Precision,recall,f1_sorce

from sklearn.metrics import precision_score,recall_score,f1_score
precision_score=precision_score(y_train_2,cross_val_predicts)
recall_score=recall_score(y_train_2,cross_val_predicts)
f1_score=f1_score(y_train_2,cross_val_predicts)
print('精度:',precision_score)
print('召回',recall_score)
print('调和平均数:',f1_score)

在这里插入图片描述

2.2 ROC曲线以及阈值对结果影响

我们设 [5,2,4,3,2,2,2,2]
为模型预测的结果,并且从左到右为决策分数[12,22,33,42,54,63,74,80],决策分数越高正确率越高,这个时候我们设阈值分数为40,则通过分数大小分成两个部分,左边的就是我们的预测失败的FN,右边预测成功的TN,通过分别的计算公式就会影响我们的 Precision,recall的分数,所以选择合适的阈值有效的提高我们模型评估。

上面我们得知X[2]为2,为Ture,我们查看其决策分数值,Scikit-Learn不允许直接设置阈值,但它可以得到决策分数,调用其decision_function()方法。

Scikit-Learn不允许直接设置阈值,但它可以得到决策分数,
调用其decision_function()方法

y_sorce=sgd_clf.decision_function(X[2].reshape(1,-1))
print(y_sorce)

在这里插入图片描述

我们同时可以获取所有的决策分数

y_sorce=cross_val_predict(sgd_clf,X_train,y_train_2,cv=3,method='decision_function')
print(y_sorce[0:15])

在这里插入图片描述

获取其所有的阈值
precision_recall_curve 是 Scikit-learn 中的一个函数,用于计算分类模型的精度和召回率的取值和阈值。
具体来说,precision_recall_curve 函数可以接收一个二分类模型的预测概率和真实标签,然后计算出一系列阈值下的精度和召回率,以及对应的阈值值。这些精度、召回率和阈值值可以用于绘制精度-召回率曲线,或计算模型的平均精度(average precision)等性能指标。

from sklearn.metrics import precision_recall_curve
predictions,recalls,thresholds=precision_recall_curve(y_train_2,y_sorce)

在这里插入图片描述
我们绘制折线图,观察情况

sns.set_theme(style="darkgrid")
data_line=pd.DataFrame({"predictions":predictions[:len(thresholds)],"recalls":recalls[:len(thresholds)],'thresholds':thresholds})
sns.lineplot(x='thresholds',y='predictions',data=data_line)
sns.lineplot(x='thresholds',y='recalls',data=data_line)
# plt.savefig(f'D:\博客文档\模型评估\{random.randint(1,100)}.png')
plt.show()

在这里插入图片描述

在0附近,精确度和召回率最高,并且接近于0对称,并且我们发现阈值的变化对于结果的影响很大,设定阈值时候需要慎重。

  • AUC值(Area Under the ROC Curve)

得出最优阈值,我们也可以得出AUC值,绘制出ROC曲线
采用的roc_curve 函数是 scikit-learn 库中的一个用于绘制 ROC 曲线(Receiver Operating Characteristic Curve)的函数,用于评估二元分类模型的性能。 ROC 曲线显示了真阳性率(True Positive Rate)tpr与假阳性率(False Positive Rate)fpr之间的关系,可以帮助我们选择分类模型的最佳阈值。

  • 我们得出tpr,fpr,阈值,绘制ROC观察
from sklearn.metrics import roc_curve
fpr,tpr,thresholds=roc_curve(y_train_2,y_sorce)
line_data=pd.DataFrame({'fpr':fpr,'tpr':tpr,'thresholds':thresholds})
sns.lineplot(data=line_data,x='fpr',y='tpr',)
sns.lineplot(data=pd.DataFrame({'x':[0,1],'y':[0,1]}))
plt.show()

在这里插入图片描述

虚线表示纯随机分类器的ROC曲线; 一个好的分类器尽可能远离该线(朝左上角),很明显我们这个模型分类器相当好。

我们也可以用roc_auc_score计算我们的AUC值

from sklearn.metrics import roc_auc_score
roc_auc_score=roc_auc_score(y_train_2,y_sorce)
print("AUC值:",roc_auc_score)

在这里插入图片描述
分数yyds,真希望我以后所有模型的AUC值有这么高就好了

  • 找到最优阈值通常需要结合实际应用场景和分类模型的性能指标来确定。

种常用的方法是根据 ROC 曲线上的坐标点来确定最优阈值。在 ROC 曲线上,我们可以通过计算每个阈值对应的 FPR 和 TPR 坐标来找到最优阈值。通常情况下,我们可以根据以下指标来选择最优阈值:

  • 最大化 TPR:当我们更加关注模型的召回率(即真阳性率)时,可以选择使 TPR 最大化的阈值作为最优阈值。

  • 最小化 FPR:当我们更加关注模型的精确率(即假阳性率)时,可以选择使 FPR 最小化的阈值作为最优阈值。

  • 最大化 AUC:当我们希望综合考虑模型的精确率和召回率时,可以选择 AUC(Area Under the Curve)最大化的阈值作为最优阈值。

  • 例子 如果我们更加关注模型的召回率,我们可以沿用上述的fpr,tpr,thresholds值。

from sklearn.metrics import roc_curve
fpr,tpr,thresholds=roc_curve(y_train_2,y_sorce)
# 找到最大化 TPR 的阈值
good_threshold = thresholds[np.argmax(tpr)]
print('最优阈值',good_threshold)

在这里插入图片描述
加入到模型之中再计算召回率

recall_scores=recall_score(y_train_2,cross_val_predicts)
print('没设置最优阈值recall_sorce:',recall_scores)
y_pred=(cross_val_predicts>good_threshold)
recall_score=recall_score(y_train_2,y_pred)
print('设置最优阈值后recall_sorce:',recall_scores)

结果比较尴尬,可以从上面的图看到我们的分类模型还是相当好的,所以不能优化了吧,或许,可能。
在这里插入图片描述
后来重新运行一下还是有点效果
在这里插入图片描述

  • 或者我们用最老的办法,每一个阈值都测试一遍
from sklearn.metrics import recall_score

for threshold in thresholds:
    b_recall_scoress = recall_score(y_train_2, cross_val_predicts)
    y_pred = (cross_val_predicts > threshold)

    e_recall_score = recall_score(y_train_2, y_pred)
    max_good_threshold.append(threshold)
    beging_recalls.append(b_recall_scoress)
    end_recalss.append(e_recall_score)

end_good_recalls_index=np.argmax(end_recalss)
b_recalss=beging_recalls[end_good_recalls_index]
e_threshold=max_good_threshold[end_good_recalls_index]
e_reclass=end_recalss[end_good_recalls_index]

print('最优阈值',e_threshold)
print('优化前',b_recalss)
print('优化后',e_reclass)

在这里插入图片描述

阈值优化后recall还是比较明显的提高

五、总结

本节我们详细的解释了模型评估的几种方法以及获取最优阈值,帮助我们更好的对模型进行评估与优化。
希望大家多多支持,我会更加努力学习分享更多有趣的东西

  • 12
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

泪懿

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

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

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

打赏作者

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

抵扣说明:

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

余额充值