knn实战:如何对手写数字进行识别?
在 Python 的 sklearn 工具包中有 KNN 算法。KNN 既可以做分類器,也可以做回歸。
如果是做分類,你需要引用:
from sklearn.neighbors import KNeighborsClassifier如果是做回歸,你需要引用:
from sklearn.neighbors import KNeighborsRegressor?
?
如何在 sklearn 中創建 KNN 分類器:
我們使用構造函數 KNeighborsClassifier(n_neighbors=5, weights=‘uniform’,algorithm=‘auto’, leaf_size=30),這里有幾個比較主要的參數:
?
| n_neighbors | 即 KNN 中的 K 值,代表的是鄰居的數量。 k小過擬合,k大欠擬合;一般默認使用5 | |
| weights | weights=uniform ? | 代表所有鄰居的權重相同 |
| weights=distance ? | 代表權重是距離的倒數,即與距離成反比 | |
| 自定義函數 | 你可以自定義不同距離所對應的權重。 | |
| algorithm ? | algorithm=auto ? | 根據數據的情況自動選擇適合的算法,默認情況選擇 auto |
| algorithm=kd_tree ? | 也叫作 KD 樹,是多維空間的數據結構,方便對關鍵數據進行檢索;不過 KD 樹適用于維度少的情況,一般維數不超過 20,如果維數大于 20 之后,效率反而會下降; | |
| algorithm=ball_tree ? ? | 也叫作球樹,它和 KD 樹一樣都是多維空間的數據結果,不同于 KD 樹,球樹更適用于維度大的情況; | |
| algorithm=brute ? | 也叫作暴力搜索,它和 KD 樹不同的地方是在于采用的是線性掃描,,而不是通過構造樹結構進行快速檢索。 | |
| leaf_size ? | 代表構造 KD 樹或球樹時的葉子數,默認是 30,調整 leaf_size 會影響到樹的構造和搜索速度。 | |
創建完 KNN 分類器之后,我們就可以輸入訓練集對它進行訓練,這里我們使用 fit() 函數,傳入訓練集中的樣本特征矩陣和分類標識,會自動得到訓練好的 KNN 分類器。然后可以使用?predict() 函數來對結果進行預測,這里傳入測試集的特征矩陣可以得到測試集的預測分類結果。
如何用 KNN 對手寫數字進行識別分類
手寫數字數據集是個非常有名的用于圖像識別的數據集。數字識別的過程就是將這些圖片與分類結果 0-9 一一對應起來。
完整的手寫數字數據集 MNIST 里面包括了 60000 個訓練樣本,以及 10000 個測試樣本。如果你學習深度學習的話,MNIST 基本上是你接觸的第一個數據集。
今天我們用 sklearn 自帶的手寫數字數據集做 KNN 分類,它只包括了 1797 幅數字圖像,每幅圖像大小是 8*8 像素。
訓練分三個階段:
1、加載數據集;本地導入,線上調取,自帶數據集;在這里,我們使用自帶數據集;
2、準備階段:可視化數據描述:樣本量多少,圖像長啥樣,輸入輸出特征;數據處理:缺失值處理,異常值處理、特征工程構造;
3、分類階段:通過訓練可以得到分類器,然后用測試集進行準確率的計算。
?
#加載庫 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 # 加載數據 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()運行結果:
我們對原始數據集中的第一幅進行數據可視化,可以看到圖像是個 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)75%數據作為訓練集;train_x作為訓練集的輸入特征值矩陣,train_y作為訓練集的輸出特征值;
對訓練集與測試集中的輸入特征值進行z評分歸一化;(記住一定要對測試集輸入特征進行同樣的處理!以后談論的變換默認都是對輸入特征進行!)
fit_transform是fit和transform兩個函數都執行一次。所以ss是進行了fit擬合的。只有在fit擬合之后,才能進行transform
在進行test的時候,我們已經在train的時候fit過了,所以直接transform即可。
另外,如果我們沒有fit,直接進行transform會報錯,因為需要先fit擬合,才可以進行transform。
?
然后我們構造一個 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.fit(訓練集輸入特征,訓練集輸出特征)
knn.predict(測試集輸入特征)=模型輸出值
accquary_score(knn.predict(測試集輸入特征),測試集輸出特征)
KNN 準確率: 0.9756
我們選用之前學過的幾個模型,進行預測:
# 創建 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.8356這里需要注意的是,我們在做多項式樸素貝葉斯分類的時候,傳入的數據不能有負數。
因為 Z-Score 會將數值規范化為一個標準的正態分布,即均值為 0,方差為 1,數值會包含負數。因此我們需要采用 Min-Max 規范化,將數據規范化到 [0,1] 范圍內。
數據預處理:無量綱化處理(線性:均值化與標準化;非線性),降維
當輸入特征接近正態分布,使用Z評分歸一化;
當輸入特征呈現高度偏斜,而我們模型對輸入特征的要求是正態分布時,選用Box-Cox變換;
Z評分歸一化的特點:變換結果均值為0,方差為1;變換時對數值進行平移和縮放的同時,保留了密度圖的總體形態
Box-Cox變換:變換時對數值進行平移和縮放的同時,改變了整體形態,產生了比原始圖偏斜更少的密度圖。
降維:特征縮減,比如PCA-主成分分析
特征工程:根據原有的特征,設計新的特征(實際應用需要反復驗證)
倘若同樣的數據集,改變k值,會得出如下結論:
knn默認k值為5 準確率:0.9756
knn的k值為200的準確率:0.8489
SVM分類準確率:0.9867
高斯樸素貝葉斯準確率:0.8111
多項式樸素貝葉斯分類器準確率:0.8844
CART決策樹準確率:0.8400
K值的選取如果過大,正確率降低。?
算法效率排行 SVM > KNN(k值在合適范圍內) >多項式樸素貝葉斯 > CART > 高斯樸素貝葉斯
分別用 KNN、SVM、樸素貝葉斯和決策樹做分類器,并統計了四個分類器的準確率。在數據量不大的情況下,使用 sklearn 還是方便的。
如果數據量很大,比如 MNIST 數據集中的?6 萬個訓練數據和 1 萬個測試數據,那么采用深度學習 +GPU 運算的方式會更適合。
因為深度學習的特點就是需要大量并行的重復計算,GPU 最擅長的就是做大量的并行計算。
?
總結:
1、各模型對輸入特征是有分布要求的;比如多項式樸素貝葉斯分類要求數據非負;最小二乘法模型要求數據是正態分布,滿足四大假設;神經網絡則對數據分布無要求。
2、特征變換是針對輸入特征的;特征變化是數據處理的子集,決定模型的上限,而模型的好壞只是逼近這個上限
3、skearn適合數據量較小的訓練,若是數據量過大,可以采用深度學習框架+GPU運算。實際運用中,可以使用集成學習(機器學習+深度學習框架)完成。
?
參考:
數據分析實戰45講
用商業案例學R語言數據挖掘--特征工程
數據預處理
?
總結
以上是生活随笔為你收集整理的knn实战:如何对手写数字进行识别?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: SVM实战:如何进行乳腺癌检测
- 下一篇: 实战:关联规则挖掘