1. 程式人生 > >k-近鄰演算法用於實際應用

k-近鄰演算法用於實際應用

摘要:

本章所有內容資料均來自《機器學習實戰》的資料,是對K近鄰演算法的應用以及熟練

例項1改進約會網站的配對效果

 題目描述:海倫喜歡在線上約會網站尋找適合自己的物件,但是她不是喜歡每一個人。她發現交往過三種類型的人:

  1.不喜歡的人

  2.魅力一般的人

  3.極具魅力的人

所以需要對網站的物件歸入恰當的分類。她週一到週五喜歡魅力一般的人,而週末則更喜歡極具魅力的人。所以需要根據資料來分類

準備資料:

  資料在文字datingTestSet.txt中,每個樣本佔據一行,總共1000行,每個樣本有3個特徵:

   每年獲得的飛行常客里程數

  玩視訊遊戲所消耗的時間

  每週消費的冰淇淋的公升

那麼這些資料從文字讀取後需要改寫成分類器可以接受的格式。輸出為樣本矩陣和類標籤向量

def file2matrix(filename):
	fr = open(filename)
	arrayOlines = fr.readlines()
	numberOfLines = len(arrayOlines)
	returnMat = zeros((numberOfLines,3))
	classLabelVector=[]
	index = 0
	for line in arrayOLines:
		line = line.strip()  #去回車
		listFromLine = line.split('\t')  #以\t分割
		returnMat[index,:] = listFromLine[0:3]
		classLabelVector.append(int(listFromLine[-1]))
		index+=1
	return returnMat,classLabelVector

其實python處理文字檔案很容易。

reload(kNN)

datingDataMat,datingLabels =  kNN.file2matrix('datingTestSet2.txt')

>>> datingDataMat
array([[  4.09200000e+04,   8.32697600e+00,   9.53952000e-01],
       [  1.44880000e+04,   7.15346900e+00,   1.67390400e+00],
       [  2.60520000e+04,   1.44187100e+00,   8.05124000e-01],
       ..., 
       [  2.65750000e+04,   1.06501020e+01,   8.66627000e-01],
       [  4.81110000e+04,   9.13452800e+00,   7.28045000e-01],
       [  4.37570000e+04,   7.88260100e+00,   1.33244600e+00]])

接下來需要分析資料,使用Matplotlib建立散點圖

>>> import matplotlib.pyplot as plt
>>> fig = plt.figure()
>>> ax = fig.add_subplot(111)
>>> ax.scatter(datingDataMat[:,1],datingDataMat[:,2]) #顏色以及尺寸標識了資料點屬性類別

散點圖使用datingDataMat矩陣的第二,第三列資料代表玩視訊遊戲所耗時間百分比,每週所消耗的冰淇凌公升數

由於沒有樣本分類的特徵值。很難看到任何有用的資料模型資訊。一般用採用色彩或其他記號標記不同分類

而展現的資料圖如下:


但是如果標識了三個不同的樣本分類區域,採用第1.2列效果會更直觀


對資料進行歸一化處理:

如果我們對資料樣本直接進行計算距離。(0-67)^2 + (20000-32000)^2 + (1.1-0.1)^2數字最大屬性對結果影響很大。

也就是說飛行常客對於結果的影響遠遠大於其他特徵。但是我們應該認為這3個屬性同等重要。所i有需要數值歸一化我們可以將任意值轉化到

0到1之間  newValue = (oldValue-min)/(max-min)

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

原來的資料為

array([[  4.09200000e+04,   8.32697600e+00,   9.53952000e-01],
       [  1.44880000e+04,   7.15346900e+00,   1.67390400e+00],
       [  2.60520000e+04,   1.44187100e+00,   8.05124000e-01],
       ..., 
       [  2.65750000e+04,   1.06501020e+01,   8.66627000e-01],
       [  4.81110000e+04,   9.13452800e+00,   7.28045000e-01],
       [  4.37570000e+04,   7.88260100e+00,   1.33244600e+00]])

進過處理後的資料為

array([[ 0.44832535,  0.39805139,  0.56233353],
       [ 0.15873259,  0.34195467,  0.98724416],
       [ 0.28542943,  0.06892523,  0.47449629],
       ..., 
       [ 0.29115949,  0.50910294,  0.51079493],
       [ 0.52711097,  0.43665451,  0.4290048 ],
       [ 0.47940793,  0.3768091 ,  0.78571804]])

測試演算法:使用完成程式測試分類

機器學習的重要工作就是評估演算法的正確率,通常按照上述的演算法如果正確分類,那麼可以使用這個軟體來處理約會網站提供的約會名單了。

但是還需要測試當前分類器的效能,我們以測試錯誤率為主對這個程式測試程式如下:

def datingClassTest():
	hoRation = 0.10
	datingDataMat,datingLabels = file2matrix('E:\pythonProject\ML\datingTestSet2.txt')
	normMat,ranges,minVals = autoNorm(datingDataMat)
	m = normMat.shape[0]
	numTestVecs = int(m*hoRation)
	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))

其實就是計算錯誤個數佔據總數的百分比,而最先給定的比率是測試集的個數

最後:進行泛化預測構造完整系統

上面已經對資料處理測試以及處理了,那麼下面就是隊資料進行預測

def classifyPerson():
	resultList = ['not at all','in small doses','in large doses']
	percentTats = float(raw_input("percentage of time spent playing?"))
	ffMiles = float(raw_input("frequent flier miles earned per year?"))
	iceCream = float(raw_input("liters of ice cream consume?"))
	datingDataMat,datingLabels = file2matrix('E:\pythonProject\ML\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]

根據型別輸出喜好的程度

>>> kNN.classifyPerson()
percentage of time spent playing?10
frequent flier miles earned per year?10000
liters of ice cream consume?0.
You will probably like this person: in small doses