《機器學習實戰》學習筆記(一):k-近鄰演算法
阿新 • • 發佈:2018-12-16
k-近鄰演算法
原書中程式碼為python2中語法,python3的語法參考連結:https://blog.csdn.net/c406495762/article/details/75172850
給出k-近鄰演算法的完整程式碼(海倫相親程式)
import numpy as np import operator """ 函式說明:kNN演算法,分類器 Parameters: inX - 用於分類的資料(測試集) dataSet - 用於訓練的資料(訓練集) labes - 分類標籤 k - kNN演算法引數,選擇距離最小的k個點 Returns: sortedClassCount[0][0] - 分類結果 Modify: 2017-03-24 """ def classify0(inX, dataSet, labels, k): #numpy函式shape[0]返回dataSet的行數 dataSetSize = dataSet.shape[0] #在列向量方向上重複inX共1次(橫向),行向量方向上重複inX共dataSetSize次(縱向) diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet #二維特徵相減後平方 sqDiffMat = diffMat**2 #sum()所有元素相加,sum(0)列相加,sum(1)行相加 sqDistances = sqDiffMat.sum(axis=1) #開方,計算出距離 distances = sqDistances**0.5 #返回distances中元素從小到大排序後的索引值 sortedDistIndices = distances.argsort() #定一個記錄類別次數的字典 classCount = {} for i in range(k): #取出前k個元素的類別 voteIlabel = labels[sortedDistIndices[i]] #dict.get(key,default=None),字典的get()方法,返回指定鍵的值,如果值不在字典中返回預設值。 #計算類別次數 classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 #python3中用items()替換python2中的iteritems() #key=operator.itemgetter(1)根據字典的值進行排序 #key=operator.itemgetter(0)根據字典的鍵進行排序 #reverse降序排序字典 sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True) #返回次數最多的類別,即所要分類的類別 return sortedClassCount[0][0] """ 函式說明:開啟並解析檔案,對資料進行分類:1代表不喜歡,2代表魅力一般,3代表極具魅力 Parameters: filename - 檔名 Returns: returnMat - 特徵矩陣 classLabelVector - 分類Label向量 Modify: 2017-03-24 """ def file2matrix(filename): #開啟檔案 fr = open(filename) #讀取檔案所有內容 arrayOLines = fr.readlines() #得到檔案行數 numberOfLines = len(arrayOLines) #返回的NumPy矩陣,解析完成的資料:numberOfLines行,3列 returnMat = np.zeros((numberOfLines,3)) #返回的分類標籤向量 classLabelVector = [] #行的索引值 index = 0 for line in arrayOLines: #s.strip(rm),當rm空時,預設刪除空白符(包括'\n','\r','\t',' ') line = line.strip() #使用s.split(str="",num=string,cout(str))將字串根據'\t'分隔符進行切片。 listFromLine = line.split('\t') #將資料前三列提取出來,存放到returnMat的NumPy矩陣中,也就是特徵矩陣 returnMat[index,:] = listFromLine[0:3] #根據文字中標記的喜歡的程度進行分類,1代表不喜歡,2代表魅力一般,3代表極具魅力 if listFromLine[-1] == 'didntLike': classLabelVector.append(1) elif listFromLine[-1] == 'smallDoses': classLabelVector.append(2) elif listFromLine[-1] == 'largeDoses': classLabelVector.append(3) index += 1 return returnMat, classLabelVector """ 函式說明:對資料進行歸一化 Parameters: dataSet - 特徵矩陣 Returns: normDataSet - 歸一化後的特徵矩陣 ranges - 資料範圍 minVals - 資料最小值 Modify: 2017-03-24 """ def autoNorm(dataSet): #獲得資料的最小值 minVals = dataSet.min(0) maxVals = dataSet.max(0) #最大值和最小值的範圍 ranges = maxVals - minVals #shape(dataSet)返回dataSet的矩陣行列數 normDataSet = np.zeros(np.shape(dataSet)) #返回dataSet的行數 m = dataSet.shape[0] #原始值減去最小值 normDataSet = dataSet - np.tile(minVals, (m, 1)) #除以最大和最小值的差,得到歸一化資料 normDataSet = normDataSet / np.tile(ranges, (m, 1)) #返回歸一化資料結果,資料範圍,最小值 return normDataSet, ranges, minVals """ 函式說明:通過輸入一個人的三維特徵,進行分類輸出 Parameters: 無 Returns: 無 Modify: 2017-03-24 """ def classifyPerson(): #輸出結果 resultList = ['討厭','有些喜歡','非常喜歡'] #三維特徵使用者輸入 precentTats = float(input("玩視訊遊戲所耗時間百分比:")) ffMiles = float(input("每年獲得的飛行常客里程數:")) iceCream = float(input("每週消費的冰激淋公升數:")) #開啟的檔名 filename = "datingTestSet.txt" #開啟並處理資料 datingDataMat, datingLabels = file2matrix(filename) #訓練集歸一化 normMat, ranges, minVals = autoNorm(datingDataMat) #生成NumPy陣列,測試集 inArr = np.array([precentTats, ffMiles, iceCream]) #測試集歸一化 norminArr = (inArr - minVals) / ranges #返回分類結果 classifierResult = classify0(norminArr, normMat, datingLabels, 3) #列印結果 print("你可能%s這個人" % (resultList[classifierResult-1])) """ 函式說明:main函式 Parameters: 無 Returns: 無 Modify: 2017-03-24 """ if __name__ == '__main__': classifyPerson()