《機器學習實戰》菜鳥學習筆記(二)kNN示例


目的:改進約會網站配對效果

數據樣本 下載地址 (百度網盤)

 讀取txt數據的代碼

 1 def file2matrix(filename):
 2     fr = open(filename)
 3     arrayOfLines = fr.readlines()
 4     numberOfLines = len(arrayOfLines)
 5     retMat = zeros((numberOfLines,3))
 6     classLabelVector = []
 7     index = 0
 8     for line in arrayOfLines:
 9         line = line.strip()
10         listFromLine = line.split('\t')
11         retMat[index,:] = listFromLine[0:3]#attention
12         classLabelVector.append(int(listFromLine[-1]))#why int
13         index += 1
14     return retMat,classLabelVector

這段代碼沒有什么好解釋的,注意一點 listFromLine[0:3] 表示的是0,1,2下標的值(不包含3)

matplotlib

    matplotlib可以認為是python下的MATLAB,集成了各種畫圖api。給個比較好的教程 點擊鏈接

    作圖代碼

 1 import kNN
 2 from numpy import * 
 3 import matplotlib
 4 import matplotlib.pyplot as plt
 5 
 6 group,labels = kNN.createDataSet()
 7 kNN.classify0([0,0],group,labels,3)
 8 datingDataMat,datingLabels = kNN.file2matrix('F:\Documents\Python Code\machinelearninginaction\Ch02\datingTestSet2.txt')
 9 fig = plt.figure()
10 ax = fig.add_subplot(1,1,1)
11 ax.scatter(datingDataMat[:,1],datingDataMat[:,2],
12     15.0*array(datingLabels),15.0*array(datingLabels))
13 plt.show()

這段代碼中需要注意的可能就只有幾點:

1. fig.add_subplot(1,1,1)表示作一個1*1的圖,其中激活第一個圖。

2. scatter() 函數,確定橫縱坐標,以及圖中點的大小以及顏色。 

結果如圖:

圖中的橫縱坐標分別表示 玩游戲所耗時間的百分比 以及 每周消費冰激凌公升數,但是我們從圖中很難獲取到有用的信息。下面我們再來用另外一維數據試試,也就是每年飛行里數這個特征,作圖如下(程序與上面那段代碼幾乎相同):

    怎么樣,效果立馬不一樣了吧。

    到此為止,可能認為這個問題已經搞定了,給定一個人,只需要看看離他最近的人的分類就可以啦。可是問題在於這個“近”是怎么判定的呢?上面我們用的是歐氏距離,這有木有問題呢?很不幸,有問題,其中一個最明顯的問題就是,算了,先看計算距離的公式吧。

    ((0-67)^2+(20000-32000)^2+(1.1-0.1)^2 )^0.5

發現了沒有啊,相對於第二項,第一項和第三項幾乎不起任何作用啊!

於是乎,怎么辦呢,歸一化!下面是歸一化的函數:

1 def autoNorm(dataSet):
2     minVals = dataSet.min(0)
3     maxVals = dataSet.max(0)
4     ranges = maxVals - minVals
5     normDataSet = zeors(shape(dataSet))
6     m = dataSet.shape[0]
7     normDataSet = dataSet - tile(minVals,(m,1))
8     normDataSet = normDataSet/tile(ranges,(m,1))
9     return normDataSet,ranges,minVals

歸一化是如何實現的呢?首先找到每一列的最小值和最大值,然后求出范圍。注意以上的操作都是基於array的,雖然表面看起來是一個數字,但實際上是數組。

這段程序實現的功能就是 (數組 - 數組中的最小值)/(最大值-最小值),於是乎,歸一化完成了。

然后測試該算法的准確性。使用隨機選取的90%的樣本訓練,10%的樣本檢測。代碼如下:

 1 def datingClassTest():
 2     hoRatio = 0.10
 3     datingDataMat,datingLabels = file2matrix('datingTestSet.txt')
 4     normMat,ranges,minVals = autoNorm(datingDataMat)
 5     m = normMat.shape[0]
 6     numTestVecs = int(m*hoRatio)
 7     errorCount = 0.0
 8     for i in range(numTestVecs):
 9         classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],\
10             datingLabels[numTestVecs:m],3)
11         print "the classifier came back with: %d, the real answer is: %d"\
12             % (classsifierresult, datingLabels[i])
13         if (classifierResult != datingLabels[i]):errorCount += 1.0
14     print "the total error rate is: %f" % (errorCount/float(numTestVecs))

這段代碼的作用就是檢測分類器效果的。

程序首先讀取數據,並進行歸一化的處理,接着調用了我們之前寫的 calssify0 這段分類程序,對normMat中的數據進行分類。

下面給出一段程序,這段程序用於輸入用戶的信息來預測海倫對他的喜歡程度

def classifyPerson():
    #定義喜歡程度
    resultList = ['not at all','in small doses','in large doses']
    #輸入玩游戲時間,飛行公里,和冰激凌消耗量
    percentTats = float(raw_input("percentage of time spent playing video games?"))
    ffMiles = float(raw_input("frequent flier miles earned per year"))
    iceCream = float(raw_input("liters of ice cream consumed per year"))
    #建立knn原始數據
    datingDataMat,datingLabels = file2matrix('datingTestSet2.txt')
    #特征歸一化
    normMat,ranges,minVals = autoNorm(datingDataMat)
    #將輸入量建成三個特征
    inArr = array([ffMiles,percentTats,iceCream])
    #最近鄰
    classifierResult = classify0((inArr-minVals)/ranges,normMat,datingLabels,3)
    #輸出結果
    print "You will probably like this person: ", resultList[classifierResult - 1]

怎么樣不難吧?

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM