該算法採用測量不一樣特徵值之間的距離方法進行分類。python
優勢:精度高,對異常值不敏感,無數據輸入假定。算法
缺點:計算複雜度高,每次測試樣本中的一個數據都要和訓練樣本全部數據進行距離計算,因此耗費的時間長,效率不高。空間複雜都高,須要存儲大量數據,佔用大量存儲空間ide
使用數據範圍:數值型,標稱型(標稱型數據要轉化爲數字型)函數
工做原理:算法要求存在一個訓練樣本數據集合,每一個數據都有一個分類標籤。輸入測試數據後,將新輸入樣本每一個特徵值與訓練樣本特徵進行比較,提取出訓練樣本中特徵最類似數據的分類標籤,而k表示提取出的分類標籤數,能夠自定義,根據計算錯誤率選擇最優k值,最後在k個最類似數據中選擇出現次數最多的分類,最爲新數據的分類性能
算法通常流程測試
(1)收集數據:任何數據收集方法網站
(2)準備數據:將收集的數據整理爲符合算法要求的結構化的數據格式spa
(3)分析數據:任何方法code
(4)訓練算法:不適用與K近鄰算法orm
(5)測試算法:計算錯誤率
(6)使用算法:針對約會網站的數據分類,手寫數字識別
準備數據:使用python導入數據
from numpy import * import operator #標準函數操做 def createDataSet(): group = array([[1.0, 1.1], [1.0, 1.0], [0, 0], [0, 0.1]]) #矩陣,特徵值量化,兩個特徵值 labels = ['A', 'A', 'B', 'B'] # 列表,上述特徵值對應的分類標籤 return group, labels
我這裏是使用的python3.6版本,我的喜歡用較新版本。注意:訓練樣本特徵值以矩陣形式存儲,行向量表明一個樣本的特徵數據,列向量表明一個特徵的全部樣本值(切記)
實施K近鄰算法
def classify0(inx,dataSet,labels,k):# inx爲用於分類的輸入向量,dataSet爲訓練樣本集,labels爲標籤向量 dataSetSize=dataSet.shape[0] diffMat=tile(inx,(dataSetSize,1))-dataSet #tile()函數將inx進行dataSetSize行,1列重複輸出,最後減去dataSet訓練集對應的數據 sqDiffMat=diffMat**2 #矩陣中每一個數據點的平方 sqDistance=sqDiffMat.sum(axis=1) #axis=1表示計算矩陣每一行行向量的和 Distance=sqDistance**0.5 #行向量,轉化爲行向量 sortDistIndicies=Distance.argsort() #從小到大排序,返回排序後的數據點在原Distance中的索引 classCount={} for i in range(k): Votelabel=labels[sortDistIndicies[i]] classCount[Votelabel]=classCount.get(Votelabel,0)+1;#0爲默認值 print(classCount) sortClassCount=sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)#升序,sortClassCount爲列表 return sortClassCount[0][0]
算法返回了一個新輸入數據的分類結果,新數據與樣本的類似性在這裏用歐式距離公式衡量,即向量間的距離公式。爲了預測數據所在分類,可使用一下命令:
group,labels=createDataSet() print(classify0([0,0],group,labels,4))
分類器的性能(分類效果)受到多種因素的影響,如分類器設置,數據集等,爲了測試分類器的效果,咱們能夠用分類器給出的測試結果與真實結果進行比較,計算出錯誤率——錯誤次數除以總的測試執行次數。
數據來源連接:https://www.manning.com/books/machine-learning-in-action
要是咱們想看一下數據的分佈狀況,能夠用Matplotlib建立散點圖
import matplotlib fig=plt.figure() ax=fig.add_subplot(111) ax.scatter(datingDataMat[:,1],datingDataMat[:,2],20*array(datinglabels),15*array(datinglabels)) plt.show()
若是兩特徵值的數據大小相差很大時,咱們能夠用歸一化將特徵值轉化爲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)) #element wise divide return normDataSet, ranges, minVals#返回歸一化後的數據矩陣,每一個特徵值的變更大小,特徵值的最小值
def datingClassTest(): hoRatio=0.1 datingDataMat,datinglabels=file2matrix('datingTestSet.txt') normMat,rangs,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) if (classifierResult!=datinglabels[i]): errorCount+=1; print(errorCount/float(numTestVecs))#輸出錯誤率
經過下面的函數,用戶能夠輸入三個特徵值,程序會自動給出預測值
def classPerson(): resultList = ['not at all', 'in small doses', 'in large doses'] percentTats = float(input("percentage of time spent playing video games?")) ffMiles = float(input("frequent flier miles earned per year?")) iceCream = float(input("liters of ice cream consumed per year?")) datingDataMat, datinglabels = file2matrix('datingTestSet2.txt') normMat, rangs, minVals = autoNorm(datingDataMat) inArr=array([ffMiles,percentile,iceCream]) classifierResult=classify0((inArr-minVals)/rangs,normMat,datinglabels,3) print(resultList[classifierResult-1])
以上就是K近鄰算法及其使用,該算法要求有接近實際數據的訓練樣本數據,同時,出了上面的缺點之外,該算法還有一個缺陷:沒法給出任何數據的基礎結構信息,所以咱們不能知曉平均實例樣本和典型樣本具備的特徵
若有轉載本博文章,請註明出處。您的支持是個人動力!文章部份內容來自互聯網,本人不負任何法律責任。