機器學習筆記(3)——K近鄰法

K-nearest neighbor(KNN)

k 近鄰法一種基本的分類與迴歸方法,原理和實現都比較直觀。其輸入爲樣本的特徵向量,輸出爲樣本的類別,可以進行多類別分類。k近鄰法是通過統計與未知樣本最近點的訓練樣本的類別來投票決定未知樣本的類別,不具有顯式的學習過程k 近鄰法主要包含有k 值選擇距離度量以及分類決策規則三部分。

1.k 近鄰模型

距離度量

特徵空間中兩個樣本的距離是兩個樣本的相似程度的反映。在k 近鄰法中常用的距離度量包括:
(1)Minkowski Distacne(閔可夫斯基距離)
定義兩個變量xi,xjχ,xi=(x1i,x2i,,xni) ,xj=(x1j,x2j,,xnj) ,則他們之間的閔可夫斯基距離爲:

Lp(xi,xj)=(l=1n(xlixlj))1p

p =1時,稱爲曼哈頓距離(Manhattan distance)
L1(xi,xj)=l=1n|xlixlj|

p =2時,是常用的歐式距離(Euclidean distance)
L2(xi,xj)=l=1n|xlixlj|2

p= 時,是常用的切比雪夫距離(chebyshev distance)
L(xi,xj)=maxl|xnixnj|

上述距離在不同特徵中存在一定的缺點,比如特徵維度中不同的單位,如果用絕對值會導致比重不一,因此不同的特徵都需要歸一化,即統一爲相對值。
(2)馬氏距離(Mahalanobis distance)
定義兩個變量xi,xjχ,xi=(x1i,x2i,,xni) ,xj=(x1j,x2j,,xnj) ,則他們之間的馬氏距離爲:
D(xi,xj)=(xiyj)TS1(xi,xj)

其中S 是協方差矩陣。馬氏距離與量綱無關,排除了變量之間相關性的干擾。在圖像處理領域中常用作特徵測量的標尺。
(3)夾角餘弦(Cosine)
夾角餘弦可以用來衡量兩個特徵向量方向的差異,機器學習中常用這一概念來衡量樣本的差異,對於給定變量,其定義爲:
cos(θ)=nl=1xlixljnl=1xni2nl=1xnj2

夾角餘弦越大表示兩個向量夾角越小,向量相似度越高。夾角餘弦度量的特徵距離常用在自然語言處理中,是很常用的機器學習特徵向量度量手段。
其餘衡量樣本相似度的手段還有漢明距離,傑卡德相似係數,相關係數和信息熵等。不同距離標準的選擇對於KNN最終的分類結果是可能不同的。
k 值選擇

k 值選擇會對KNN的結果產生重大影響。
如果選擇較小的k 值,相當於在較小的鄰域中進行預測,使“學習”的近似誤差減小,估計誤差增大,預測結果會對近鄰的樣本點非常敏感。這意味着,k 值越小整體模型會變得越複雜,模型容易過擬合。如果k 值較大,相當於在較大的鄰域中進行預測,可以減少“學習”的估計誤差,但是近似誤差增大。這意味着k 值越大,模型越簡單,適應性越強。
通常選取交叉驗證法來選取 k 值。

分類決策規則

在KNN中常用的分類決策規則往往是多數表決,即由距離測試樣本最近的k 個訓練樣本的類別決定分類結果。
分類函數:

f:Rn{c1,c2,,ck}

那麼誤分類的概率:
P(Yf(X))=1P(Y=f(x))

給定樣本xχ ,其最近鄰的k 個訓練樣本構成的集合Nk(x) . 如果最終的決策類別是cj , 那麼誤分類率爲:
1kxiNk(x)I(yicj)=11kxiNk(x)I(yi=cj)

要使誤分類率最小,即經驗風險最小,就要使xiNk(x)I(yi=cj) 最大,所以多數表決規則等效於經驗風險最小化。

2.k 近鄰算法

kNN 算法簡單、直觀:給定一個訓練樣本集,對新的輸入樣本,在訓練樣本中找k 個與該測試樣本最近鄰的k 個樣本,這k 個樣本多數屬於哪一類,則該測試樣本就屬於哪一類:

  • Algorithm 3.1
  • Input: traning_data T={(x1,y1),(x2,y2),,(xN,yN)} , testing_data (xi,yi)
  • Output: the label of yi
  • calculate all distances between testing_data and training_data
  • select the nearest k sample Nk(x)
  • voting rule: yi=argmaxxiNk(x)I(yi=cj)

    KNN算法的簡單實現

# Project: Machine Learning-KNN
# Author:Lyndon
# Date: 2015/10/18

from numpy import *
import operator

# Creating training data
def createdata():
    group = array([[1,1],[1,1.1],[0.9,1],[0,0.1],[0.1,0],[0.1,0.1],[0,1],[0.1,0.9],[0,0.8]])
    labels = ['A','A','A','B','B','B','C','C','C']
    return group,labels

# testing process
def knnclassify(testing_data,group,labels,k):
    datasize = group.shape[0]           #the rows of array
    # calculate the distance 
    diffMat = tile (testing_data,(datasize,1))-group
    sqdiffMat = diffMat**2
    sqdiffMatsum=sqdiffMat.sum(axis=1)
    distances = sqdiffMatsum**2
    # majority voting rule
    classcount={}
    sortdistances = distances.argsort()
    for i in range(k):
        votelabel = labels[sortdistances[i]]
        classcount[votelabel] = classcount.get(votelabel,0)+1
    sortclass=sorted(classcount.iteritems(),key=operator.itemgetter(1),reverse=True)
    return sortclass[0][0]

# main
if __name__ == "__main__":
    string=raw_input("please enter two numbers, split by comma:")
    input_data= string.split(",")
    testing_data= []
    for i in range(len(input_data)):
        testing_data.append(float(input_data[i]))
    string1=raw_input("please enter the k:")
    k=int(string1)
    group,labels = createdata()
    label=knnclassify(testing_data,group, labels, k)
    print "the label of input data is:" + str(label)

kNN 沒有顯式的學習過程,直接通過給定的訓練來預測未知樣本的結果,測試結果:
這裏寫圖片描述

kNN 是經典的數據分類算法,在郵件分類,文字識別,推薦系統等領域都有相應的應用,但其整體計算量大,特別對於高維數據會消耗很多資源,雖然KD樹能夠優化搜索的計算量,但計算大部分的數據還是消耗很大資源。
PS:本文爲機器學習(3)總結筆記,通過python實現了簡單分類,原理主要參考李航《統計學習理論》第三章。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章