四、 任務分析
每部電影的打斗鏡頭數、接吻鏡頭數以及電影類型。如圖1所示。
就是已有的數據集合,也稱訓練樣本集。數據集有兩個特征,打斗鏡頭數和接吻鏡頭數。也知道每部電影的類型,既分類標簽。根據經驗可以通過電影中打斗鏡頭數和接吻鏡頭數判斷出該電影屬於什么類型。但是在K-近鄰算法中不會告訴這些,會根據提取樣本集中特征最相似的數據分類標簽來判斷電影屬於愛情片還是動作片。
電影分類。如圖2所示
從散點圖可以判斷出該電影屬於動作片,因為距離已知的動作片更近。那么,K-近鄰算法怎么判斷呢,可以使用兩點距離公式計算距離。如圖3所示。
通過公式計算得知紅色圓點標記到動作片(108,5)的距離最近,通過算法直接得知電影類型,這個算法是最近鄰算法,而非k-近鄰算法。
| ♥ 知識鏈接 |
|
1、計算已知類別數據集中點與當前點的距離 2、按照距離遞增次序排序 3、選取與當前點距離最小的K個點 4、確定前K個點所屬類別出現頻率 5、返回當前K個點出現頻率最高的類別作為當前點的預測分類 |
五、 任務實施
步驟1、環境准備
右擊Ubuntu操作系統桌面,從彈出菜單中選擇【Open in Terminal】命令 打開終端。
通過【cd /home】切換到home目錄下。【ls】查看該目錄下的所有內容。如圖4所示。
【mkdir KNN】在home目錄下創建KNN文件夾。如圖5所示。
步驟2、數據集
數據可以使用Numpy進行創建。
【cd KNN】切換目錄,【vim kNN_movie.py】回車后創建並編輯名為kNN_movie的Python文件。如圖6所示。
回車后進入編輯框內,按鍵盤【i】進入編輯狀態,編譯如下程序。如圖7所示。
createDataSet()方法內通過np.array生成四組二維數據特征和四組特征標簽列表。在main方法內調用createDataSet()方法並將二維數據和特征標簽打印。
編輯完畢后,按【esc】退出編輯狀態,【:wq】保存並退出編輯框,【python kNN_movie.py】執行kNN_movie的Python文件。如圖8所示。
四組二維數據特征及特征標簽打印。
步驟3、k-近鄰算法
根據兩點距離公式,計算距離,選擇最小的前k個點,並返回分類結果。
再次進入kNN_movie.py文件編輯狀態,修改程序(需要導入運算符模塊【import operator】)。如圖9所示。
根據公式計算並排序對類別進行返回。
在main方法內定義測試數據集,並調用分類器的方法,將測試數據集、創建的數據集、分類標簽、k值當做參數並輸出最后的結果。如圖10所示。
編輯完畢后,按【esc】退出編輯狀態,【:wq】保存並退出編輯框,【python kNN_movie.py】執行kNN_movie的Python文件。如圖11所示。
得知該部電影的類型為動作片。
步驟4、源碼
1 #coding:utf-8 2 import numpy as np 3 import operator 4 from os import listdir 5 from sklearn.neighbors import KNeighborsClassifier as kNN 6 """ 7 將32x32的二進制圖像轉換為1x1024向量 8 """ 9 def img2vector(filename): 10 returnVect = np.zeros((1,1024)) #生成1x1024零向量 11 fr = open(filename) #打開文件 12 for i in range(32): #文本格式是32x32的,讀取所有行 13 lineStr = fr.readline() #讀一行數據 14 for j in range(32): #讀取行中所有元素 15 returnVect[0, 32*i+j] = int(lineStr[j]) #將所有的元素添加到returnVect中 16 return returnVect #返回轉換后的1x1024向量 17 """ 18 手寫數字分類測試 19 """ 20 def handwritingClassTest(): 21 hwLabels = [] #訓練集的Labels 22 trainingFileList = listdir('digits/trainingDigits') #返回trainingDigits目錄下的文件名 23 m = len(trainingFileList) #返回文件夾下文件的個數 24 trainingMat = np.zeros(((m,1024))) #初始化訓練的矩陣 25 for i in range(m): 26 fileNameStr = trainingFileList[i] #獲得文件的名字 27 classNumber = int(fileNameStr.split('_')[0]) #獲得分類的數字 28 hwLabels.append(classNumber) #將獲得的類別添加到hwLabels中 29 #將每一個文件的1x1024數據存儲到trainingMat矩陣中 30 trainingMat[i,:] = img2vector("digits/trainingDigits/%s" % (fileNameStr)) 31 neigh = kNN(n_neighbors=3,algorithm="auto") #構建kNN分類器 32 neigh.fit(trainingMat,hwLabels) #訓練模型 33 testFileList = listdir("digits/testDigits") #返回TestDigits目錄下的文件列表 34 errorCount = 0.0 #錯誤檢測計數 35 mTest = len(testFileList) #測試數據的數量 36 for i in range(mTest): #從文件中解析出測試集的類別並進行分類測試 37 fileNameStr = testFileList[i] #獲得文件名字 38 classNumber = int(fileNameStr.split("_")[0]) #獲得分類的數字 39 vectorUnderTest = img2vector("digits/testDigits/%s" % (fileNameStr)) #獲得測試集的1x1024向量,用於訓練 40 classifierResult = neigh.predict(vectorUnderTest) #獲取預測結果 41 print "分類返回結果為%d\t真實結果為%d" % (classifierResult,classNumber) 42 if (classifierResult != classNumber): 43 errorCount += 1.0 44 print "總共錯了%d個數據\n錯誤率為%f%%" % (errorCount,errorCount/mTest * 100) 45 if __name__ == '__main__': 46 handwritingClassTest()
