K近鄰算法

概述

該算法採用測量不一樣特徵值之間的距離方法進行分類。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近鄰算法及其使用,該算法要求有接近實際數據的訓練樣本數據,同時,出了上面的缺點之外,該算法還有一個缺陷:沒法給出任何數據的基礎結構信息,所以咱們不能知曉平均實例樣本和典型樣本具備的特徵

 若有轉載本博文章,請註明出處。您的支持是個人動力!文章部份內容來自互聯網,本人不負任何法律責任。

相關文章
相關標籤/搜索