KNN之手寫數字識別


如何在 sklearn 中使用 KNN

在 Python 的 sklearn 工具包中有 KNN 算法。KNN 既可以做分類器,也可以做回歸。如果是做分類,你需要引用:

from sklearn.neighbors import KNeighborsClassifier

如果是做回歸,你需要引用:

from sklearn.neighbors import KNeighborsRegressor

如何用 KNN 對手寫數字進行識別分類

我們先來規划下整個 KNN 分類的流程:

整個訓練過程基本上都會包括三個階段:

  1. 數據加載:我們可以直接從 sklearn 中加載自帶的手寫數字數據集;

  2. 准備階段:在這個階段中,我們需要對數據集有個初步的了解,比如樣本的個數、圖像長什么樣、識別結果是怎樣的。你可以通過可視化的方式來查看圖像的呈現。通過數據規范化可以讓數據都在同一個數量級的維度。另外,因為訓練集是圖像,每幅圖像是個 8*8 的的矩陣,我們不需要對它進行特征選擇,將全部的圖像數據作為特征值矩陣即可;

  3. 分類階段:通過訓練可以得到分類器,然后用測試集進行准確率的計算。

首先是加載數據和對數據的探索:

# 加載數據
digits = load_digits()
data = digits.data
# 數據探索
print(data.shape)
# 查看第一幅圖像
print(digits.images[0])
# 第一幅圖像代表的數字含義
print(digits.target[0])
# 將第一幅圖像顯示出來
plt.gray()
plt.imshow(digits.images[0])
plt.show()


# 運行結果:
(1797, 64)
[[ 0.  0.  5. 13.  9.  1.  0.  0.]
 [ 0.  0. 13. 15. 10. 15.  5.  0.]
 [ 0.  3. 15.  2.  0. 11.  8.  0.]
 [ 0.  4. 12.  0.  0.  8.  8.  0.]
 [ 0.  5.  8.  0.  0.  9.  8.  0.]
 [ 0.  4. 11.  0.  1. 12.  7.  0.]
 [ 0.  2. 14.  5. 10. 12.  0.  0.]
 [ 0.  0.  6. 13. 10.  0.  0.  0.]]
0

我們對原始數據集中的第一幅進行數據可視化,可以看到圖像是個8*8 的像素矩陣,上面這幅圖像是一個“0”,從訓練集的分類標注中我們也可以看到分類標注為“0”。

sklearn 自帶的手寫數字數據集一共包括了 1797 個

樣本,每幅圖像都是 8*8 像素的矩陣。因為並沒有專門的測試集,所以我們需要對數據集做划分,划分成訓練集和測試集。因為KNN 算法和距離定義相關,我們需要對數據進行規范化處理,采用 Z-Score 規范化,代碼如下:

# 分割數據,將 25% 的數據作為測試集,其余作為訓練集(你也可以指定其他比例的數據作為訓練集)
train_x, test_x, train_y, test_y = train_test_split(data, digits.target, test_size=0.25, random_state=33)
# 采用 Z-Score 規范化
ss = preprocessing.StandardScaler()
train_ss_x = ss.fit_transform(train_x)
test_ss_x = ss.transform(test_x)

然后我們構造一個 KNN 分類器 knn,把訓練集的數據傳入構造好的 knn,並通過測試集進行結果預測,與測試集的結果進行對比,得到 KNN 分類器准確率,代碼如下:

# 創建 KNN 分類器
knn = KNeighborsClassifier() 
knn.fit(train_ss_x, train_y) 
predict_y = knn.predict(test_ss_x) 
print("KNN 准確率: %.4lf" % accuracy_score(predict_y, test_y))


# 運行結果:
KNN 准確率: 0.9756

這樣我們就構造好了一個 KNN 分類器。之前我們還講過 SVM、朴素貝葉斯和決策樹分類。我們用手寫數字數據集一起來訓練下這些分類器,然后對比下哪個分類器的效果更好。代碼如下:

# 創建 SVM 分類器
svm = SVC()
svm.fit(train_ss_x, train_y)
predict_y=svm.predict(test_ss_x)
print('SVM 准確率: %0.4lf' % accuracy_score(predict_y, test_y))
# 采用 Min-Max 規范化
mm = preprocessing.MinMaxScaler()
train_mm_x = mm.fit_transform(train_x)
test_mm_x = mm.transform(test_x)
# 創建 Naive Bayes 分類器
mnb = MultinomialNB()
mnb.fit(train_mm_x, train_y) 
predict_y = mnb.predict(test_mm_x) 
print(" 多項式朴素貝葉斯准確率: %.4lf" % accuracy_score(predict_y, test_y))
# 創建 CART 決策樹分類器
dtc = DecisionTreeClassifier()
dtc.fit(train_mm_x, train_y) 
predict_y = dtc.predict(test_mm_x) 
print("CART 決策樹准確率: %.4lf" % accuracy_score(predict_y, test_y))


# 運行結果:
SVM 准確率: 0.9867
多項式朴素貝葉斯准確率: 0.8844
CART 決策樹准確率: 0.8556

這里需要注意的是,我們在做多項式朴素貝葉斯分類的時候,傳入的數據不能有負數。因為 Z-Score 會將數值規范化為一個標准的正態分布,即均值為 0,方差為 1,數值會包含負數。因此我們需要采用 Min-Max 規范化,將數據規范化到 [0,1] 范圍內。

####    多項式朴素貝葉斯實際上是符合多項式分布,不會存在負數。而高斯朴素貝葉斯呈現的是高斯分布,也就是正態分布,比如均值為0,方差為1的標准正態分布,可以存在負數。

整理下這 4 個分類器的結果:

# 相關的導包
from sklearn.model_selection import train_test_split
from sklearn import preprocessing
from sklearn.metrics import accuracy_score
from sklearn.datasets import load_digits
from sklearn.neighbors import KNeighborsClassifier
from sklearn.svm import SVC
from sklearn.naive_bayes import MultinomialNB
from sklearn.tree import DecisionTreeClassifier
import matplotlib.pyplot as plt

 


免責聲明!

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



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