西普收集的約會數據在/home/soft/KNN/datingTestSet.txt。根據分析,每一個樣本數據佔據一行,總共1000行,樣本數據包含3中特徵:一、每一年得到的飛行常客里程數;二、玩視頻遊戲所消耗的時間百分比;三、每週消耗的冰淇淋公升數。didntLike表明不喜歡;smallDoses表明魅力通常;largeDoses表明極具魅力。python
♥ 知識連接 |
一、收集數據:網絡爬蟲、第三方提供的免費及收費數據 二、準備數據:使用Python解析、預處理數據 三、分析數據:對數據進行可視化 四、測試算法:計算錯誤率 五、使用算法:錯誤率在接受範圍內,運行算法進行分類 |
步驟一、環境準備算法
右擊Ubuntu操做系統桌面,從彈出菜單中選擇【Open in Terminal】命令 打開終端。vim
經過【cd /home】切換到home目錄下。【ls】查看該目錄下的全部內容。如圖1所示。數組
【mkdir KNN】在home目錄下建立KNN文件夾。如圖2所示。網絡
步驟二、數據解析app
【cd KNN】切換目錄,【cp /home/soft/KNN/datingTestSet.txt /home/KNN/】將數據集複製到該目錄下,【head -n 10 datingTestSet.txt】查看前十行的數據。如圖3所示。機器學習
樣本數據包含3中特徵:一、每一年得到的飛行常客里程數;二、玩視頻遊戲所消耗的時間百分比;三、每週消耗的冰淇淋公升數。didntLike表明不喜歡;smallDoses表明魅力通常;largeDoses表明極具魅力。學習
【vim kNN_date.py】回車後建立並編輯名爲kNN_date的Python文件。如圖4所示。測試
回車後進入編輯框內,按鍵盤【i】進入編輯狀態,編譯以下程序。如圖5所示。網站
對數據進行解析,將數據分類成兩部分,既特徵矩陣和對應的分類標籤。
在main方法內定義文件信息,調用處理數據的方法,將方法返回的特徵矩陣和分類標籤打印。如圖6所示。
編輯完畢後,按【esc】退出編輯狀態,【:wq】保存並退出編輯框,【python kNN_date.py】執行kNN_date的Python文件。如圖7所示。
步驟三、數據歸一化
約會網站樣本數據。如圖8所示。
想要計算樣本3和樣本4之間的距離,可使用歐拉公式計算。如圖9所示。
在計算中發現數字差值最大的屬性對計算結果的影響最大。在處理這種不一樣取值範圍的特徵值時,採用的方法是將數值歸一化。將取值範圍處理爲0到1或者-1到1之間。
公式爲:newValue = (oldValue - min) / (max - min)
再次進入kNN_date.py文件編輯狀態,修改程序。如圖10所示。
以數據矩陣爲參數根據公式求出數值歸一化的特徵矩陣、數據範圍、最小值。
在main內調用歸一化的方法,並將數據處理後獲得的數據矩陣做爲參數,輸出數值歸一化的特徵矩陣、數據範圍、最小值。如圖11所示。
編輯完畢後,按【esc】退出編輯狀態,【:wq】保存並退出編輯框,【python kNN_date.py】執行kNN_date的Python文件。如圖12所示。
控制檯分別打印歸一化後的特徵矩陣、數據範圍、最小值
步驟四、驗證分類器
機器學習算法最重要的工做就是評估算法的正確率,一般提供已有數據的90%做爲訓練樣原本訓練分類器,10%數據測試分類器。
再次進入kNN_date.py文件編輯狀態,修改程序。如圖13所示。
建立分類器(導入運算符模塊【import operator】)。
測試分類器,90%做爲訓練集,10%做爲測試集。如圖14所示。
在main內調用測試分類器的方法。如圖15所示。
編輯完畢後,按【esc】退出編輯狀態,【:wq】保存並退出編輯框,【python kNN_date.py】執行kNN_date的Python文件。如圖16所示。
根據結果得知錯誤率是3%。是一個在能夠接受的範圍之類。
步驟五、構建系統
給西普一個程序,經過該程序西普在約會網站找到並輸入某我的的信息。程序會判斷出對該男生的預測值。
再次進入kNN_date.py文件編輯狀態,修改程序。如圖17所示。
分別獲取玩視頻遊戲所佔的時間百分比、每一年得到飛行常客里程數、每週消費的冰淇淋公升數的值。對數據集進行處理,數據集歸一化,並生成測試集,對測試集歸一化,以後對數據進行分類。返回分類的結果。
在main方法內調用classifyPerson()方法。
編輯完畢後,按【esc】退出編輯狀態,【:wq】保存並退出編輯框,【python kNN_date.py】執行kNN_date的Python文件。如圖18所示。
分別輸入玩視頻遊戲所佔的時間百分比爲20、每一年得到飛行常客里程數爲52000、每週消費的冰淇淋公升數爲1。得知西普很是喜歡這我的。
步驟六、源碼
1 #coding:utf-8 2 import numpy as np 3 import operator 4 def file2matrix(filename): 5 fr = open(filename) #打開文件 6 arrayOLines = fr.readlines() #讀取文件全部內容 7 numberOfLines = len(arrayOLines) #獲得文件行數 8 returnMat = np.zeros((numberOfLines,3)) #生成numberOfLines行,3列數據 9 classLabelVector = [] #分類標籤向量 10 index = 0 #行的索引值 11 for line in arrayOLines: 12 line = line.strip() #默認刪除空白符 13 listFromLine = line.split('\t') #將字符串根據'\t'分隔符進行切片 14 returnMat[index,:] = listFromLine[0:3] #將數據前三列提取出來,存放到returnMat的Numpy矩陣 15 #根據文本中標記的喜歡的程度進行分類,1表明不喜歡,2表明魅力通常,3表明極具魅力 16 if listFromLine[-1] == 'didntLike': 17 classLabelVector.append(1) 18 elif listFromLine[-1] == 'smallDoses': 19 classLabelVector.append(2) 20 elif listFromLine[-1] == 'largeDoses': 21 classLabelVector.append(3) 22 index += 1 23 return returnMat,classLabelVector 24 """ 25 dataSet:特徵矩陣 26 """ 27 def autoNorm(dataSet): 28 #得到數據的最小、最大值 29 minVals = dataSet.min(0) 30 maxVals = dataSet.max(0) 31 #最大值和最小值的範圍 32 ranges = maxVals - minVals #最大值和最小值的範圍 33 normDataSet = np.zeros(np.shape(dataSet)) #生成與dataSet相同矩陣行列數 34 m = dataSet.shape[0] #返回dataSet的行數 35 normDataSet = dataSet - np.tile(minVals,(m,1)) #原始值減去最小值 36 normDataSet = normDataSet / np.tile(ranges,(m,1)) #除以最大和最小值的差,獲得歸一化數據 37 #返回歸一化數據結果,數據範圍,最小值 38 return normDataSet,ranges,minVals 39 """ 40 分類器 41 inX:測試集 42 dataSet:訓練集 43 label:分類標籤 44 k:距離最小的k個點 45 """ 46 def classify0(inX,dataSet,labels,k): 47 dataSetSize = dataSet.shape[0] #返回dataSet的行數 48 diffMat = np.tile(inX,(dataSetSize,1)) - dataSet #生成四組二維已知預測數據與樣本數據集相減 49 sqDiffMat = diffMat**2 #二維特徵相減後的平方 50 sqDistances = sqDiffMat.sum(axis=1) #sum()全部元素相加,sum(1)行相加 51 distances = sqDistances**0.5 #開方,計算出距離 52 sortedDistIndices = distances.argsort() #返回從小到大排序後的索引值 53 classCount = {} #記錄類別次數的字典 54 for i in range(k): 55 voteIlabel = labels[sortedDistIndices[i]] #取出前k個元素的類別 56 classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 #計算類別次數 57 #operator.itemgetter(1)根據字典的值進行排序 58 #reverse降序排序字典 59 sortedClassCount = sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True) 60 return sortedClassCount[0][0] #返回次數最多的類別,及索要分類的類別 61 """ 62 分類器測試 63 """ 64 def datingClassTest(): 65 filename = "datingTestSet.txt" #文件名 66 #將返回的特徵矩陣和分類向量分別存儲到datingdataMat和datingLabels中 67 datingDataMat, datingLabels = file2matrix(filename) 68 hoRatio = 0.10 #取全部數據的百分之十 69 #數據歸一化,返回歸一化的矩陣,數據範圍,數據最小值 70 normMat, ranges, minVals = autoNorm(datingDataMat) 71 m = normMat.shape[0] #得到normMat的行數 72 numTestVecs = int(m * hoRatio) #百分之十的測試數據的個數 73 errorCount = 0.0 #分類錯誤計數 74 for i in range(numTestVecs): 75 #前numTestVecs個數據做爲測試集,後m-numTestVecs個數據做爲訓練集 76 classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],4) 77 print "分類結果:%d\t真實類別:%d" %(classifierResult,datingLabels[i]) 78 if classifierResult != datingLabels[i]: 79 errorCount += 1.0 80 print "錯誤率:%f%%"%(errorCount/float(numTestVecs) * 100) 81 def classifyPerson(): 82 resultList = ['討厭','有些喜歡','很是喜歡'] #輸出結果 83 #三維特徵用戶輸入 84 precentTats = float(raw_input("玩視頻遊戲所耗時間百分比:")) 85 ffmiles = float(raw_input("每一年得到的飛行常客里程數:")) 86 iceCream = float(raw_input("每週消費的冰淇淋公升數:")) 87 filename = "datingTestSet.txt" #文件名 88 #打開並處理數據 89 datingDataMat,datingLabels = file2matrix(filename) 90 #訓練集歸一化 91 normMat,ranges,minVals = autoNorm(datingDataMat) 92 #生成Numpy數組,測試集 93 inArr = np.array([ffmiles,precentTats,iceCream]) 94 #測試集歸一化 95 norminArr = (inArr-minVals) / ranges 96 #返回分類結果 97 classifierResult = classify0(norminArr,normMat,datingLabels,3) 98 #打印結果 99 print "你可能%s這我的" % (resultList[classifierResult-1]) 100 if __name__ == '__main__': 101 classifyPerson()