Machine Learning in Action 之 kNN
阿新 • • 發佈:2018-12-25
k臨近演算法(kNN)採用測量不同特徵值之間的距離方法進行分類,也是一種非常直觀的方法。本文主要記錄了使用kNN演算法改進約會網站的例子。 任務一:分類演算法classify0 就是使用距離公式計算特徵值之間的距離,選擇最鄰近的k個點,通過統計這k個點的結果來得出樣本的預測值。 def classify0 (inX,dataset,labels,k) : #shape 返回行列數,shape[0]是行數,有多少元組 datasetsize = dataset.shape[
>>> numpy.tile([ 0 , 0 ], 5 ) #在列方向上重複[0,0]5次,預設行1次 array([ 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 ]) >>> numpy.tile([ 0 , 0 ],( 1 , 1 )) #在列方向上重複[0,0]1次,行1次 array([[ 0 , 0 ]]) >>> numpy.tile([ 0 , 0 ],( 2 , 1 )) #在列方向上重複[0,0]1次,行2次 array([[ 0 , 0 ], [ 0 , 0 ]]) >>> numpy.tile([ 0 , 0 ],( 3 , 1 )) array([[ 0 , 0 ], [ 0 , 0 ], [ 0 , 0 ]]) 5、 argsort函式 任務二:讀入資料 注意這裡書上寫錯了,應該讀入的是datingTestSet2.txt而不是datingTestSet.txt def file2matrix (filename) : fr = open(filename) #開啟檔案,按行讀入 arrayOLines = fr.readlines() #獲得檔案行數 numberOfLines = len(arrayOLines) #建立m行n列的零矩陣 returnMat = zeros((numberOfLines, 3 )) classLabelVector = [] index = 0 for line in arrayOLines: line = line.strip() #刪除行前面的空格 listFromLine = line.split( '\t' ) #根據分隔符劃分 returnMat[index,:] = listFromLine[ 0 : 3 ] #取得每一行的內容存起來 classLabelVector.append(int(listFromLine[- 1 ])) index += 1 return returnMat,classLabelVector 任務三:使用Matplotlib畫圖 安裝Matplotlib時還需要numpy, dateutil, pytz, pyparsing, six, setuptools這幾個包。可以在 這裡 下載到,挺全的。加入到python27\Lib\site-packages目錄下。 在powershell中cd到datingTestSet2.txt所在資料夾 輸入python命令並且輸入以下命令 貼上: import numpy import matplotlib import matplotlib.pyplot as plt import k NN reload (k NN ) datingDataMat , datingLabels = kNN . file2matrix ('dating TestSet2 .txt') fig = plt . figure () ax = fig . add_subplot ( 111 ) ax . scatter (dating DataMat [:, 1 ],dating DataMat [:, 2 ], 15.0 *numpy. array (dating Labels ), 15.0 *numpy. array (dating Labels )) plt . show () 下面使用後兩個特徵的圖片 將scatter函式修改為: ax .scatter (datingDataMat[:, 0 ],datingDataMat[:, 1 ], 15.0 *numpy .array (datingLabels), 15.0 *numpy .array (datingLabels)) 1 使用前兩個特徵的圖片 任務四:歸一化 免除較大數值的資料給分類帶來的影響,將每一項資料歸一化為0~1之間的數字。 def autoNorm (dataSet) : #找出樣本集中的最小值 minVals = dataSet.min( 0 ) #找出樣本集中的最大值 maxVals = dataSet.max( 0 ) #最大最小值之間的差值 ranges = maxVals - minVals #建立與樣本集一樣大小的零矩陣 normDataSet = zeros(shape(dataSet)) m = dataSet.shape[ 0 ] #樣本集中的元素與最小值的差值 normDataSet = dataSet - tile(minVals, (m, 1 )) #資料相除,歸一化 normDataSet = normDataSet/tile(ranges, (m, 1 )) return normDataSet, ranges, minVals 任務五: 分類並檢驗書中所給的資料 def datingClassTest () : #選取多少資料測試分類器 hoRatio = 0.10 #從datingTestSet2.txt中獲取資料 datingDataMat,datingLabels = file2matrix( 'datingTestSet2.txt' ) #歸一化資料 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 出錯率為5% 任務六:將影象轉換為測試向量 任務七:測試識別手寫數字
def img2vector(filename): returnVect = zeros((1,1024)) fr = open(filename) for i in range(32): lineStr = fr.readline() for j in range(32): returnVect[0,32*i+j] = int(lineStr[j]) return returnVect def handwritingClassTest(): hwLabels = [] trainingFileList = listdir('trainingDigits') #load the training set m = len(trainingFileList) trainingMat = zeros((m,1024)) for i in range(m): fileNameStr = trainingFileList[i] fileStr = fileNameStr.split('.')[0] #take off .txt classNumStr = int(fileStr.split('_')[0]) hwLabels.append(classNumStr) trainingMat[i,:] = img2vector('trainingDigits/%s' % fileNameStr) testFileList = listdir('testDigits') #iterate through the test set errorCount = 0.0 mTest = len(testFileList) for i in range(mTest): fileNameStr = testFileList[i] fileStr = fileNameStr.split('.')[0] #take off .txt classNumStr = int(fileStr.split('_')[0]) vectorUnderTest = img2vector('testDigits/%s' % fileNameStr) 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 error rate is: %f" % (errorCount/float(mTest))