1. 程式人生 > >機器學習實戰---k近鄰演算法(程式碼及執行)

機器學習實戰---k近鄰演算法(程式碼及執行)

import numpy as np #匯入numpy import operator #運算子模組 #k-近鄰演算法 #計算距離 def classify0(inX,dataSet,labels,k): dataSetSize=dataSet.shape[0] #shape讀取資料矩陣第一維度的長度 diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet #tile重複陣列inX,有dataSet行 1個dataSet列,減法計算差值 sqDiffMat=diffMat**2 #**是冪運算的意思,這裡用的歐式距離 sqDisttances=sqDiffMat.sum(axis
=1) #普通sum預設引數為axis=0為普通相加,axis=1為一行的行向量相加 distances=sqDisttances**0.5 sortedDistIndicies=distances.argsort() #argsort返回數值從小到大的索引值(陣列索引0,1,2,3) #選擇距離最小的k個點 classCount={} for i in range(k): voteIlabel=labels[sortedDistIndicies[i]] #根據排序結果的索引值返回靠近的前k個標籤 classCount[voteIlabel]=classCount.get(voteIlabel,0
)+1 #各個標籤出現頻率 sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True) #排序頻率 #!!!!! classCount.iteritems()修改為classCount.items() #sorted(iterable, cmp=None, key=None, reverse=False) --> new sorted list。 # reverse預設升序 key關鍵字排序itemgetter(1)按照第一維度排序(0,1,2,3)
return sortedClassCount[0][0] #找出頻率最高的 #建立資料集 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 #import kn #group,labels=kn.createDataSet() def file2matrix(filename): fr=open(filename) arrayOLines=fr.readlines() numberOfLines=len(arrayOLines) #讀出資料行數 returnMat=np.zeros((numberOfLines,3)) #建立返回矩陣 classLabelVector=[] index=0 for line in arrayOLines: line=line.strip() #刪除空白符 listFromLine=line.split('\t') #split指定分隔符對資料切片 returnMat[index,:]=listFromLine[0:3] #選取前3個元素(特徵)儲存在返回矩陣中 classLabelVector.append(int(listFromLine[-1])) #-1索引表示最後一列元素,位label資訊儲存在classLabelVector index+=1 return returnMat,classLabelVector #datingDatMat,datingLabels=kn.file2matrix('datingTestSet2.txt') ##使用matplotlib建立散點圖 #import matplotlib #import matplotlib.pyplot as plt ##figure指定圖表名稱 #fig=plt.figure() ##在整張圖上加入一個子圖,111的意思是在一個1行1列的子圖中的第一張 #ax=fig.add_subplot(111) ##標明畫散點圖,plot為預設為華連線圖 #ax.scatter(datingDatMat[:,1],datingDatMat[:,2]) ##一定要加上這句話才能讓畫顯示在螢幕上 #plt.show #ax=fig.add_subplot(121) #ax.scatter(datingDatMat[:,1],datingDatMat[:,2],15.0*np.array(datingLabels),15.0*np.array(datingLabels)) #plt.show #ax=fig.add_subplot(131) ##第一二列屬性 #ax.scatter(datingDatMat[:,0],datingDatMat[:,1],15.0*np.array(datingLabels),15.0*np.array(datingLabels)) #plt.show #歸一化特徵值 #歸一化公式 :(當前值-最小值)/range def autoNorm(dataSet): minVals=dataSet.min(0) #存放每列最小值,引數0使得可以從列中選取最小值,而不是當前行 maxVals=dataSet.max(0) #存放每列最大值 ranges = maxVals - minVals normDataSet=np.zeros(np.shape(dataSet)) #初始化歸一化矩陣為讀取的dataSet m=dataSet.shape[0] #m儲存第一行 # 特徵矩陣是3x1000,min max range是1x3 因此採用tile將變數內容複製成輸入矩陣同大小 normDataSet=dataSet-np.tile(minVals,(m,1)) normDataSet=normDataSet/np.tile(ranges,(m,1)) return normDataSet, ranges, minVals #normMat,ranges,minVals=kn.autoNorm(datingDatMat) #測試約會網站分類結果程式碼 def datingClassTest(): hoRatio = 0.10 #hold out 10% datingDataMat,datingLabels = file2matrix('datingTestSet2.txt') #load data setfrom file normMat, ranges, minVals = autoNorm(datingDataMat) m = normMat.shape[0] numTestVecs = int(m*hoRatio) errorCount = 0.0 for i in range(numTestVecs): classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3) print("the classifier came back with: %d, the real answer is: %d" % (classifierResult, datingLabels[i])) if (classifierResult != datingLabels[i]): errorCount += 1.0 print("the total error rate is: %f" % (errorCount/float(numTestVecs))) #print(errorCount) #完整的約會網站預測:給定一個人,判斷時候適合約會 def classifyPerson(): resultList=['not at all','in small doses','in large doses'] percentTats=float(input("percentage of time spent playing video games?")) #書中raw_input在python3中修改為input() ffMiles=float(input("frequent flier miles earned per year?")) iceCream=float(input("liters of ice cream consumed per year?")) datingDataMat,datingLabels=file2matrix('datingTestSet2.txt')#原書沒有2 normMat, ranges, minVals = autoNorm(datingDataMat) inArr=np.array([ffMiles,percentTats,iceCream]) classifierResult=classify0((inArr-minVals)/ranges,normMat,datingLabels,3) print("You will probably like this person:", resultList[classifierResult-1]) #kn.classifyPerson() import os#, sys def img2vector(filename): returnVect=np.zeros((1,1024))#每個手寫識別為32x32大小的二進位制影象矩陣 轉換為1x1024 numpy向量陣列returnVect fr=open(filename)#開啟指定檔案 for i in range(32):#迴圈讀出前32行 lineStr=fr.readline() for j in range(32): returnVect[0,32*i+j]=int(lineStr[j])#將每行的32個字元值儲存在numpy陣列中 return returnVect #testvector=kn.img2vector('testDigits/0_13.txt') #測試演算法 def handwritingClassTest(): hwLabels=[] trainingFileList=os.listdir('trainingDigits')#修改 import os 這裡加上os. m=len(trainingFileList) trainingMat=np.zeros((m,1024)) #定義檔案數x每個向量的訓練集 for i in range(m): fileNameStr=trainingFileList[i] fileStr=fileNameStr.split('.')[0]#解析檔案 classNumStr=int(fileStr.split('_')[0])#解析檔名 hwLabels.append(classNumStr)#儲存類別 trainingMat[i,:]=img2vector('trainingDigits/%s'%fileNameStr) #訪問第i個檔案內的資料 #測試資料集 testFileList=os.listdir('testDigits') errorCount=0.0 mTest=len(testFileList) for i in range(mTest): fileNameStr=testFileList[i] fileStr=fileNameStr.split('.')[0] classNumStr=int(fileStr.split('_')[0])#從檔名中分離出數字作為基準 vectorUnderTest=img2vector('testDigits/%s'%fileNameStr)#訪問第i個檔案內的測試資料,不儲存類 直接測試 classifierResult=classify0(vectorUnderTest,trainingMat,hwLabels,3) print("the classifier came back with: %d,the real answer is: %d" %(classifierResult,classNumStr)) if(classifierResult!=classNumStr): errorCount+=1.0 print("\nthe total number of errors is: %d" % errorCount) print("\nthe total rate is:%f"% (errorCount/float(mTest))) #kn.handwritingClassTest()