k-近鄰算法采用測量不同特征值之間的距離方法(上面寫的公式)進行分類。
優點:精度高、對異常值不敏感、無數據輸入假定。
缺點:計算復雜度高、空間復雜度高。
原理:1.存在一個訓練樣本集,並且樣本集中每個數據都存在標簽,即我們知道樣本集中每一數據與所屬分類的對應關系。
2.輸入沒有標簽的新數據后,將新數據的每個特征與樣本集中數據對應的特征進行比較,然后算法提取樣本集中特征最相思數據(最近鄰)的分類標簽。
3.一般的,我們只選擇樣本數據集中前k個最相似的數據,通常k是不大於20的整數,最后選擇k個最相似數據中出現次數最多的分類,作為新數據的分類。
1 ''' 2 1、計算已知類別數據集中的點與當前點之間的距離 3 2、按照距離遞增次序排序 4 3、選取與當前點距離最小的k個點 5 4、確定前k個點所在類別的出現概率 6 5、返回前k個點出現頻率最高的類別作為當前點的預測分類 7 ''' 8 import numpy as np 9 import operator 10 11 #處理文本 12 def fileToMatrix(filename): 13 fr = open(filename) 14 arrayOLines = fr.readlines() 15 numberOfLines = len(arrayOLines) 16 returnMat = np.zeros((numberOfLines, 5)) 17 classLabelVector = [] 18 index = 0 19 for line in arrayOLines: 20 line = line.strip() 21 listFromLine = line.split(',') 22 returnMat[index,:] = listFromLine[0:5] 23 classLabelVector.append(listFromLine[-1]) 24 index += 1 25 return returnMat, classLabelVector 26 27 #功能:歸一化數據,避免某些數據的特征值過大 28 def autoNorm(dataSet): 29 minVals = dataSet.min(0)#取列值的最小值 30 maxVals = dataSet.max(0) 31 ranges = maxVals - minVals 32 normDataSet = np.zeros(np.shape(dataSet)) 33 m = dataSet.shape[0] 34 normDataSet = dataSet - np.tile(minVals, (m,1)) 35 normDataSet = normDataSet/np.tile(ranges, (m, 1))#特征值相除 36 return normDataSet, ranges, minVals 37 38 #功能:kNN核心算法 39 #intX - 輸入向量,dataSet - 輸入訓練樣本集,labels - 標簽向量 40 def classify(inX, dataSet, labels, k): 41 #歐式距離的計算 42 dataSize = dataSet.shape[0]#數據的行數 43 diffMat = np.tile(inX, (dataSize,1)) - dataSet#將輸入向量inX縱向重復dataSet的行數次 44 sqDiffMat = diffMat ** 2 45 sqDistances = sqDiffMat.sum(axis = 1)# 每行數據相加 46 distances = sqDistances ** 0.5#得到訓練樣本集每一點與當前點的距離 47 sortedDistIndicies = distances.argsort() 48 #選擇距離最小的k個點 49 classCount = {} 50 for i in range(k): 51 voteIlabel = labels[sortedDistIndicies[i]]#最近K個的距離對應的類別 52 classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1#類別分別出現的概率 53 sortedClassCount = sorted(classCount.items(), key = operator.itemgetter(1), reverse = True)#選擇發生頻率最高的元素標簽 54 return sortedClassCount[0][0] 55 56 #功能:#功能:十折交叉驗證 57 #思路:將數據集分成十份,輪流將其中9份做訓練1份做測試,10次結果的均值作為對算法精度的估計 58 #一般還要進行多次10倍交叉驗證 59 def dataClassTest(filename,k): 60 testRate = 0.1 61 datingDataMat, datingLabels = fileToMatrix(filename) 62 datingDataMat = datingDataMat[:,:k-1] 63 normMat, ranges, minVals = autoNorm(datingDataMat) 64 m = normMat.shape[0] 65 numTestVecs = int(m * testRate) 66 all = 0 67 for k in range(1,11): 68 t = normMat[0:numTestVecs] 69 p = datingLabels[0:numTestVecs] 70 for i in range(numTestVecs): 71 errorCount = 0 72 classifierResult = classify(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3) 73 if(classifierResult != datingLabels[i]): errorCount += 1.0 74 #----------將第幾折的數據拿出來,放回到normMat的前面 75 b = normMat[numTestVecs*(k-1):numTestVecs*k] 76 normMat[0:numTestVecs] = b 77 normMat[numTestVecs*(k-1):numTestVecs*k] = t 78 errorRate = errorCount/float(numTestVecs) 79 #----------將第幾折類別拿出來,放回到datingLabels的前面 80 c = datingLabels[numTestVecs*(k-1):numTestVecs*k] 81 datingLabels[0:numTestVecs] = c 82 datingLabels[numTestVecs*(k-1):numTestVecs*k] = p 83 errorRate = errorCount/float(numTestVecs) 84 all = all + errorRate 85 #------------------------------------------------------------------ 86 print("第%d折分類的錯誤率為%f" % (k,(errorCount/float(numTestVecs)))) 87 #獲得平均錯誤率 88 print("平均錯誤率為%f" % (all/10))
歡迎加郵箱一起討論機器學習~=v=934363224@qq.com