如何在 sklearn 中使用 KNN
在 Python 的 sklearn 工具包中有 KNN 算法。KNN 既可以做分類器,也可以做回歸。如果是做分類,你需要引用:
from sklearn.neighbors import KNeighborsClassifier
如果是做回歸,你需要引用:
from sklearn.neighbors import KNeighborsRegressor
如何用 KNN 對手寫數字進行識別分類
我們先來規划下整個 KNN 分類的流程:
整個訓練過程基本上都會包括三個階段:
-
數據加載:我們可以直接從 sklearn 中加載自帶的手寫數字數據集;
-
准備階段:在這個階段中,我們需要對數據集有個初步的了解,比如樣本的個數、圖像長什么樣、識別結果是怎樣的。你可以通過可視化的方式來查看圖像的呈現。通過數據規范化可以讓數據都在同一個數量級的維度。另外,因為訓練集是圖像,每幅圖像是個 8*8 的的矩陣,我們不需要對它進行特征選擇,將全部的圖像數據作為特征值矩陣即可;
-
分類階段:通過訓練可以得到分類器,然后用測試集進行准確率的計算。
首先是加載數據和對數據的探索:
# 加載數據 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