《機器學習實戰》--KNN

代碼來自《機器學習實戰》https://github.com/wzy6642/Machine-Learning-in-Action-Python3git

K-近鄰算法(KNN)

介紹

簡單地說,k-近鄰算法採用測量不一樣特徵值之間的距離方法進行分類。github

優勢:精度高、對異常值不敏感,無數據輸入假定。算法

缺點:計算複雜度高、空間複雜度高,沒法給出數據的內在含義。app

使用數據範圍:數值型、標稱型。機器學習

分類函數的僞代碼:ide

  對未知類別屬性的數據集中的每一個點依次執行如下操做:函數

  (1)計算已知類別數據集中的點與當前點之間的距離;學習

  (2)按照距離遞增次序排序;測試

  (3)選取與當前點距離最小的k個點;spa

  (4)肯定前k個點所在類別的出現機率;

  (5)返回前k個點出現頻率最高的類別做爲當前點的預測分類。

 1 """建立數據集
 2 返回: group - 數據集
 3      labels - 分類標籤
 4 """
 5 def createDataSet():
 6     # 四組二維特徵
 7     group = np.array([[1, 101], [5, 89], [108, 5], [115, 8]])
 8     # 四組特徵的標籤
 9     labels = ['愛情片', '愛情片', '動做片', '動做片']
10     return group, labels
11 
12 
13 """
14 KNN算法,分類器
15 參數:
16     inX - 用於分類的數據(測試集)
17     dataSet - 用於訓練的數據(訓練集)(n*1維列向量)
18     labels - 分類標準(n*1維列向量)
19     k - KNN算法參數,選擇距離最小的k個點
20 返回:
21     sortedClasscount[0][0] - 分類結果
22 """
23 def classify0(inX, dataSet, labels, k):
24     # numpy函數shape[0]返回dataSet的行數(維度)
25     dataSetSize = dataSet.shape[0]
26     # 將inX重複dataSetSize次並排成一列
27     diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet
28     # 二維特徵相減後平方
29     sqDiffMat = diffMat**2
30     # sum()全部元素相加,sum(0)列相加,sum(1)行相加
31     sqDistances = sqDiffMat.sum(axis=1)
32     # 開方,計算出距離
33     distances = sqDistances**0.5
34     # argsort函數返回的是distances值從小到大的索引值
35     sortedDistIndicies = distances.argsort()
36     # 定義一個記錄類別次數的詞典
37     classCount = {}
38     # 選擇距離最小的k個點
39     for i in range(k):
40         # 取出前k個元素的類別
41         voteIlabel = labels[sortedDistIndicies[i]]
42         # 字典的get()方法,返回指定鍵的值,若是值不在字典中返回0
43         # 計算類別次數
44         classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
45     # reverse降序排序字典,operator.itemgetter(1)按值排序,(0)按鍵排序
46     sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
47     # 返回次數最多的類別,即所要分類的類別
48     return sortedClassCount[0][0]
49 
50 # 測試
51 group, labels = createDataSet()
52 classify0([0,0], group, labels, 3)  # output: '愛情片'
View Code 

實戰:手寫數字識別系統

這裏只能識別數字0到9,圖像爲32*32像素的黑白圖像,將圖像轉換爲文本格式。

將圖像格式化處理爲一個向量,把32*32的二進制圖像矩陣爲1*2014的向量。

 1 """
 2 將32*32的二進制圖像轉換爲1*1024向量
 3 參數:
 4     filename - 文件名
 5 返回:
 6     returnVect - 返回二進制圖像的1*1024向量
 7 """
 8 
 9 def img2vector(filename):
10     returnVect = np.zeros((1, 1024))
11     fr = open(filename)
12     # 按行讀取
13     for i in range(32):
14         # 讀取一行數據
15         lineStr = fr.readline()
16         # 每一行的前32個數據依次存儲到returnVect中
17         for j in range(32):
18             returnVect[0, 32*i+j] = int(lineStr[j])
19     # 返回轉換後的1*1024向量
20     return returnVect
21 
22 # 測試
23 testVector = img2vector('testDigits/0_13.txt')
24 testVector[0, 0:31]
25 # output: array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 1., 1., 1.,
26 #        1., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
View Code

測試算法

 1 """
 2 手寫數字分類測試
 3 參數:
 4     None
 5 返回:
 6     None
 7 """
 8 def handwritingClassTest():
 9     # 測試集的labels
10     hwLabels = []
11     # 返回trainingDigits目錄下的文件名
12     trainingFilesList = listdir('trainingDigits')
13     # 返回文件夾下文件的個數
14     m = len(trainingFilesList)
15     # 初始化訓練的Mat矩陣(全零針),測試集
16     trainingMat = np.zeros((m, 1024))
17     # 從文件名中解析出訓練集的類別
18     for i in range(m):
19         # 得到文件的名字
20         fileNameStr = trainingFilesList[i]
21         # 得到分類的數字
22         classNumber = int(fileNameStr.split('_')[0])
23         # 將得到的類別添加到hwLabels中
24         hwLabels.append(classNumber)
25         # 將每一個文件的1*1024數據存儲到trainingMat矩陣中
26         trainingMat[i, :] = img2vector('trainingDigits/%s' % (fileNameStr))
27     # 構造KNN分類器
28     neigh = KNN(n_neighbors=3, algorithm='auto')
29     # 擬合模型,trainingMat爲測試矩陣,hwLabels爲對應標籤
30     neigh.fit(trainingMat, hwLabels)
31     # 返回testDigits目錄下的文件列表
32     testFileList = listdir('testDigits')
33     # 錯誤檢測計數
34     errorCount =0.0
35     # 測試數據的數量
36     mTest = len(testFileList)
37     # 從文件中解析出測試集的類別並進行分類測試
38     for i in range(mTest):
39         # 得到文件名字
40         fileNameStr = testFileList[i]
41         # 得到分類的數字
42         classNumber = int(fileNameStr.split('_')[0])
43         # 得到測試集的1*1024向量,用於訓練
44         vectorUnderTest = img2vector('testDigits/%s' % (fileNameStr))
45         # 得到預測結果
46         classifierResult = neigh.predict(vectorUnderTest)
47         print("分類返回結果爲%d\t真實結果爲%d" % (classifierResult, classNumber))
48         if(classifierResult != classNumber):
49             errorCount += 1.0
50     print("總共錯了%d個數據\n錯誤率爲%f%%" % (errorCount, errorCount/mTest * 100))
相關文章
相關標籤/搜索