机器学习之sklearn使⽤下载MNIST数据集进⾏分类识别
机器学习之sklearn使⽤下载MNIST数据集进⾏分类识别
⼀、MNIST数据集
1.MNIST数据集简介
本次博客使⽤MNIST数据集,这是⼀组由美国⾼中⽣和⼈⼝调查局员⼯⼿写的70000个数字的图⽚。每张图像都⽤其代表的数字标记。这个数据集被⼴为使⽤,因此也被称作是机器学习领域的“Hello World”:但凡有⼈想到了⼀个新的分类算法,都会想看看在MNIST上的执⾏结果。因此只要是学习机器学习的⼈,早晚都要⾯对MNIST。
2.获取MNIST数据集
# 使⽤sklearn的函数来获取MNIST数据集
from sklearn.datasets import fetch_openml
import numpy as np
import os
# to make this notebook's output stable across runs
np.random.seed(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)
# 为了显⽰中⽂
# 耗时巨⼤
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]
接下来获取数据,这⼀步根据电脑性能时间各有不同,⼤家可以跟我⼀样加个定时间查看运⾏所耗费的时间:
import time
time_begin = time.time()
mnist=fetch_openml('mnist_784',version=1,cache=True)
mnist.target=mnist.target.astype(np.int8)
sort_by_target(mnist)
time_end = time.time()
time = time_end - time_begin
print('time:', time)
再对数据集进⾏排序
mnist["data"], mnist["target"]
运⾏结果如下:
Scikit-Learn加载的数据集通常具有类似的字典结构,包括:
1·DESCR键,描述数据集
2·data键,包含⼀个数组,每个实例为⼀⾏,每个特征为⼀列
3·target键,⼀个标签的数组。
接下来我们查看⼀下MNIST数据集的信息,可以使⽤下⾯这三种⽅法:mnist.data.shape
X,y=mnist["data"],mnist["target"]
rows函数的使用方法及实例X.shape
y.shape
28*28
数据共有7万张图⽚,每张图⽚有784个特征。因为图⽚是28×28像素,每个特征代表了⼀个像素点的强度,从0(⽩⾊)到255(⿊⾊),X[36000]的数字如下,通过“y[36000]”查看其标签为“5”。
展⽰单张图⽚:
# 展⽰图⽚
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))
运⾏结果:
展⽰数字:
展⽰更多的数据:
# 更好看的图⽚展⽰
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")
画图展⽰:
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()
结果展⽰:
接下来,我们需要创建⼀个测试集,并把其放在⼀边。
X_train, X_test, y_train, y_test = X[:60000], X[60000:], y[:60000], y[60000:]
同样,我们还需要对训练集进⾏洗牌,这样可以保证交叉验证的时候,所有的折叠都差不多。此外,有些机器学习算法对训练⽰例的循序敏感,如果连续输⼊许多相似的实例,可能导致执⾏的性能不佳。给数据洗牌,正是为了确保这种情况不会发⽣。
import numpy as np
shuffer_index=np.random.permutation(60000)
X_train,y_train=X_train[shuffer_index],y_train[shuffer_index]
⼆、训练⼀个⼆分类器
1、随机梯度下降(SGD)分类器
现在我们先简化问题,只尝试识别⼀个数字,⽐如数字5,那么这个"数字5检测器",就是⼀个⼆分类器
的例⼦,它只能区分两个类别:5和⾮5。
先为此分类任务创建⽬录标量(将数字标签转换为bool型标签true代表 5,false代表 ⾮5):
y_train_5=(y_train==5)
y_test_5=(y_test==5)
接着挑选⼀个分类器并开始训练。⼀个好的选择是随机梯度下降(SGD)分类器,使⽤sklearn的SGDClassifier类即可。这个分类器的优势是:能够有效处理⾮常⼤型的数据集。这部分是因为SGD独⽴处理训练实例,⼀次⼀个(这也使得SGD⾮常适合在线学习任务)。此时先创建⼀个SGDClassifier并在整个训练集上进⾏训练:
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在训练时是完全随机的(因此得名“随机”),如果你希望得到可复现的结果,需要设置参数random_state。
⽤它来检测数字5的图像,输出如下图:
分类正确!
梯度下降法(SGD)是⼀个简单有效的⽅法,⽤于判断使⽤凸loss函数(convex loss function)的分类器(SVM或logistic回归)。SGD被成功地应⽤在⼤规模稀疏机器学习问题上(large-scale and sparse machine learning),经常⽤在⽂本分类及⾃然语⾔处理上。假如数据是稀疏的,该模块的分类器可以轻松地解决这样的问题:超过10^5 的训练样本、超过10^5的features。
SGD的优点是:
⾼效
容易实现(有许多机会进⾏代码调优)
SGD的缺点是:
SGD需要许多超参数:⽐如正则项参数、迭代数。
SGD对于特征归⼀化(feature scaling)是敏感的。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论