基于jupyternotebook的python编程-----MNIST数据集的的定义及相。。。
基于jupyter notebook的python编程-----MNIST数据集的相关处理
⼈⼯智能我们已经有过⼀段时间的学习了,其中,第⼀章提到,最常见的监督式学习任务包括回归任务(预测值)和分类任务(预测类)。
第⼆章探讨了⼀个回归任务–预测住房价格,⽤到了线性回归、决策树以及随机森林等各种算法(我们会在后续章节中进⼀步讲解这些算法)。
本章中我们会把注意⼒转向分类系统。
那么那么林君学长就带⼤家交接对MNIST数据集的操作!
⼀、MNIST定义
1、什么是MNIST数据集
数据介绍:本章使⽤MNIST数据集,这是⼀组由美国⾼中⽣和⼈⼝调查局员⼯⼿写的70000个数字的图⽚。每张图像都⽤其代表的数字标记。这个数据集被⼴为使⽤,因此也被称作是机器学习领域的“Hello
World”:但凡有⼈想到了⼀个新的分类算法,都会想看看在MNIST上的执⾏结果。因此只要是学习机器学习的⼈,早晚都要⾯对MNIST。
2、python如何导⼊MNIST数据集并操作
1)、导⼊需求的库
# 使⽤sklearn的函数来获取MNIST数据集
from sklearn.datats import fetch_openml
import numpy as np
import os
# to make this notebook's output stable across runs
np.random.ed(42)
# To plot pretty figures
%matplotlib inline
import matplotlib as mpl
import matplotlib.pyplot as plt
<('axes', labelsize=14)
<('xtick', labelsize=12)九曲棹歌
<('ytick', labelsize=12)
# 为了显⽰中⽂
2)、定义导⼊数据集函数
# 耗时巨⼤
def sort_by_target(mnist):
邓石如隶书
reorder_train=np.array(sorted([(target,i)for i, target in enumerate(mnist.target[:60000])]))[:,1]
reorder_test=np.array(sorted([(target,i)for i, target in enumerate(mnist.target[60000:])]))[:,1]
mnist.data[:60000]=mnist.data[reorder_train]
mnist.target[:60000]=mnist.target[reorder_train]
mnist.data[60000:]=mnist.data[reorder_test+60000]
mnist.target[60000:]=mnist.target[reorder_test+60000]
3)、测试导⼊数据集函数,并计算导⼊时间
import time
a=time.time()
mnist=fetch_openml('mnist_784',version=1,cache=True)
mnist.target=mnist.target.astype(np.int8)
sort_by_target(mnist)
b=time.time()
print(b-a)
32.70347619056702
4)、取出mnist数据集的数据,并进⾏数据展⽰
X,y=mnist["data"],mnist["target"]
# 展⽰图⽚
def plot_digit(data):
image = shape(28,28)
plt.imshow(image, cmap = binary,
interpolation="nearest")
plt.axis("off")
some_digit = X[36000]
plot_digit(X[36000].reshape(28,28))
5)、定义mnist数据集中数字0-9展⽰功能函数
# 更好看的图⽚展⽰
def plot_digits(instances,images_per_row=10,**options):
size=28
# 每⼀⾏有⼀个
image_pre_row=min(len(instances),images_per_row)
images=[shape(size,size)for instances in instances]
# 有⼏⾏
n_rows=(len(instances)-1)// image_pre_row+1校本培训计划
row_images=[]
n_empty=n_rows*image_pre_row-len(instances)
images.s((size,size*n_empty)))
for row in range(n_rows):
# 每⼀次添加⼀⾏
rimages=images[row*image_pre_row:(row+1)*image_pre_row] # 对添加的每⼀⾏的额图⽚左右连接
row_images.atenate(rimages,axis=1))
# 对添加的每⼀列图⽚上下连接
atenate(row_images,axis=0)
plt.imshow(image,binary,**options)
plt.axis("off")
6)、调⽤函数,实现数字0-9⼿写体的展⽰
plt.figure(figsize=(9,9))
example_images=np.r_[X[:12000:600],X[13000:30600:600],X[30600:60000:590]] plot_digits(example_images,images_per_row=10)
plt.show()
3、接下来,我们需要创建⼀个测试集
1)、创建⼀个测试卷
X_train, X_test, y_train, y_test = X[:60000], X[60000:], y[:60000], y[60000:]
同样,我们还需要对训练集进⾏洗牌,这样可以保证交叉验证的时候,所有的折叠都差不多。此外,有些机器学习算法对训练⽰例的循序敏感,如果连续输⼊许多相似的实例,可能导致执⾏的性能不佳。给数据洗牌,正是为了确保这种情况不会发⽣。
2)、对训练集进⾏洗牌
import numpy as np
shuffer_index=np.random.permutation(60000)
X_train,y_train=X_train[shuffer_index],y_train[shuffer_index]
⼆、训练⼀个⼆分类器
现在,我们先简化问题,只尝试识别⼀个数字,⽐如数字5,那么这个"数字5检测器",就是⼀个⼆分
类器的例⼦,它只能区分两个类别:5和⾮5。先为此分类任务创建⽬录标量
y_train_5=(y_train==5)
y_test_5=(y_test==5)
接着挑选⼀个分类器并开始训练。⼀个好的选择是随机梯度下降(SGD)分类器,使⽤sklearn的SGDClassifier类即可。这个分类器的优势是:能够有效处理⾮常⼤型的数据集。这部分是因为SGD独⽴处理训练实例,⼀次⼀个(这也使得SGD⾮常适合在线学习任务)。
from sklearn.linear_model import SGDClassifier
sgd_clf=SGDClassifier(max_iter=5,tol=-np.infty,random_state=42)
sgd_clf.fit(X_train,y_train_5)
SGDClassifier(alpha=0.0001, average=Fal, class_weight=None,
early_stopping=Fal, epsilon=0.1, eta0=0.0, fit_intercept=True,
l1_ratio=0.15, learning_rate='optimal', loss='hinge', max_iter=5,
n_iter_no_change=5, n_jobs=None, penalty='l2', power_t=0.5,
random_state=42, shuffle=True, tol=-inf, validation_fraction=0.1,
verbo=0, warm_start=Fal)
sgd_clf.predict([some_digit])
array([Fal])
三、性能考核
韩的笔顺评估分类器⽐评估回归器要困难很多,因此本章将会⽤很多篇幅来讨论这个主题,同时也会涉及许多性能考核的⽅法。
1、使⽤交叉验证测量精度
1)、随机交叉验证和分层交叉验证效果对⽐
del_lection import cross_val_score
cross_val_score(sgd_clf, X_train, y_train_5, cv=3, scoring="accuracy")
array([0.9492, 0.9598, 0.9689])
# 类似于分层采样,每⼀折的分布类似
del_lection import StratifiedKFold
from sklearn.ba import clone
skfolds = StratifiedKFold(n_splits=3, 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))
0.9492
0.9598
0.9689
2)、我们可以看到两种交叉验证的准确率都达到了95%上下,看起来很神奇,不过在开始激动之前,让我们来看⼀个蠢笨的分类器,将所有图⽚都预测为‘⾮5’
from sklearn.ba import BaEstimator
# 随机预测模型
class Never5Classifier(BaEstimator):
def fit(lf, X, y=None):
pass
def predict(lf, X):
s((len(X),1), dtype=bool)
never_5_clf = Never5Classifier()
cross_val_score(never_5_clf, X_train, y_train_5, cv=3, scoring="accuracy")
array([0.90965, 0.91135, 0.90795])
我们可以看到,准确率也超过了90%!这是因为我们只有⼤约10%的图像是数字5,所以只要猜⼀张图⽚不是5,那么有90%的时间都是正确的,简直超过了⼤预⾔家。
这说明,准确率通常⽆法成为分类器的⾸要性能指标,特别是当我们处理偏斜数据集的时候(也就是某些类别⽐其他类更加频繁的时候) 2、混淆矩阵
评估分类器性能的更好的⽅法是混淆矩阵。总体思路就是统计A类别实例被分成B类别的次数。例如,
要想知道分类器将数字3和数字5混淆多少次,只需要通过混淆矩阵的第5⾏第3列来查看。
要计算混淆矩阵,需要⼀组预测才能将其与实际⽬标进⾏⽐较。当然可以通过测试集来进⾏预测,但是现在我们不动它(测试集最好保留到项⽬的最后,准备启动分类器时再使⽤)。最为代替,可以使⽤cross_val_predict()函数:
cross_val_predict 和 cross_val_score 不同的是,前者返回预测值,并且是每⼀次训练的时候,⽤模型没有见过的数据来预测
del_lection import cross_val_predict
y_train_pred = cross_val_predict(sgd_clf, X_train, y_train_5, cv=3)
ics import confusion_matrix
confusion_matrix(y_train_5, y_train_pred)
array([[53598, 981],
[ 1461, 3960]], dtype=int64)
上⾯的结果表明:第⼀⾏所有’⾮5’(负类)的图⽚中,有53417被正确分类(真负类),1162,错误分类成了5(假负类);第⼆⾏表⽰所有’5’(正类)的图⽚中,有1350错误分类成了⾮5(假正类),有4071被正确分类成5(真正类).
⼀个完美的分类器只有真正类和真负类,所以其混淆矩阵只会在其对⾓线(左上到右下)上有⾮零值
y_train_perfect_predictions = y_train_5
confusion_matrix(y_train_5, y_train_perfect_predictions)
array([[54579, 0],
[ 0, 5421]], dtype=int64)
混淆矩阵能提供⼤量信息,但有时我们可能会希望指标简洁⼀些。正类预测的准确率是⼀个有意思的指标,它也称为分类器的精度(如下)。
TP
Precision(精度)=TP+FP
其中TP是真正类的数量,FP是假正类的数量。
做⼀个简单的正类预测,并保证它是正确的,就可以得到完美的精度(精度=1/1=100%)
这并没有什么意义,因为分类器会忽略这个正实例之外的所有内容。因此,精度通常会与另⼀个指标⼀起使⽤,这就是召回率,⼜称为灵敏度或者真正类率(TPR):它是分类器正确检测到正类实例的⽐率(如下):
TP
Recall(召回率)=TP+FN
FN是假负类的数量
团队执行力3、精度和召回率
女生打呼噜是什么原因# 使⽤sklearn的⼯具度量精度和召回率
ics import precision_score, recall_score
precision_score(y_train_5, y_train_pred)
0.8014571948998178
recall_score(y_train_5, y_train_pred)
0.7304925290536801