from sklearn.datasets import fetch_openml
mnist = fetch_openml("mnist_784")
/home/h/miniconda3/lib/python3.8/site-packages/sklearn/datasets/_openml.py:932: FutureWarning: The default value of `parser` will change from `'liac-arff'` to `'auto'` in 1.4. You can set `parser='auto'` to silence this warning. Therefore, an `ImportError` will be raised from 1.4 if the dataset is dense and pandas is not installed. Note that the pandas parser may return different data types. See the Notes Section in fetch_openml's API doc for details. warn(
print(mnist.keys()) # 看下数据集中有啥键,'data', 'target' 分别为 特征(就是每张图像)和标签
print(mnist['DESCR']) # 打印下说明
dict_keys(['data', 'target', 'frame', 'categories', 'feature_names', 'target_names', 'DESCR', 'details', 'url']) **Author**: Yann LeCun, Corinna Cortes, Christopher J.C. Burges **Source**: [MNIST Website](http://yann.lecun.com/exdb/mnist/) - Date unknown **Please cite**: The MNIST database of handwritten digits with 784 features, raw data available at: http://yann.lecun.com/exdb/mnist/. It can be split in a training set of the first 60,000 examples, and a test set of 10,000 examples It is a subset of a larger set available from NIST. The digits have been size-normalized and centered in a fixed-size image. It is a good database for people who want to try learning techniques and pattern recognition methods on real-world data while spending minimal efforts on preprocessing and formatting. The original black and white (bilevel) images from NIST were size normalized to fit in a 20x20 pixel box while preserving their aspect ratio. The resulting images contain grey levels as a result of the anti-aliasing technique used by the normalization algorithm. the images were centered in a 28x28 image by computing the center of mass of the pixels, and translating the image so as to position this point at the center of the 28x28 field. With some classification methods (particularly template-based methods, such as SVM and K-nearest neighbors), the error rate improves when the digits are centered by bounding box rather than center of mass. If you do this kind of pre-processing, you should report it in your publications. The MNIST database was constructed from NIST's NIST originally designated SD-3 as their training set and SD-1 as their test set. However, SD-3 is much cleaner and easier to recognize than SD-1. The reason for this can be found on the fact that SD-3 was collected among Census Bureau employees, while SD-1 was collected among high-school students. Drawing sensible conclusions from learning experiments requires that the result be independent of the choice of training set and test among the complete set of samples. Therefore it was necessary to build a new database by mixing NIST's datasets. The MNIST training set is composed of 30,000 patterns from SD-3 and 30,000 patterns from SD-1. Our test set was composed of 5,000 patterns from SD-3 and 5,000 patterns from SD-1. The 60,000 pattern training set contained examples from approximately 250 writers. We made sure that the sets of writers of the training set and test set were disjoint. SD-1 contains 58,527 digit images written by 500 different writers. In contrast to SD-3, where blocks of data from each writer appeared in sequence, the data in SD-1 is scrambled. Writer identities for SD-1 is available and we used this information to unscramble the writers. We then split SD-1 in two: characters written by the first 250 writers went into our new training set. The remaining 250 writers were placed in our test set. Thus we had two sets with nearly 30,000 examples each. The new training set was completed with enough examples from SD-3, starting at pattern # 0, to make a full set of 60,000 training patterns. Similarly, the new test set was completed with SD-3 examples starting at pattern # 35,000 to make a full set with 60,000 test patterns. Only a subset of 10,000 test images (5,000 from SD-1 and 5,000 from SD-3) is available on this site. The full 60,000 sample training set is available. Downloaded from openml.org.
查看下 数据维度和类型
mnist["data"].shape, mnist["target"].shape, type(mnist["target"])
((70000, 784), (70000,), pandas.core.series.Series)
为了方便,我们将 panda 对象转为 numpy
x = mnist["data"].to_numpy()
y = mnist["target"].to_numpy()
x.shape, y.shape
((70000, 784), (70000,))
画图显示下数据和对应的标签
import matplotlib.pyplot as plt
# 8 行 8 列
fig, axes = plt.subplots(8, 8, figsize=(10, 10),
subplot_kw={'xticks':[], 'yticks':[]},
gridspec_kw=dict(hspace=0.1, wspace=0.1))
# 绿的是 标签值
for i, ax in enumerate(axes.flat):
ax.imshow(x[i].reshape(28, 28), cmap='binary', interpolation='nearest')
ax.text(0.05, 0.05, str(y[i]),
transform=ax.transAxes, color='green')
from sklearn.model_selection import train_test_split
Xtrain, Xtest, ytrain, ytest = train_test_split(x, y, random_state=42)
Xtrain.shape, ytrain.shape
((52500, 784), (52500,))
from sklearn.svm import SVC
model = SVC(kernel='rbf', class_weight='balanced')
model.fit(Xtrain, ytrain) # 需要花一些时间
SVC(class_weight='balanced')In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
SVC(class_weight='balanced')
将训练好的模型来跑下测试集
ypred = model.predict(Xtest) # 需要花一些时间
统计下模型分类精度
from sklearn.metrics import accuracy_score
accuracy_score(ytest, ypred)
0.9765142857142857
默认的参数看来模型不太行啊,没有达到 99%。下面画以下 混淆矩阵
from sklearn.metrics import confusion_matrix
import seaborn as sns
mat = confusion_matrix(ytest, ypred)
sns.heatmap(mat, square=True, annot=True, cbar=False, fmt='.20g', annot_kws={"fontsize":8}) # fmt:不用科学计数法
plt.xlabel('predicted value')
plt.ylabel('true value')
Text(113.9222222222222, 0.5, 'true value')
预测错误的 标注为 红色,对的为 绿色
fig, axes = plt.subplots(5, 5, figsize=(28, 28),
subplot_kw={'xticks':[], 'yticks':[]},
gridspec_kw=dict(hspace=0.1, wspace=0.1))
test_images = Xtest.reshape(-1, 28, 28)
for i, ax in enumerate(axes.flat):
ax.imshow(test_images[i], cmap='binary', interpolation='nearest')
ax.text(0.05, 0.05, str(ypred[i]),
transform=ax.transAxes,
color='green' if (ytest[i] == ypred[i]) else 'red',
fontsize=30)
统计结果
from sklearn.metrics import classification_report
target_names = list(mnist['target'].cat.categories)
print(classification_report(ytest, ypred,
target_names=target_names))
precision recall f1-score support 0 0.99 0.99 0.99 1714 1 0.98 0.99 0.99 1977 2 0.97 0.98 0.97 1761 3 0.97 0.97 0.97 1806 4 0.97 0.98 0.97 1587 5 0.98 0.97 0.98 1607 6 0.98 0.99 0.99 1761 7 0.97 0.97 0.97 1878 8 0.98 0.96 0.97 1657 9 0.97 0.96 0.97 1752 accuracy 0.98 17500 macro avg 0.98 0.98 0.98 17500 weighted avg 0.98 0.98 0.98 17500
from sklearn.svm import SVC
from sklearn.decomposition import PCA as RandomizedPCA
from sklearn.pipeline import make_pipeline
# 28*28 降维为 10
pca = RandomizedPCA(n_components=10, whiten=True, random_state=42)
svc = SVC(kernel='rbf', class_weight='balanced')
model = make_pipeline(pca, svc)
model.fit(Xtrain, ytrain) # 速度明显加快,可以统计下时间
Pipeline(steps=[('pca', PCA(n_components=10, random_state=42, whiten=True)), ('svc', SVC(class_weight='balanced'))])In a Jupyter environment, please rerun this cell to show the HTML representation or trust the notebook.
Pipeline(steps=[('pca', PCA(n_components=10, random_state=42, whiten=True)), ('svc', SVC(class_weight='balanced'))])
PCA(n_components=10, random_state=42, whiten=True)
SVC(class_weight='balanced')
ypred = model.predict(Xtest)
from sklearn.metrics import accuracy_score
accuracy_score(ytest, ypred) # 降低了,看来 svm 的默认参数确实效果一般
0.9339428571428572
其余步骤请参考上面内容...