KNN算法也是基于距離的簡單算法刺覆,本主題主要說明:
??1. KNN算法的數(shù)學模型哥倔;
??2. KNN的實現(xiàn)與應用兜喻;
??3. 交叉驗證尋找最合適的K涩哟;
KNN緊鄰算法的說明
- KNN(K-Nearest Neighbor)K最近鄰算法
- 對于KNN緊鄰算法需要說明的有如下幾點:
- KNN緊鄰算法是基于距離的算法。
- KNN主要用于分類侵贵。
- KNN是一種有監(jiān)督學習届搁。
KNN緊鄰算法
KNN(K-Nearest Neighbor)的特點
- KNN算法沒有訓練過程,對一個沒有標簽的數(shù)據(jù)窍育,KNN算法直接在已經標簽的數(shù)據(jù)集(俗稱訓練集)之上對未標簽的數(shù)據(jù)分類卡睦。
KNN的算法模型
-
假設已知訓練數(shù)據(jù)集
- 樣本總數(shù)就是
假設需要分類的樣本是
-
算法過程
- 計算待分類樣本到所有訓練樣本的距離
- 在D中取前K個比較小的距離。
- 統(tǒng)計每個類別在K個較小距離中對應的樣本點的數(shù)量漱抓;
- 待分類樣本就屬于樣本點最多的那個類別表锻。
-
算法例子說明:
- 假設數(shù)據(jù)集是鳶尾花,150個樣本辽旋,一共三類(假設A浩嫌,B檐迟,C三類)补胚。
- 待分類樣本
- 計算到150個樣本的距離(一般歐氏距離),一共得到150個距離追迟。
- 在150個距離中溶其,取前K個較小距離。
- 統(tǒng)計K個距離中敦间,ABC三類占的數(shù)量瓶逃。
- 樣本就屬于最大那個分類。
KNN算法中K值的選擇
-
K緊鄰算法中的K的選擇對分類結果會產生比較大的影響廓块。
-
K較小
- 預測結果對近鄰的實例點非常敏感厢绝。
- 容易發(fā)生過擬合(估計誤差會增大【爭對測試集】,近似誤差較少【爭對訓練集】)
-
K較大
- 較遠的訓練實例也會對預測起作用
- 使預測發(fā)生錯誤带猴,k值增大模型的復雜度會下降昔汉,當K=樣本數(shù)量N的時候,模型就變成單一模型拴清。
-
K較小
在實際應用靶病,K值一般選取比較下的值会通。
距離的選擇在這里也顯得比較重要。
距離的定義
- 常見的距離的定義
- 歐氏距離(Euclidean)
- 曼哈頓距離(Manhattan / City Block distance)
- 切比雪夫距離(Chebyshev)
- 閔可夫斯基距離(Minkowski)
- 標準化歐氏距離(Standardized Euclidean)
- 馬氏距離(Mahalanobis)
- 巴氏距離(Bhattacharyya)
- 漢明距離(Hamming)
- 夾角余弦(Cosine)
- 杰卡德距離(Jaccard)
- 皮爾遜距離(Pearson)
KNN算法實現(xiàn)與應用
KNN算法標量版本
import numpy as np
import sklearn.datasets as ds
def knn(train_data, train_label, sample, k):
"""
train_data:訓練集
train_label:訓練集的分類標簽
sample:待分類樣本
k:用來分類判定的前K個距離的個數(shù)
"""
# 1. 計算待分類樣本sample與所有訓練集的距離
distances = [] # 存放sample到所有訓練集的距離
for s in train_data:
diff = (s - sample)**2
distance = np.sqrt(diff.sum())
distances.append(distance)
# 2. 對距離排序(從小到大)娄周,取前K個來統(tǒng)計分類(返回排序后的下標)
distances_np = np.array(distances) # 轉換為ndarray涕侈,利用其中的返回排序后的下標功能
sorted_index = distances_np.argsort()
# 3. 統(tǒng)計前K個距離對應訓練樣本的分類數(shù)量
categories = {} # 存放前k個距離的類別統(tǒng)計
for i in range(k):
# 取排序下標,在target標簽中得到類別
idx = sorted_index[i] # 取下標
category = train_label[idx] # 取列別
if category not in categories:
categories[category] = 0
categories[category] += 1
# print(categories)
# 4. 分類數(shù)量最多的就是帶分類樣本的分類類別(返回類別下標)
# 對統(tǒng)計的類別 categories 進行排序煤辨,其中最后一個就是最多的類別就是待分類樣本的類別裳涛。
categories_sorted = sorted(categories.items(), key= lambda x: x[1], reverse=True) # 返回列表
return categories_sorted[0][0] # 第一個最大,取第一個數(shù)據(jù)的第一個值:就是類別
# --- 數(shù)據(jù)加載與測試
# 數(shù)據(jù)加載
data, target = ds.load_iris(return_X_y=True)
# 使用第一個樣本來測試掷酗,k=7
data, target = ds.load_iris(return_X_y=True)
knn(data, target, data[100], 7)
2
KNN算法向量版本
import numpy as np
import sklearn.datasets as ds
def knn_v(train_data, train_label, sample, k):
diff = (train_data - sample)**2
distances = np.sqrt(diff.sum(axis=1))
sorted_index = distances.argsort()
categories = {}
for i in range(k):
category = train_label[sorted_index[I]]
categories[category] = categories.get(category,0) + 1
# print(categories)
categories_sorted = sorted(categories.items(), key= lambda x: x[1], reverse=True) # 返回列表
return categories_sorted[0][0] # 第一個最大调违,取第一個數(shù)據(jù)的第一個值:就是類別
data, target = ds.load_iris(return_X_y=True)
knn_v(data, target, data[100], 7)
2
# --- 數(shù)據(jù)加載與測試
# 數(shù)據(jù)加載
data, target = ds.load_iris(return_X_y=True)
# 生成交叉驗證方案
kf = KFold(n_splits=5)
ss = ShuffleSplit(n_splits=10, test_size=0.20)
result_split = ss.split(data)
# 開始交叉驗證
# 存放k=1,k=2泻轰,...技肩,k=120的正確數(shù),最高的那個k就是我們選擇的k
k_rates = {} # key對應k的值浮声,value對應分類正確數(shù)
Ks = 120
for index_train, index_test in result_split:
# 根據(jù)索引得到訓練集與測試集
data_train = data.take(index_train, axis=0)
target_train = target.take(index_train)
# 訓練測試集虚婿,統(tǒng)計識別正確總數(shù)(對所有交叉方案統(tǒng)計的結果)
for idx in index_test:
sample = data[idx]
# 訓練取k
for k in range(1, Ks+1):
c = knn(data_train, target_train, sample, k)
# 判定分類是否正確
if c == target[idx]: # 分類正確
# 統(tǒng)計數(shù)據(jù)到k_rates
if k not in k_rates: # 如果字典中沒有k對應的key,則增加一個
k_rates[k] = 0
k_rates[k] +=1 # 正確數(shù)累加
# 選擇正確最高的作為k
k_rates_sorted = sorted(k_rates.items(), key= lambda x: x[1], reverse=True)
best_k = k_rates_sorted[0][0]
print(best_k, k_rates_sorted[0][1])
# k_rates_sorted
%matplotlib inline
import matplotlib.pyplot as plt
figure = plt.figure('KNN', figsize=(8, 6))
ax = figure.add_axes([0.1, 0.1, 0.8, 0.8])
dict_sorted = dict(sorted(k_rates.items(), key= lambda x: x[0], reverse=False))
ax.plot(dict_sorted.keys(), dict_sorted.values(), color=(1, 0, 0, 1))
plt.show()
dict_data.keys()
9 296
dict_keys([69, 71, 72, 55, 70, 57, 58, 65, 73, 76, 54, 59, 68, 75, 56, 66, 60, 64, 52, 53, 67, 74, 61, 63, 51, 62, 50, 47, 77, 78, 44, 48, 45, 46, 33, 49, 35, 36, 37, 38, 43, 90, 42, 31, 34, 40, 79, 105, 80, 84, 89, 91, 39, 28, 29, 41, 88, 107, 87, 27, 32, 24, 26, 92, 93, 30, 82, 83, 110, 106, 86, 85, 94, 114, 104, 23, 25, 81, 115, 117, 20, 113, 103, 19, 95, 108, 21, 22, 111, 116, 97, 98, 101, 14, 109, 112, 119, 102, 96, 18, 120, 99, 100, 1, 2, 17, 5, 12, 16, 118, 10, 6, 8, 9, 13, 15, 3, 7, 11, 4])
交叉驗證與k的選取
交叉驗證的概念
- 交叉驗證的包含兩個重要的操作
- 數(shù)據(jù)集分成兩個部分:一部分用來作為訓練數(shù)據(jù)集泳挥,另外一部分用來測試數(shù)據(jù)集然痊。
- 數(shù)據(jù)重復使用,多次訓練與測試(我們把一次訓練與測試稱為一次驗證):在重復驗證過程屉符,某個數(shù)據(jù)在第一次驗證可能是訓練樣本剧浸,在下一次驗證有可能是測試樣本。
交叉驗證的樣本選擇方式
-
基本交叉驗證
- 數(shù)據(jù)集隨機洗牌打亂矗钟,然后按照比例分成兩部分:訓練數(shù)據(jù)集與測試數(shù)據(jù)集唆香;
- 反復重復上述過程。
-
K折交叉驗證
據(jù)集隨機洗牌打亂吨艇,分成K份躬它。
隨機的選擇K-1份作為訓練集,剩下的1份做測試集东涡,這樣數(shù)據(jù)集分成兩個部分:訓練數(shù)據(jù)集與測試數(shù)據(jù)集冯吓。
重復從K分鐘隨機選擇K-1份作為訓練集,剩下的1份做測試集疮跑;(這里是對K份重復隨機组贺,不再對數(shù)據(jù)集再隨機洗牌打亂)
注意:K折方式也可以反復調用。
-
留一交叉驗證
- 是K折交叉驗證的特例祖娘,就是K = N(N是樣本總數(shù))
- 這種情況用于樣本數(shù)比較少的情況失尖。
-
留P交叉驗證
- 與留一交叉驗證類似,只是從訓練集中剔除P個樣本。
在sklearn提供了用戶自定義數(shù)據(jù)集劃分方式
sklearn的樣本切割實現(xiàn)
切割函數(shù)train_test_split
- 把數(shù)據(jù)集隨機切割成兩個部分
sklearn.model_selection.train_test_split(
*arrays : sequence of indexables with same length / shape[0] # 拆分數(shù)據(jù)集
test_size : float, int or None, optional (default=None) # 測試集比例
train_size : float, int, or None, (default=None) # 訓練集比例
shuffle : boolean, optional (default=True) # 是否打亂
)
import sklearn.datasets as ds
from sklearn.model_selection import train_test_split
# 加載數(shù)據(jù)集
data,target = ds.load_iris(return_X_y=True)
# 切分數(shù)據(jù)集
data_train, data_test, target_train, target_test = train_test_split(
data, # 數(shù)據(jù)集
target, # 數(shù)據(jù)集標簽
test_size=0.2)
print(data_train.shape, data_test.shape)
(120, 4) (30, 4)
切割類KFold雹仿,LeaveOneOut增热,LeavePOut,ShuffleSplit
- sklearn提供了系列的切分類:
- KFold
import sklearn.datasets as ds
from sklearn.model_selection import KFold, LeaveOneOut, LeavePOut, ShuffleSplit
# 加載數(shù)據(jù)集
data,target = ds.load_iris(return_X_y=True)
# k折切分
kf = KFold(n_splits=5)
result_split = kf.split(data) # 返回生成器
for index_train, index_test in result_split:
print(index_train.shape, index_test.shape)
# 返回下標胧辽,可以在原來數(shù)據(jù)上操作
data_test = data.take(index_test, axis=0)
data_train = data.take(index_train, axis=0)
print(data_train.shape, data_test.shape)
(120,) (30,)
(120,) (30,)
(120,) (30,)
(120,) (30,)
(120,) (30,)
(120, 4) (30, 4)
- LeaveOneOut
import sklearn.datasets as ds
from sklearn.model_selection import KFold, LeaveOneOut, LeavePOut, ShuffleSplit
# 加載數(shù)據(jù)集
data,target = ds.load_iris(return_X_y=True)
# 留一切分
loo = LeaveOneOut()
result_split = loo.split(data) # 返回生成器
for index_train, index_test in result_split:
print(index_train.shape, index_test.shape)
break
# 返回下標峻仇,可以在原來數(shù)據(jù)上操作
data_test = data.take(index_test, axis=0)
data_train = data.take(index_train, axis=0)
print(data_train.shape, data_test.shape)
(149,) (1,)
(149, 4) (1, 4)
- LeavePOut
import sklearn.datasets as ds
from sklearn.model_selection import KFold, LeaveOneOut, LeavePOut, ShuffleSplit
# 加載數(shù)據(jù)集
data,target = ds.load_iris(return_X_y=True)
# 留p切分
lpo = LeavePOut(p=30) # 留30個
result_split = lpo.split(data) # 返回生成器
for index_train, index_test in result_split:
print(index_train.shape, index_test.shape)
break
# 返回下標,可以在原來數(shù)據(jù)上操作
data_test = data.take(index_test, axis=0)
data_train = data.take(index_train, axis=0)
print(data_train.shape, data_test.shape)
(120,) (30,)
(120, 4) (30, 4)
- ShuffleSplit
import sklearn.datasets as ds
from sklearn.model_selection import KFold, LeaveOneOut, LeavePOut, ShuffleSplit
# 加載數(shù)據(jù)集
data,target = ds.load_iris(return_X_y=True)
# 隨機切分
ss = ShuffleSplit(n_splits=2, test_size=0.20) # 生成的重復次數(shù)
result_split = ss.split(data) # 返回生成器
for index_train, index_test in result_split:
print(index_train.shape, index_test.shape)
# break
# 返回下標邑商,可以在原來數(shù)據(jù)上操作
data_test = data.take(index_test, axis=0)
data_train = data.take(index_train, axis=0)
print(data_train.shape, data_test.shape)
(120,) (30,)
(120,) (30,)
(120, 4) (30, 4)
KNN的k的選擇
- 使用K折交叉驗證摄咆,其他的可以自己使用
import numpy as np
import sklearn.datasets as ds
from sklearn.model_selection import KFold, LeaveOneOut, LeavePOut, ShuffleSplit
from sklearn.model_selection import train_test_split
def knn(train_data, train_label, sample, k):
"""
train_data:訓練集
train_label:訓練集的分類標簽
sample:待分類樣本
k:用來分類判定的前K個距離的個數(shù)
"""
# 1. 計算待分類樣本sample與所有訓練集的距離
distances = [] # 存放sample到所有訓練集的距離
for s in train_data:
diff = s - sample
distance = np.sqrt(np.dot(diff, diff))
distances.append(distance)
# 2. 對距離排序(從小到大),取前K個來統(tǒng)計分類(返回排序后的下標)
distances_np = np.array(distances) # 轉換為ndarray人断,利用其中的返回排序后的下標功能
sorted_index = distances_np.argsort()
# 3. 統(tǒng)計前K個距離對應訓練樣本的分類數(shù)量
categories = {} # 存放前k個距離的類別統(tǒng)計
for i in range(k):
# 取排序下標吭从,在target標簽中得到類別
idx = sorted_index[i] # 取下標
category = train_label[idx] # 取列別
if category not in categories:
categories[category] = 0
categories[category] += 1
# 4. 分類數(shù)量最多的就是帶分類樣本的分類類別(返回類別下標)
# 對統(tǒng)計的類別 categories 進行排序,其中最后一個就是最多的類別就是待分類樣本的類別恶迈。
categories_sorted = sorted(categories.items(), key= lambda x: x[1], reverse=True) # 返回列表
return categories_sorted[0][0] # 第一個最大涩金,取第一個數(shù)據(jù)的第一個值:就是類別
# --- 數(shù)據(jù)加載與測試
# 數(shù)據(jù)加載
data, target = ds.load_iris(return_X_y=True)
# 生成交叉驗證方案
kf = KFold(n_splits=5)
ss = ShuffleSplit(n_splits=10, test_size=0.20)
result_split = ss.split(data)
# 開始交叉驗證
# 存放k=1,k=2暇仲,...步做,k=120的正確數(shù),最高的那個k就是我們選擇的k
k_rates = {} # key對應k的值奈附,value對應分類正確數(shù)
Ks = 120
for index_train, index_test in result_split:
# 根據(jù)索引得到訓練集與測試集
data_train = data.take(index_train, axis=0)
target_train = target.take(index_train)
# 訓練測試集全度,統(tǒng)計識別正確總數(shù)(對所有交叉方案統(tǒng)計的結果)
for idx in index_test:
sample = data[idx]
# 訓練取k
for k in range(1, Ks+1):
c = knn(data_train, target_train, sample, k)
# 判定分類是否正確
if c == target[idx]: # 分類正確
# 統(tǒng)計數(shù)據(jù)到k_rates
if k not in k_rates: # 如果字典中沒有k對應的key,則增加一個
k_rates[k] = 0
k_rates[k] +=1 # 正確數(shù)累加
# 選擇正確最高的作為k
k_rates_sorted = sorted(k_rates.items(), key= lambda x: x[1], reverse=True)
best_k = k_rates_sorted[0][0]
print(best_k, k_rates_sorted[0][1])
# k_rates_sorted
15 292
# 可視化
%matplotlib inline
import matplotlib.pyplot as plt
figure = plt.figure('KNN', figsize=(8, 6))
ax = figure.add_axes([0.1, 0.1, 0.8, 0.8])
dict_sorted = dict(sorted(k_rates.items(), key= lambda x: x[0], reverse=False))
ax.plot(dict_sorted.keys(), dict_sorted.values(), color=(1, 0, 0, 1))
plt.show()
dict_data.keys()
dict_keys([69, 71, 72, 55, 70, 57, 58, 65, 73, 76, 54, 59, 68, 75, 56, 66, 60, 64, 52, 53, 67, 74, 61, 63, 51, 62, 50, 47, 77, 78, 44, 48, 45, 46, 33, 49, 35, 36, 37, 38, 43, 90, 42, 31, 34, 40, 79, 105, 80, 84, 89, 91, 39, 28, 29, 41, 88, 107, 87, 27, 32, 24, 26, 92, 93, 30, 82, 83, 110, 106, 86, 85, 94, 114, 104, 23, 25, 81, 115, 117, 20, 113, 103, 19, 95, 108, 21, 22, 111, 116, 97, 98, 101, 14, 109, 112, 119, 102, 96, 18, 120, 99, 100, 1, 2, 17, 5, 12, 16, 118, 10, 6, 8, 9, 13, 15, 3, 7, 11, 4])
k選擇的測試
- 根據(jù)上面的交叉驗證斥滤,選擇k=7将鸵,下面是測試結果。
import numpy as np
import sklearn.datasets as ds
from sklearn.model_selection import KFold, LeaveOneOut, LeavePOut, ShuffleSplit
from sklearn.model_selection import train_test_split
def knn(train_data, train_label, sample, k):
"""
train_data:訓練集
train_label:訓練集的分類標簽
sample:待分類樣本
k:用來分類判定的前K個距離的個數(shù)
"""
# 1. 計算待分類樣本sample與所有訓練集的距離
distances = [] # 存放sample到所有訓練集的距離
for s in train_data:
diff = s - sample
distance = np.sqrt(np.dot(diff, diff))
distances.append(distance)
# 2. 對距離排序(從小到大)佑颇,取前K個來統(tǒng)計分類(返回排序后的下標)
distances_np = np.array(distances) # 轉換為ndarray顶掉,利用其中的返回排序后的下標功能
sorted_index = distances_np.argsort()
# 3. 統(tǒng)計前K個距離對應訓練樣本的分類數(shù)量
categories = {} # 存放前k個距離的類別統(tǒng)計
for i in range(k):
# 取排序下標,在target標簽中得到類別
idx = sorted_index[i] # 取下標
category = train_label[idx] # 取列別
if category not in categories:
categories[category] = 0
categories[category] += 1
# 4. 分類數(shù)量最多的就是帶分類樣本的分類類別(返回類別下標)
# 對統(tǒng)計的類別 categories 進行排序漩符,其中最后一個就是最多的類別就是待分類樣本的類別一喘。
categories_sorted = sorted(categories.items(), key= lambda x: x[1], reverse=True) # 返回列表
return categories_sorted[0][0] # 第一個最大驱还,取第一個數(shù)據(jù)的第一個值:就是類別
# --- 數(shù)據(jù)加載與測試
# 數(shù)據(jù)加載
data, target = ds.load_iris(return_X_y=True)
# 使用第一個樣本來測試嗜暴,k=60
# data_train, data_test, target_train, target_test = train_test_split(
# data, # 數(shù)據(jù)集
# target, # 數(shù)據(jù)集標簽
# test_size=0.2)
ss = ShuffleSplit(n_splits=1, test_size=0.20)
result_split = ss.split(data)
for index_train, index_test in result_split:
data_test = data.take(index_test, axis=0)
data_train = data.take(index_train, axis=0)
target_test = target.take(index_test, axis=0)
target_train = target.take(index_train, axis=0)
correct_counter = 0
for d, t in zip(data_test, target_test):
c = knn(data_train, target_train, d, 17)
if c==t:
correct_counter += 1
print(F'訓練集與測試集不重疊- 識別正確:{correct_counter},測試樣本數(shù):{len(target_test)}')
correct_counter = 0
for d, t in zip(data_test, target_test):
c = knn_v(data, target, d, 7)
# print(c,t)
if c==t:
correct_counter += 1
print(F'訓練集與測試集重疊- 識別正確:{correct_counter}议蟆,測試樣本數(shù):{len(target_test)}')
# for d in data[100:150]:
# c = knn(data, target, d, 7)
# print(c)
訓練集與測試集不重疊- 識別正確:30闷沥,測試樣本數(shù):30
訓練集與測試集重疊- 識別正確:30,測試樣本數(shù):30
KNN的sklearn應用
from sklearn.neighbors import KNeighborsClassifier
import numpy as np
import sklearn.datasets as ds
from sklearn.model_selection import KFold, LeaveOneOut, LeavePOut, ShuffleSplit
from sklearn.model_selection import train_test_split
k_nn = KNeighborsClassifier(n_neighbors=7)
data, target = ds.load_iris(return_X_y=True)
# 使用第一個樣本來測試咐容,k=60
# data_train, data_test, target_train, target_test = train_test_split(
# data, # 數(shù)據(jù)集
# target, # 數(shù)據(jù)集標簽
# test_size=0.2)
ss = ShuffleSplit(n_splits=1, test_size=0.20)
result_split = ss.split(data)
for index_train, index_test in result_split:
data_test = data.take(index_test, axis=0)
data_train = data.take(index_train, axis=0)
target_test = target.take(index_test, axis=0)
target_train = target.take(index_train, axis=0)
k_nn.fit(data_train, target_train)
c = k_nn.predict(data_test)
print(c)
(c == target_test).sum()
[1 2 0 0 0 2 1 0 1 2 2 2 0 2 0 2 0 2 0 1 2 2 1 0 0 2 2 0 0 2]
29
KNN的手寫數(shù)字識別
- 代碼來自《機器學習實戰(zhàn)》一書的源代碼舆逃,并使用sklearn的KNeighborsClassifier類改寫。
import numpy as np
import operator
from os import listdir
from sklearn.neighbors import KNeighborsClassifier as kNN
'''
函數(shù)說明:將32*32的二進制圖片轉換為1*1024向量
Parameters:
filename - 文件名
Returns:
returnVect - 返回的二進制圖像的1*1024向量
'''
def img2vector(filename):
#創(chuàng)建1*1024的0向量
returnVect = np.zeros((1,1024))
fr = open(filename)
#按行讀取
for i in range(32):
#讀一行數(shù)據(jù)
lineStr=fr.readline()
#每一行的前32個數(shù)據(jù)依次添加到returnVect
for j in range(32):
returnVect[0,32*i+j]=int(lineStr[j])
return returnVect
'''
函數(shù)說明:手寫數(shù)字分類測試
Parameters:
filename - 無
Returns:
returnVect - 無
'''
def handwritingClassTest():
#測試集的labels
hwLabels=[]
#返回trainingDigits目錄下的文件名
trainingFileList=listdir('digits/trainingDigits')
#返回文件夾下文件的個數(shù)
m=len(trainingFileList)
#初始化訓練的Mat矩陣的測試集
trainingMat=np.zeros((m,1024))
#從文件名中解析出訓練集的類別
for i in range(m):
fileNameStr=trainingFileList[I]
classNumber = int(fileNameStr.split('_')[0])
#將獲取的類別添加到hwLabels中
hwLabels.append(classNumber)
#將每一個文件的1*1024數(shù)據(jù)存儲到trainingMat矩陣中
trainingMat[i,:]=img2vector('digits/trainingDigits/%s'%(fileNameStr))
#構建KNN分類器
neigh = kNN(n_neighbors=3,algorithm='auto')
#擬合模型,trainingMat為測試矩陣,hwLabels為對應的標簽
neigh.fit(trainingMat,hwLabels)
#返回testDigits目錄下的文件列表
testFileList=listdir('digits/testDigits')
errorCount=0.0
mTest=len(testFileList)
#從文件中解析出測試集的類別并進行分類測試
for i in range(mTest):
fileNameStr=testFileList[I]
classNumber=int(fileNameStr.split('_')[0])
#獲得測試集的1*1024向量用于訓練
vectorUnderTest=img2vector('digits/testDigits/%s'%(fileNameStr))
#獲得預測結果
classifierResult=neigh.predict(vectorUnderTest)
print ("分類返回結果%d\t真實結果%d"%(classifierResult,classNumber))
if (classNumber != classifierResult):
errorCount += 1.0
print ("總共錯了%d個\t錯誤率為%f%%"%(errorCount,errorCount/mTest*100))
handwritingClassTest()
分類返回結果0 真實結果0
分類返回結果0 真實結果0
分類返回結果0 真實結果0
分類返回結果0 真實結果0
......
分類返回結果9 真實結果9
分類返回結果9 真實結果9
總共錯了12個 錯誤率為1.268499%