机器学习笔记1(K-近邻算法)
人生苦短,我用Python
K-近鄰算法:簡單來說,K-近鄰算法就是采用測量不同特征值之間的距離方法進行分類
- 優點:精度高、對異常值不敏感、無數據輸入假定
- 缺點:計算復雜度高、空間復雜度高
- 適用范圍:數值型、標稱型
工作原理:
存在一個樣本數據集合,也稱作訓練樣本集,并且樣本集中每個數據都存在標簽,即我們知道樣本集中每一個數據與所屬分類的對應關系。輸入沒有標簽的新數據后,將新數據的每個特征與樣本集中數據對應的特征進行比較,然后算法提取樣本集中特征最相似的數據(最近鄰)的分類標簽。一般來說,我們只選擇樣本集中前K個最相似的數據,這就是K-近鄰算法中K的出處,通常K是不大于20的整數。最后,選擇K個最相似數據中出現次數最多的分類,作為新數據的分類。
K-近鄰算法的一般流程:
實施KNN分類算法--偽代碼
對未知類別屬性的數據集中的每個點依次執行以下操作:
計算兩個向量點之間的距離公式--歐式距離公式:
例如:點(0,0)與(1,2)之間的距離計算為:
sqrt((1-0)**2+(2-0)**2)
代碼實現:
import numpy as np import operator """ def CreateDataSet():group=np.array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]])labels=['A','A','B','B']return group,labels print(CreateDataSet()) """ """ inX--用于分類的輸入向量 dataSet--輸入的訓練樣本集 labels--標簽向量 k--用于選擇最近鄰居的數目 其中標簽向量的元素數目和矩陣dataSet的行數相同 """ def classify(inX,dataSet,labels,k):dataSetSize=dataSet.shape[0] #獲得訓練樣本集的行數#將輸入向量在列方向重復一次,在行方向上dataSize次,并與訓練樣本集dataSet相減diffMat=np.tile(inX,(dataSetSize,1))-dataSetprint("diffMat:")print(diffMat)#將相減后的集合進行平方運算sqDiffMat=diffMat**2print("sqDiffMat:")print(sqDiffMat)#對平方后的集合進行相加運算--按行相加sqDistances=sqDiffMat.sum(axis=1)print("sqDistances:")print(sqDistances)#對相加后的數據開平方,得到輸入向量與每個訓練樣本集之間的距離值distances=np.sqrt(sqDistances)print("distances")print(distances)#返回數組從小到大的索引值--排序sortedDistIndicies=np.argsort(distances)print("sortedDistIndicies")print(sortedDistIndicies)classCount={}for i in range(k):voteIlabel=labels[sortedDistIndicies[i]]print("voteIlabel"+str(i))print(voteIlabel)classCount[voteIlabel]=classCount.get(voteIlabel,0)+1print("classCount"+str(i))print(classCount)sortedClassCount=sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)print("sortedClassCount:")print(sortedClassCount)return sortedClassCount[0][0]if __name__=='__main__':#訓練樣本集group = np.array([[1.0, 1.1], [1.0, 1.0], [0, 0], [0, 0.1]])#標簽向量labels = ['A', 'A', 'B', 'B']#輸入向量inX=[0,0]#用于選擇最近鄰居的數目k=3result=classify(inX,group,labels,k)print(result)""" 輸出值: diffMat: [[-1. -1.1][-1. -1. ][ 0. 0. ][ 0. -0.1]] sqDiffMat: [[ 1. 1.21][ 1. 1. ][ 0. 0. ][ 0. 0.01]] sqDistances: [ 2.21 2. 0. 0.01] distances [ 1.48660687 1.41421356 0. 0.1 ] sortedDistIndicies [2 3 1 0] voteIlabel0 B classCount0 {'B': 1} voteIlabel1 B classCount1 {'B': 2} voteIlabel2 A classCount2 {'B': 2, 'A': 1} sortedClassCount: [('B', 2), ('A', 1)] BProcess finished with exit code 0 """復制代碼測試結果:
輸入[0,0],經過測試后,返回的結果是B,也就是說[0,0]這個輸入向量通過K-近鄰算法分類后歸為B類
示例:使用K-近鄰算法改進約會網站的配對效果
準備數據:從文本文件中解析數據
文本樣本數據特征:
- 每年獲得的飛行常客里程數
- 玩視頻游戲所耗時間的百分比
- 每周消費的冰淇淋公升數
將文本記錄轉換為numpy數據的解析程序:
def file2matrix(filename):# 打開文件fr = open(filename, 'r', encoding='utf-8')# 按行讀取數據arrayOLines = fr.readlines()# 獲取數據的行數numberOfLines = len(arrayOLines)# 創建以0填充的矩陣returnMat = np.zeros((numberOfLines, 3))print(returnMat)classLabelVector = []index = 0for line in arrayOLines:print(line)# 截取掉所有回車字符line = line.strip()print(line)# 以'\t'將line分割成一個元素列表listFromLine = line.split('\t')# 選取前三個元素,存儲到特征矩陣中returnMat[index, :] = listFromLine[0:3]# 選取最后一個元素存儲到標簽向量中classLabelVector.append(int(listFromLine[-1]))index += 1return returnMat, classLabelVector datingDataMat,datingLabels=file2matrix('D:\liuguojiang_Python\city_58\city_58\datingTestSet2.txt') fig=plt.figure() plt.title('K-') plt.xlabel('fly') plt.ylabel('consume') ax=fig.add_subplot(111)ax.scatter(datingDataMat[:,0],datingDataMat[:,1],15.0*np.array(datingLabels),15.0*np.array(datingLabels)) plt.show()復制代碼特別說明:代碼中的資源文件可以在此處下載:LiuGuoJiang/machinelearninginaction
解析文本數據并用散點圖展示:
準備數據:歸一化數值
任選樣本數據中一行數據,計算距離時,因為飛行常客里程數比較大,所以對最后計算結果影響過大,所以需要對數據做歸一化處理。如將取值范圍處理為0~1或者-1~1之間。下面的公式可以將任意取值范圍的特征值轉化為0~1區間內的值:
newValue=(oldValue-min)/(max-min)
- 其中min和max分別是數據集中的最小特征值和最大特征值。
歸一化特征值函數:
def autoNorm(dataSet):#選取列的最小值minVals=dataSet.min(0)#選取列的最大值maxVals=dataSet.max(0)#列的最大值與最小值做減法ranges=maxVals-minVals#normDataSet=np.zeros([dataSet.shape[0],dataSet.shape[1]])print(normDataSet)#取出dataSet的行數m=dataSet.shape[0]#np.tile(minVals,(m,1))將minVals在 列上重復一次,在行上重復m次normDataSet=dataSet-np.tile(minVals,(m,1)) #(oldValue-min)normDataSet=normDataSet/np.tile(ranges,(m,1)) #(oldValue-min)/(max-min)return normDataSet,ranges,minValsnormDataSet,ranges,minVals=autoNorm(datingDataMat) print(normDataSet)復制代碼測試算法:機器學習算法一個很重要的工作就是評估算法的正確率,通常我們只提供已有數據的90%作為訓練樣本來訓練分類器,而使用其余的10%數據去測試分類器,檢測分類器的正確率。10%數據應該是隨機選擇的。
分類器的測試代碼:
def datingClassUnitTest():hoRatio=0.10datingDataMat, datingLabels = file2matrix('D:\liuguojiang_Python\city_58\city_58\datingTestSet2.txt')print(datingDataMat)normDataSet, ranges, minVals = autoNorm(datingDataMat)print(normDataSet)m=normDataSet.shape[0]numTestVecs=int(m*hoRatio)print("numTestVecs")print(numTestVecs)errorCount=0.0for i in range(numTestVecs):classifierResult=classify(normDataSet[i,:],normDataSet[numTestVecs:m,:],datingLabels[numTestVecs:m],3)print("the classfier came back with:{},the real answer is:{}".format(classifierResult,datingLabels[i]))if (classifierResult!=datingLabels[i]):errorCount+=1.0print("the total error rate is:{}".format(errorCount/float(numTestVecs)))the classfier came back with:3,the real answer is:3 the classfier came back with:2,the real answer is:2 the classfier came back with:1,the real answer is:1 ......... the classfier came back with:1,the real answer is:1 the classfier came back with:3,the real answer is:3 the classfier came back with:3,the real answer is:3 the classfier came back with:2,the real answer is:2 the classfier came back with:1,the real answer is:1 the classfier came back with:3,the real answer is:1 the total error rate is:0.05復制代碼分類器處理數據集的錯誤率是5%,即代表此分類器可以幫助對象判定分類。
編寫可以讓用戶輸入自己需要判斷的輸入向量,通過該分類器幫助用戶判斷屬于哪一分類:
def classifyPerson():resultList = ['not at all', 'in small doses', 'in large doses']percentTats = float(input( \"percentage of time spent playing video games?"))ffMiles = float(input("frequent flier miles earned per year?"))iceCream = float(input("liters of ice cream consumed per year?"))datingDataMat, datingLabels = file2matrix('D:\liuguojiang_Python\city_58\city_58\datingTestSet2.txt')normDataSet, ranges, minVals = autoNorm(datingDataMat)inArr = np.array([ffMiles, percentTats, iceCream, ])classifierResult = classify((inArr - \minVals) / ranges, normDataSet, datingLabels, 3)print("You will probably like this person: {}".format(resultList[classifierResult - 1])) if __name__=='__main__':classifyPerson()""" return: percentage of time spent playing video games?10 frequent flier miles earned per year?10000 liters of ice cream consumed per year?0.5 You will probably like this person: in small doses """復制代碼總結:
總結
以上是生活随笔為你收集整理的机器学习笔记1(K-近邻算法)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java 域的隐藏_Windows Se
- 下一篇: Git客户端精简版Git-2.10.0-