MNIST數據集包含了70000張0~9的手寫數字圖像。
一、准備工作:導入MNIST數據集
1 import sys 2 assert sys.version_info >= (3, 5) 3 4 import sklearn 5 assert sklearn.__version__ >= "0.20" 6 7 import numpy as np 8 import os 9 10 from sklearn.datasets import fetch_openml 11 12 mnist = fetch_openml('mnist_784', version=1) #加載數據集
fatch_openml用來加載數據集,所加載的數據集是一個key-value的字典結構
輸入:mnist.keys()
可以看到字典的鍵值包括:dict_keys(['data', 'target', 'frame', 'categories', 'feature_names', 'target_names', 'DESCR', 'details', 'url'])
其中'data'鍵包含一個數組:實例為行,特征為列;'target'鍵包含一個帶有標記數組。
為了更好的展示'data'和'target'執行下列語句:
X, y = mnist["data"], mnist["target"]
print(X.shape) #data 中有7w張圖即實列為7w,圖像由28*28大小的像素組成即特征為784
print(y.shape) #y為標簽,y[i]顯示x[i]對應的數字
輸出:
(70000, 784) (70000,)
現在我們觀察數據集中的第一個元素:
在這之前我們先准備圖像打印的相關參數:
%matplotlib inline
import matplotlib as mpl
import matplotlib.pyplot as plt
mpl.rc('axes', labelsize=14)
mpl.rc('xtick', labelsize=12)
mpl.rc('ytick', labelsize=12)
現在我們嘗試將數據集中第一個元素的圖像打印出來,執行下列語句:
some_digit = X[0] #抓取X的第一行
some_digit_image = some_digit.reshape(28, 28) #將特征向量重新排序為28*28的像素矩陣
plt.imshow(some_digit_image, cmap=mpl.cm.binary) #imshow函數用於顯示圖像 cmap為顏色設置
plt.axis("off") #不顯示坐標軸
plt.show()
輸出:
二、使用KNN分類器在MNIST數據集上進行分類首先需要將原始數據集進行切片操作:我們將原始數據集的前60000個元素用於對分類器的訓練,后10000個元素用於對分類器分類效果的檢驗
X_train, X_test, y_train, y_test = X[:60000], X[60000:], y[:60000], y[60000:]
接下來我們導入KNN分類器,並用訓練數據集對分類器進行訓練,這里我們設定的KNN中的K=4
from sklearn.neighbors import KNeighborsClassifier knn_clf = KNeighborsClassifier(weights='distance', n_neighbors=4) knn_clf.fit(X_train, y_train) #使用指定的訓練數據集進行訓練 y_knn_pred = knn_clf.predict(X_test) #用訓練好的分類器對測試數據集進行分類預測
值得一提的是KNeighborsClassifier()中可以通過增加n_jobs參數來指定設定工作的core數量,n_jobs=-1時使用全部core。
訓練好的分類器對測試數據集的預測結果存儲在y_knn_pred中,y_knn_pred[i]代表分類器認為的X_test[i]所對應的數字。y_knn_pred是一個序列,其中的元素類型為字符
通過執行語句:
print(y_knn_pred)
輸出:
['7' '2' '1' ... '4' '5' '6']
三、評判分類器的性能我們可以通過混淆矩陣來判斷一個分類器的性能。
通過confusion_matrix()函數我們可以很容易的獲取混淆矩陣,例如執行以下代碼:
from sklearn.metrics import confusion_matrix
print(confusion_matrix(y_test, y_knn_pred))
則輸出:
通過混淆矩陣可以知道分類器將某兩個數字混淆的次數,例如matrix[0,1]=1,就表示分類器將數字0和數字1混淆了1次。
另一方面,混淆矩陣的行表示【實際類別】,列表示【預測類別】,很直觀的可以將預測結果分為以下四類:
TP:真正類
FP:假正類
TN:真負類
FN:假負類
假如說現在的目標是選取數字【5】,則對預測結果的划分如下圖所示:
公式:精度=(TP/(TP+FP))
公式:召回率=(TP/(TP+FN))
執行下列代碼,可以查看一個分類器的精度和召回率:
from sklearn.metrics import recall_score,precision_score print(recall_score(y_test, y_knn_pred, average=None)) print(precision_score(y_test,y_knn_pred, average=None)) """輸出為: [0.99285714 0.99735683 0.96414729 0.96435644 0.96741344 0.96636771 0.9874739 0.96692607 0.94455852 0.95936571] [0.973 0.96834902 0.98417409 0.96819085 0.97535934 0.96312849 0.97828335 0.95945946 0.98818475 0.95746785]"""
另一個顯而易見的問題是如何平衡精度與召回率,這個問題實際上還是蠻復雜的,我會單獨寫一篇博客探討。