使用KNN分類器對MNIST數據集進行分類


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]"""

另一個顯而易見的問題是如何平衡精度與召回率,這個問題實際上還是蠻復雜的,我會單獨寫一篇博客探討。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM