學習到的第一個機器學習算法是“k-近鄰算法 (kNN) ”, 它的工作原理是:
存在一個樣本數據集合,也稱作訓練樣本集,并且樣本集中每個數據都存在標簽,即我們知道樣本集中每一數據與所屬分類的對應關系。輸人沒有標簽的新數據后,將新數據的每個特征與樣本集中數據對應的特征進行比較,然后算法提取樣本集中特征最相似數據(最近鄰)的分類標簽。一般來說,我們 只選擇樣本數據集中前k個最相似的數據,這就是k-近鄰算法中k的出處,通常k是不大于20的整數。 最后,選擇k個最相似數據中出現次數最多的分類,作為新數據的分類。
準備工作:建立訓練用樣本集group和其標簽集labels
import numpy as np
import operator
import sys
reload(sys)
sys.setdefaultencoding('utf8')
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
kNN算法實現函數:
def classify0(inX,dataSet,labels,k):
dataSetSize=dataSet.shape[0]#查看訓練集有多少行,即有多少個實例。
diffMat=np.tile(inX,(dataSetSize,1))-dataSet
#將測試數據也重復擴大成訓練集一樣的形式
#tile函數詳細:http://blog.csdn.net/april_newnew/article/details/44176059
sqDiffMat=diffMat**2#平方運算
sqDistances=sqDiffMat.sum(axis=1)
distances=sqDistances**0.5#開根運算
sortedDistIndicies=distances.argsort()#argsort返回升序排序后的索引值。
#關于argsort詳細:http://blog.csdn.net/maoersong/article/details/21875705
classCount={}
for i in range(k):
voteIlabel=labels[sortedDistIndicies[i]]#將標簽向量按排序索引存儲于voteIlabel中
classCount[voteIlabel]=classCount.get(voteIlabel,0)+1#對前k個點所在類別進行出現次數統計。
#關于get函數:http://www.runoob.com/python/att-dictionary-get.html
sortedClassCount=sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse=True)
#iteritems()迭代輸出字典的鍵值對,與item()類似,用法iter = dict.iteritems() iter.next()
#itemgetter(1)表明按值排序,reverse=True表明降序排序。
函數的四個參數分別為:
inX:需要分類的測試數據。
dataSet:訓練樣本集
labels:訓練樣本集的標簽集
k:需要取的最相近距離的個數。
兩點間距離公式如下:
在約會網站數據上使用kNN算法
- 讀取文件
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() #移除每行首尾指定字符。參數為空則移除空白符(如/d,/r,/n等)
listFromLine=line.split('\t')
returnMat[index,:]=listFromLine[0:3]
classLabelVector.append(int(listFromLine[-1]))
index +=1
return returnMat,classLabelVector
datingDataMat,datingLabels=file2matrix('文件路徑')
- 準備數據:歸一化數值
歸一化公式:newValue = {oldValue-min)/(max-min)
def autoNorm(dataSet):#歸一化特征值函數
minVals=dataSet.min(0) #axis=0,求每列中的最小值
maxVals=dataSet.max(0)# 求每列中的最大值。詳細參考:http://blog.csdn.net/qq_18433441/article/details/54743271
ranges=maxVals-minVals
normDataSet=np.zeros(np.shape(dataSet))
m=dataSet.shape[0]#取dataSet的行數 詳細參考:http://blog.csdn.net/u010758410/article/details/71554224
normDataSet=dataSet-np.tile(minVals,(m,1))
normDataSet=normDataSet/np.tile(ranges,(m,1))
return normDataSet,ranges,minVals
normMat,ranges,minVals=autoNorm(datingDataMat)
3.測試算法:作為完整程序驗證分類器
def datingClassTest():#訓練測試
hoRatio=0.1 #測試數據集占總數據的比例。
datingDataMat,datingLabels=file2matrix('文件路徑') #讀取文件數據
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],5)
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 classifyPersion():
resultList=['not at all','in small doses','in large doses']
persenTats=float(raw_input("percentage of time spent playing video games?"))
ffMiles=float(raw_input("freguent flier miles earned per year?"))
iceCream=float(raw_input("liters of ice cream consumed per year?"))
datingDataMat,datingLabels=file2matrix('文件路徑')
normMat,ranges,minVals=autoNorm(datingDataMat)
inArr=np.array([ffMiles,persenTats,iceCream])
classifierResult=classify0((inArr-minVals)/ranges,normMat,datingLabels,3)
print "You will probably like this person:",resultList[classifierResult-1]
classifyPersion()
代碼里自己總結的一些小疑問。
shape[0]
函數中,shape[0]用于查看訓練樣本集有多少行,即有多少實例。tile函數
用np.tile函數將測試數據重復,擴大為和訓練數據集一樣的大小。用這個擴大后的測試數據集和訓練樣本集相減,即為diffMat。
關于tile函數的具體使用參考:http://blog.csdn.net/april_newnew/article/details/44176059**2運算
2為平方運算,0.5為開根運算.sum(axis=1)
axis=1表示按行相加。axis=0表示按列相加。argsort()
distances.argsort()返回升序排序后的索引值。
關于argsort()詳細用法參考:http://blog.csdn.net/maoersong/article/details/21875705get函數
classCount.get(voteIlabel,0)返回計數字典里voteIlabel這個類別的出現次數。即鍵voteIlabel對應的值。還沒被統計過,也就是不存在的話,返回默認值0
關于get函數的詳細用法參考:http://www.runoob.com/python/att-dictionary-get.htmlsorted函數
sorted函數為用于列表或者iterator的排序函數,其直接返回一個排序后的新數據,而不是對原數據進行操作。
四個參數:
classCount.iteritems() :teritems()迭代輸出字典的鍵值對,與item()類似
key=operator.itemgetter(1):itemgetter(1)表明按值排序,0表明按鍵排序。
reverse=True:表明降序排序
itemgetter詳細:http://blog.163.com/wjyydhs810@126/blog/static/162071754201411864324976/
排序詳解:https://www.douban.com/note/271284737/