深度学习实战MNIST数据集的二分类腾讯云开发者社区

MNIST数据集是一组由美国高中生和人口调查局员工手写的70,000个数字的图片,每张图片上面有代表的数字标记。

这个数据集被广泛使用,被称之为机器学习领域的“HelloWorld”,主要是被用于分类问题。本文是对MNIST数据集执行一个二分类的建模

关键词:随机梯度下降、二元分类、混淆矩阵、召回率、精度、性能评估

在这里是将一份存放在本地的mat文件的数据导进来:

In[1]:

importpandasaspdimportnumpyasnpimportscipy.ioassi#fromsklearn.datasetsimportfetch_openmlIn[2]:

type(mnist)#查看数据类型Out[3]:

dictIn[4]:

mnist.keys()Out[4]:

In[5]:

#修改1:一定要转置X,y=mnist["data"].T,mnist["label"].TX.shapeOut[5]:

(70000,784)总共是70000张图片,每个图片中有784个特征。图片是28*28的像素,所以每个特征代表一个像素点,取值从0-255。

In[6]:

y.shapeOut[6]:

(70000,1)In[7]:

y#每个图片有个专属的数字Out[7]:

array([[0.],[0.],[0.],...,[9.],[9.],[9.]])显示一张图片In[8]:

importmatplotlibasmplimportmatplotlib.pyplotaspltone_digit=X[0]one_digit_image=one_digit.reshape(28,28)plt.imshow(one_digit_image,cmap="binary")plt.axis("off")plt.show()

In[9]:

y[0]#真实的标签的确是0Out[9]:

array([0.])#结果是0标签类型转换元数据中标签是字符串,我们需要转成整数类型

In[10]:

y.dtypeOut[10]:

y=y.astype(np.uint8)创建训练集和测试集前面的6万条是训练集,后面的1万条是测试集

In[12]:

X_train,X_test,y_train,y_test=X[:60000],X[60000:],y[:60000],y[60000:]二元分类器比如现在有1张图片,显示是0,我们识别是:“0和非0”,两种情形即可,这就是简单的二元分类问题

In[13]:

y_train_0=(y_train==0)#挑选出5的部分y_test_0=(y_test==0)随机梯度下降分类器SGD使用scikit-learn自带的SGDClassifier分类器:能够处理非常大型的数据集,同时SGD适合在线学习

In[14]:

fromsklearn.linear_modelimportSGDClassifiersgd_c=SGDClassifier(random_state=42)#设置随机种子,保证运行结果相同sgd_c.fit(X_train,y_train_0)/Applications/downloads/anaconda/anaconda3/lib/python3.7/site-packages/sklearn/utils/validation.py:993:DataConversionWarning:Acolumn-vectorywaspassedwhena1darraywasexpected.Pleasechangetheshapeofyto(n_samples,),forexampleusingravel().y=column_or_1d(y,warn=True)Out[14]:

SGDClassifier(random_state=42)结果验证在这里我们检查下数字0的图片:结果为True

In[15]:

sgd_c.predict([one_digit])#one_digit是0,非5表示为FalseOut[15]:

array([True])性能测量1-交叉验证一般而言,分类问题的评估比回归问题要困难的多。

In[16]:

#K折交叉验证fromsklearn.model_selectionimportStratifiedKFold#用于生成分类器的副本fromsklearn.baseimportclone#实例化对象k_folds=StratifiedKFold(n_splits=3,#3折shuffle=True,#add一定要设置shuffle才能保证random_state生效random_state=42)#每个折叠由StratifiedKFold执行分层抽样fortrain_index,test_indexink_folds.split(X_train,y_train_0):#分类器的副本clone_c=clone(sgd_c)X_train_folds=X_train[train_index]#训练集的索引号y_train_folds=y_train_0[train_index]X_test_fold=X_train[test_index]#测试集的索引号y_test_fold=y_train_0[test_index]clone_c.fit(X_train_folds,y_train_folds)#模型训练y_pred=clone_c.predict(X_test_fold)#预测n_correct=sum(y_pred==y_test_fold)#预测准确的数量print(n_correct/len(y_pred))#预测准确的比例运行的结果如下:

[0.098750.098750.09875...0.901250.901250.90125][0.09870.09870.0987...0.90130.90130.9013][0.09870.09870.0987...0.90130.90130.9013]scikit_learn的交叉验证使用cross_val_score来评估分类器:

In[17]:

#评估分类器的效果fromsklearn.model_selectionimportcross_val_scorecross_val_score(sgd_c,#模型X_train,#数据集y_train_0,cv=3,#3折scoring="accuracy"#准确率)#结果array([0.98015,0.95615,0.9706])可以看到准确率已经达到了95%以上,效果是相当的可观

自定义一个“非0”的简易分类器,看看效果:

In[18]:

fromsklearn.baseimportBaseEstimator#基分类器classNever0Classifier(BaseEstimator):deffit(self,X,y=None):returnselfdefpredict(self,X):returnnp.zeros((len(X),1),dtype=bool)In[19]:

never_0_clf=Never0Classifier()cross_val_score(never_0_clf,#模型X_train,#训练集样本y_train_0,#训练集标签cv=3,#折数scoring="accuracy")Out[19]:

array([0.70385,1.,1.])In[20]:

统计数据中每个字出现的次数:

pd.DataFrame(y).value_counts()Out[20]:

17877772933714126990969580690366876868254682456313dtype:int64In[21]:

6903/70000Out[21]:

下面显示大约有10%的概率是0这个数字

0.09861428571428571In[22]:

(0.70385+1+1)/3Out[22]:

0.9012833333333333可以看到判断“非0”准确率基本在90%左右,因为只有大约10%的样本是属于数字0。

所以如果猜测一张图片是非0,大约90%的概率是正确的。

评估分类器性能更好的方法是混淆矩阵,总体思路是统计A类别实例被划分成B类别的次数

混淆矩阵是通过预测值和真实目标值来进行比较的。

cross_val_predict函数返回的是每个折叠的预测结果,而不是评估分数

In[23]:

fromsklearn.model_selectionimportcross_val_predicty_train_pred=cross_val_predict(sgd_c,#模型X_train,#特征训练集y_train_0,#标签训练集cv=3#3折)y_train_predOut[23]:

array([True,True,True,...,False,False,False])混淆矩阵In[24]:

#导入混淆矩阵fromsklearn.metricsimportconfusion_matrixconfusion_matrix(y_train_0,y_train_pred)Out[24]:

array([[52482,1595],[267,5656]])混淆矩阵中:行表示实际类别,列表示预测类别

In[25]:

#假设一个完美的分类器:只存在真正类和真负类,它的值存在于对角线上y_train_perfect_predictions=y_train_0confusion_matrix(y_train_0,y_train_perfect_predictions)Out[25]:

array([[54077,0],[0,5923]])精度和召回率精度=\frac{TP}{TP+FP}召回率的公式为:

混淆矩阵显示的内容:

精度:正类预测的准确率

召回率(灵敏度或真正类率):分类器正确检测到正类实例的比例

In[26]:

fromsklearn.metricsimportprecision_score,recall_scoreprecision_score(y_train_0,y_train_pred)#精度Out[26]:

0.78003034064267In[27]:

recall_score(y_train_0,y_train_pred)#召回率Out[27]:

0.9549214924869154F_1系数F_1系数是精度和召回率的谐波平均值。只有当召回率和精度都很高的时候,分类器才会得到较高的F_1分数

1=21精度+1召回率(3)(3)F1=21精度+1召回率

In[28]:

fromsklearn.metricsimportf1_scoref1_score(y_train_0,y_train_pred)Out[28]:

0.8586609989373006精度/召回率权衡精度和召回率通常是一对”抗体“,我们一般不可能同时增加精度又减少召回率,反之亦然,这就现象叫做精度/召回率权衡

In[29]:

#使用decision_functiony_scores=sgd_c.decision_function([one_digit])y_scoresOut[29]:

array([24816.66593936])In[30]:

threshold=0#设置阈值y_digit_pred=y_scores>thresholdy_digit_predOut[30]:

array([True])In[31]:

#提升阈值threshold=100000y_digit_pred=y_scores>thresholdy_digit_predOut[31]:

array([False])如何使用阈值In[32]:

y_scores=cross_val_predict(sgd_c,X_train,y_train_0.ravel(),#原文y_train_0cv=3,method="decision_function")y_scoresOut[32]:

array([51616.39393745,27082.28092103,20211.29278048,...,-23195.59964776,-21022.63597851,-18702.17990507])有了这些分数就可以计算精度和召回率:

In[33]:

fromsklearn.metricsimportprecision_recall_curveprecisions,recalls,thresholds=precision_recall_curve(y_train_0,y_scores)In[34]:

precisions#精度Out[34]:

array([0.10266944,0.10265389,0.10265566,...,1.,1.,1.])In[35]:

recalls#召回率Out[35]:

array([1.00000000e+00,9.99831167e-01,9.99831167e-01,...,3.37666723e-04,1.68833361e-04,0.00000000e+00])In[36]:

thresholds#阈值Out[36]:

array([-86393.49001095,-86375.60229796,-86374.22313529,...,92555.12952489,93570.30614671,96529.58216984])绘制精度和召回率曲线In[37]:

deffigure_precision_recall(precisions,recalls,thresholds):plt.plot(thresholds,precisions[:-1],"b--",label="Precision")#精度-蓝色plt.plot(thresholds,recalls[:-1],"g-",label="Recall")#召回率-绿色plt.legend(loc="centerright",fontsize=12)plt.xlabel("Threshold",fontsize=16)plt.grid(True)figure_precision_recall(precisions,recalls,thresholds)plt.show()

直接绘制精度和召回率的曲线图:

#精度-召回率plt.plot(recalls[:-1],precisions[:-1],"b--")plt.legend(loc="centerright",fontsize=12)plt.xlabel("Threshold",fontsize=16)plt.grid(True)

现在我们将精度设置成90%,通过np.argmax()函数来获取最大值的第一个索引,即表示第一个True的值:

In[39]:

threshold_90_precision=thresholds[np.argmax(precisions>=0.9)]threshold_90_precisionOut[39]:

9075.648564157285In[40]:

y_train_pred_90=(y_scores>=threshold_90_precision)y_train_pred_90Out[40]:

array([True,True,True,...,False,False,False])In[41]:

#再次查看精度和召回率precision_score(y_train_0,y_train_pred_90)Out[41]:

0.9001007387508395In[42]:

recall_score(y_train_0,y_train_pred_90)Out[42]:

0.9051156508526085性能测量3-ROC曲线绘制ROC还有一种经常和二元分类器一起使用的工具,叫做受试者工作特征曲线ROC。

绘制的是真正类率(召回率的别称)和假正类率(FPR)。FPR是被错误分为正类的负类实例比率,等于1减去真负类率(TNR)

TNR是被正确地分为负类的负类实例比率,也称之为特异度。

ROC绘制的是灵敏度和(1-特异度)的关系图

In[43]:

#1、计算TPR、FPRfromsklearn.metricsimportroc_curvefpr,tpr,thresholds=roc_curve(y_train_0,y_scores)In[44]:

defplot_roc_curve(fpr,tpr,label=None):plt.plot(fpr,tpr,linewidth=2,label=label)plt.plot([0,1],[0,1],"k--")plt.legend(loc="centerright",fontsize=12)plt.xlabel("FPR",fontsize=16)plt.ylabel("TPR",fontsize=16)plt.grid(True)plot_roc_curve(fpr,tpr)plt.show()

auc就是上面ROC曲线的线下面积。完美的分类器ROC_AUC等于1;纯随机分类器的ROC_AUC等于0.5

In[45]:

fromsklearn.metricsimportroc_auc_scoreroc_auc_score(y_train_0,y_scores)Out[45]:

报错:index1isoutofboundsforaxis1withsize1

In[46]:

X_train.shapeOut[46]:

(60000,784)In[47]:

#解决方案y_train_0=y_train_0.reshape(X_train.shape[0],)y_train_0Out[47]:

array([True,True,True,...,False,False,False])In[48]:

fromsklearn.ensembleimportRandomForestClassifierforest_clf=RandomForestClassifier(random_state=42)y_probas_forest=cross_val_predict(forest_clf,X_train,y_train_0,cv=3,method="predict_proba")y_probas_forestOut[48]:

array([[0.,1.],[0.04,0.96],[0.15,0.85],...,[0.93,0.07],[0.97,0.03],[0.96,0.04]])使用roc_curve函数来提供分类的概率:

In[49]:

y_scores_forest=y_probas_forest[:,1]fpr_rf,tpr_rf,thresholds_rf=roc_curve(y_train_0,y_scores_forest)In[50]:

plt.plot(fpr,tpr,"b:",label="SGD")plot_roc_curve(fpr_rf,tpr_rf,"RandomForest")plt.legend(loc="lowerright")plt.show()

现在我们重新查看ROC-AUC值、精度和召回率,发现都得到了提升:

In[51]:

roc_auc_score(y_train_0,y_scores_forest)#ROC-AUC值Out[51]:

0.9975104189747056In[52]:

precision_score(y_train_0,y_train_pred)#精度Out[52]:

0.78003034064267In[53]:

recall_score(y_train_0,y_train_pred)#召回率Out[53]:

0.9549214924869154总结本文从公开的MNIST数据出发,通过SGD建立一个二元分类器,同时利用交叉验证来评估我们的分类器,以及使用不同的指标(精度、召回率、精度/召回率平衡)、ROC曲线等来比较SGD和RandomForestClassifier不同的模型。

THE END
1.python中数据二分类数据集mob64ca12f028ff的技术博客在机器学习领域,数据二分类问题是最常见的任务之一。数据二分类涉及将输入数据分为两个类别,例如,判断电子邮件是“垃圾邮件”还是“正常邮件”。在 Python 中,我们可以使用一些流行的库来处理这样的二分类数据集。本文将介绍如何构建和处理二分类数据集,并提供代码示例。 https://blog.51cto.com/u_16213430/12160653
2.机器学习实战二分类(MNIST数据集)二分类数据集机器学习实战--二分类(MNIST数据集) importmatplotlib.pyplotasplt%matplotlib inlinefromsklearn.datasetsimportfetch_mldata mnist=fetch_mldata('MNIST original') 1 2 3 4 Scikit-Learn加载数据集通常具有类似于字典的结构,包括: DESCR:描述数据集 data:包含一个数组,每个实例为一行,每个特征为一列https://blog.csdn.net/qq_45603718/article/details/117235656
3.数据集UCI 机器学习数据集合中的经典二分类数据集,包括 Iris、Hert Dieses、German Credit 等经典二分类问题测试数据集。 数据集详情 原始数据名称:UCI经典二分类数据集 数据介绍:UCI 机器学习数据集合中的经典二分类数据集,包括 Iris、Hert Dieses、German Credit 等经典二分类问题测试数据集。 http://dataju.cn/Dataju/web/datasetInstanceDetail/438
4.什么是数据集的分类?简介:【7月更文挑战第10天】什么是数据集的分类? 什么是数据集的分类? 数据集的分类主要指根据数据的性质、来源或用途将数据集进行不同类别的划分。 在机器学习和数据分析中,数据集通常被分为训练集、验证集和测试集三个部分,以评估模型对新数据的泛化能力并避免模型过拟合[^1^][^2^]。这些划分方法有各自的https://developer.aliyun.com/article/1564190
5.关于机器学习的一些记录(二)1、二分类(Binary Classification)是什么? 二分类是机器学习中最基本的分类问题之一,它将数据集中的样本(数据点)划分为两个互斥的类别(通常是“正类”和“负类”)。 二分类任务的目标是预测一个样本属于两个类别中的哪一个。 2、二分类应用场景有哪些? https://www.jianshu.com/p/4b2ece849b4a
6.二分类数据集该数据是一个平衡的图片二分类数据集,正负类图片各250张,一个50 0 张图,是个不错的做图片分类的数据集。 上传者:qq_44630529时间:2020-08-23 医学数据集-乳腺癌数据集-二分类数据集-med开源数据集提取2.zip 依据开源数据集整理和标注的数据,可以直接使用,希望对你有帮助。 https://www.iteye.com/resource/qq_37879432-10203809