1. 程式人生 > >KNN算法項目實戰——改進約會網站的配對效果

KNN算法項目實戰——改進約會網站的配對效果

san 計數 [1] 一行 畫出 下載 minus 就是 iter

KNN項目實戰——改進約會網站的配對效果 1、項目背景: 海倫女士一直使用在線約會網站尋找適合自己的約會對象。盡管約會網站會推薦不同的人選,但她並不是喜歡每一個人。經過一番總結,她發現自己交往過的人可以進行如下分類:
  • 不喜歡的人
  • 魅力一般的人
  • 極具魅力的人
2、項目數據 海倫收集約會數據已經有了一段時間,她把這些數據存放在文本文件datingTestSet.txt中,每個樣本數據占據一行,總共有1000行。 datingTestSet.txt數據集下載 海倫收集的樣本數據主要包含以下3種特征:
  • 每年獲得的飛行常客裏程數
  • 玩視頻遊戲所消耗時間百分比
  • 每周消費的冰淇淋公升數
數據格式如下: 技術分享圖片
3、K-近鄰算法的一般流程 (1)收集數據:提供文本文件。 (2)準備數據:使用Python解析文本文件。 (3)分析數據:使用Matplotlib畫二維擴散圖。 (4)測試算法:使用文本文件的部分數據作為測試樣本,計算錯誤率。 (5)使用算法:錯誤率在可接受範圍內,就可以運行k-近鄰算法進行分類。 4、項目步驟及代碼實現
  1 #-*- coding:utf-8 -*-
  2 
  3 import matplotlib.lines as mlines
  4 import matplotlib.pyplot as plt
  5 import numpy as np
6 import matplotlib as mpl 7 import operator 8 9 ‘‘‘ 10 #準備數據,從文本文件中解析數據 11 ‘‘‘ 12 def file2matrix(filename): 13 #打開文件 14 with open(filename,r) as fr: 15 # 讀取文件所有內容 16 arrayOLines = fr.readlines() 17 # 得到文件行數 18 numberOfLines = len(arrayOLines)
19 # 返回的NumPy矩陣,解析完成的數據:numberOfLines行,3列 20 returnMat = np.zeros((numberOfLines, 3)) 21 # 返回的分類標簽向量 22 classLabelVector = [] 23 # 行的索引值 24 index = 0 25 for line in arrayOLines: 26 # s.strip(rm),當rm空時,默認刪除空白符(包括‘\n‘,‘\r‘,‘\t‘,‘ ‘) 27 line = line.strip() 28 # 使用s.split(str="",num=string,cout(str))將字符串根據‘\t‘分隔符進行切片。 29 listFromLine = line.split(\t) 30 # 將數據前三列提取出來,存放到returnMat的NumPy矩陣中,也就是特征矩陣 31 returnMat[index, :] = listFromLine[0:3] 32 # 根據文本中標記的喜歡的程度進行分類,1代表不喜歡,2代表魅力一般,3代表極具魅力 33 if listFromLine[-1] == didntLike: 34 classLabelVector.append(1) 35 elif listFromLine[-1] == smallDoses: 36 classLabelVector.append(2) 37 elif listFromLine[-1] == largeDoses: 38 classLabelVector.append(3) 39 index += 1 40 return returnMat, classLabelVector 41 42 43 44 ‘‘‘ 45 #分析數據,數據可視化,使用Matplotlib創建散點圖 46 ‘‘‘ 47 def showdatas(datingDataMat, datingLabels): 48 #設置漢字格式 49 # sans-serif就是無襯線字體,是一種通用字體族。 50 # 常見的無襯線字體有 Trebuchet MS, Tahoma, Verdana, Arial, Helvetica, 中文的幼圓、隸書等等 51 mpl.rcParams[font.sans-serif] = [SimHei] # 指定默認字體 SimHei為黑體 52 mpl.rcParams[axes.unicode_minus] = False # 用來正常顯示負號 53 #將fig畫布分隔成2行2列,不共享x軸和y軸,fig畫布的大小為(13,8) 54 #當nrow=2,nclos=2時,代表fig畫布被分為四個區域,axs[0][0]表示第一行第一個區域 55 fig, axs = plt.subplots(nrows=2, ncols=2,sharex=False, sharey=False, figsize=(13,9)) 56 57 LabelsColors = [] 58 for i in datingLabels: 59 if i == 1: 60 LabelsColors.append(black) 61 if i == 2: 62 LabelsColors.append(orange) 63 if i == 3: 64 LabelsColors.append(red) 65 66 #畫出散點圖,以datingDataMat矩陣的第一(飛行常客例程)、第二列(玩遊戲)數據畫散點數據,散點大小為15,透明度為0.5 67 axs[0][0].scatter(x=datingDataMat[:,0], y=datingDataMat[:,1], color=LabelsColors,s=15, alpha=.5) 68 #設置標題,x軸label,y軸label 69 axs0_title_text = axs[0][0].set_title(每年獲得的飛行常客裏程數與玩視頻遊戲所消耗時間占比) 70 axs0_xlabel_text = axs[0][0].set_xlabel(每年獲得的飛行常客裏程數) 71 axs0_ylabel_text = axs[0][0].set_ylabel(玩視頻遊戲所消耗時間占) 72 plt.setp(axs0_title_text, size=12, weight=bold, color=red) 73 plt.setp(axs0_xlabel_text, size=10, weight=bold, color=black) 74 plt.setp(axs0_ylabel_text, size=10, weight=bold, color=black) 75 76 #畫出散點圖,以datingDataMat矩陣的第一(飛行常客例程)、第三列(冰激淩)數據畫散點數據,散點大小為15,透明度為0.5 77 axs[0][1].scatter(x=datingDataMat[:,0], y=datingDataMat[:,2], color=LabelsColors,s=15, alpha=.5) 78 #設置標題,x軸label,y軸label 79 axs1_title_text = axs[0][1].set_title(每年獲得的飛行常客裏程數與每周消費的冰激淋公升數,) 80 axs1_xlabel_text = axs[0][1].set_xlabel(每年獲得的飛行常客裏程數) 81 axs1_ylabel_text = axs[0][1].set_ylabel(每周消費的冰激淋公升數) 82 plt.setp(axs1_title_text, size=12, weight=bold, color=red) 83 plt.setp(axs1_xlabel_text, size=10, weight=bold, color=black) 84 plt.setp(axs1_ylabel_text, size=10, weight=bold, color=black) 85 86 #畫出散點圖,以datingDataMat矩陣的第二(玩遊戲)、第三列(冰激淩)數據畫散點數據,散點大小為15,透明度為0.5 87 axs[1][0].scatter(x=datingDataMat[:,1], y=datingDataMat[:,2], color=LabelsColors,s=15, alpha=.5) 88 #設置標題,x軸label,y軸label 89 axs2_title_text = axs[1][0].set_title(玩視頻遊戲所消耗時間占比與每周消費的冰激淋公升數) 90 axs2_xlabel_text = axs[1][0].set_xlabel(玩視頻遊戲所消耗時間占比) 91 axs2_ylabel_text = axs[1][0].set_ylabel(每周消費的冰激淋公升數) 92 plt.setp(axs2_title_text, size=12, weight=bold, color=red) 93 plt.setp(axs2_xlabel_text, size=10, weight=bold, color=black) 94 plt.setp(axs2_ylabel_text, size=10, weight=bold, color=black) 95 96 #設置圖例 97 didntLike = mlines.Line2D([], [], color=black, marker=., markersize=6, label=不喜歡) 98 smallDoses = mlines.Line2D([], [], color=orange, marker=.,markersize=6, label=魅力一般) 99 largeDoses = mlines.Line2D([], [], color=red, marker=.,markersize=6, label=極具魅力) 100 #添加圖例 101 axs[0][0].legend(handles=[didntLike,smallDoses,largeDoses]) 102 axs[0][1].legend(handles=[didntLike,smallDoses,largeDoses]) 103 axs[1][0].legend(handles=[didntLike,smallDoses,largeDoses]) 104 #顯示圖片 105 plt.show() 106 107 108 109 ‘‘‘ 110 #準備數據,數據歸一化處理 111 ‘‘‘ 112 def autoNorm(dataSet): 113 #獲得每列數據的最小值和最大值 114 minVals = dataSet.min(0) 115 maxVals = dataSet.max(0) 116 #最大值和最小值的範圍 117 ranges = maxVals - minVals 118 #shape(dataSet)返回dataSet的矩陣行列數 119 #normDataSet = np.zeros(np.shape(dataSet)) 120 #返回dataSet的行數 121 m = dataSet.shape[0] 122 #原始值減去最小值 123 normDataSet = dataSet - np.tile(minVals, (m, 1)) 124 #除以最大和最小值的差,得到歸一化數據 125 normDataSet = normDataSet / np.tile(ranges, (m, 1)) 126 #返回歸一化數據結果,數據範圍,最小值 127 return normDataSet, ranges, minVals 128 129 130 131 ‘‘‘ 132 KNN算法分類器 133 # inX - 用於分類的數據(測試集) 134 # dataSet - 用於訓練的數據(訓練集) 135 # labes - 訓練數據的分類標簽 136 # k - kNN算法參數,選擇距離最小的k個點 137 # sortedClassCount[0][0] - 分類結果 138 ‘‘‘ 139 def classify0(inX, dataSet, labels, k): 140 #numpy函數shape[0]返回dataSet的行數 141 dataSetSize = dataSet.shape[0] 142 #在列向量方向上重復inX共1次(橫向),行向量方向上重復inX共dataSetSize次(縱向) 143 diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet 144 #二維特征相減後平方 145 sqDiffMat = diffMat**2 146 #sum()所有元素相加,sum(0)列相加,sum(1)行相加 147 sqDistances = sqDiffMat.sum(axis=1) 148 #開方,計算出距離 149 distances = sqDistances**0.5 150 #返回distances中元素從小到大排序後的索引值 151 sortedDistIndices = distances.argsort() 152 #定一個記錄類別次數的字典 153 classCount = {} 154 for i in range(k): 155 #取出前k個元素的類別 156 voteIlabel = labels[sortedDistIndices[i]] 157 #dict.get(key,default=None),字典的get()方法,返回指定鍵的值,如果值不在字典中返回默認值。 158 #計算類別次數 159 classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 160 #python3中用items()替換python2中的iteritems() 161 #key=operator.itemgetter(1)根據字典的值進行排序 162 #key=operator.itemgetter(0)根據字典的鍵進行排序 163 #reverse降序排序字典 164 sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True) 165 #返回次數最多的類別,即所要分類的類別 166 return sortedClassCount[0][0] 167 168 169 170 ‘‘‘ 171 #測試算法,計算分類器的準確率,驗證分類器 172 ‘‘‘ 173 def datingClassTest(): 174 #打開的文件名 175 filename = "datingTestSet.txt" 176 #將返回的特征矩陣和分類向量分別存儲到datingDataMat和datingLabels中 177 datingDataMat, datingLabels = file2matrix(filename) 178 #取所有數據的百分之十 179 hoRatio = 0.10 180 #數據歸一化,返回歸一化後的矩陣,數據範圍,數據最小值 181 normMat, ranges, minVals = autoNorm(datingDataMat) 182 #獲得normMat的行數 183 m = normMat.shape[0] 184 #百分之十的測試數據的個數 185 numTestVecs = int(m * hoRatio) 186 #分類錯誤計數 187 errorCount = 0.0 188 189 for i in range(numTestVecs): 190 #前numTestVecs個數據作為測試集,後m-numTestVecs個數據作為訓練集 191 classifierResult = classify0(normMat[i,:], normMat[numTestVecs:m,:],datingLabels[numTestVecs:m], 4) 192 print("分類結果:%d\t真實類別:%d" % (classifierResult, datingLabels[i])) 193 if classifierResult != datingLabels[i]: 194 errorCount += 1.0 195 print("錯誤率:%f%%" %(errorCount/float(numTestVecs)*100)) 196 197 198 199 ‘‘‘ 200 #使用算法,構建完整可用系統 201 ‘‘‘ 202 def classifyPerson(): 203 #輸出結果 204 resultList = [不喜歡,有些喜歡,非常喜歡] 205 #三維特征用戶輸入 206 ffMiles = float(input("每年獲得的飛行常客裏程數:")) 207 precentTats = float(input("玩視頻遊戲所耗時間百分比:")) 208 iceCream = float(input("每周消費的冰激淋公升數:")) 209 #打開的文件名 210 filename = "datingTestSet.txt" 211 #打開並處理數 據 212 datingDataMat, datingLabels = file2matrix(filename) 213 #訓練集歸一化 214 normMat, ranges, minVals = autoNorm(datingDataMat) 215 #生成NumPy數組,測試集 216 inArr = np.array([ffMiles,precentTats, iceCream]) 217 #測試集歸一化 218 norminArr = (inArr - minVals) / ranges 219 #返回分類結果 220 classifierResult = classify0(norminArr, normMat, datingLabels, 3) 221 #打印結果 222 print("你可能%s這個人" % (resultList[classifierResult-1])) 223 224 225 226 ‘‘‘ 227 #主函數,測試以上各個步驟,並輸出各個步驟的結果 228 ‘‘‘ 229 if __name__ == __main__: 230 #打開的文件名 231 filename = "datingTestSet.txt" 232 #打開並處理數據 233 datingDataMat, datingLabels = file2matrix(filename) 234 #數據可視化 235 showdatas(datingDataMat, datingLabels) 236 #驗證分類器 237 datingClassTest() 238 #使用分類器 239 classifyPerson()

5、項目結果 (1)數據可視化結果 技術分享圖片 (2)驗證分類器計算錯誤率結果 技術分享圖片 (3)使用分類器根據輸入數據獲得預測結果 技術分享圖片

KNN算法項目實戰——改進約會網站的配對效果