keyword
文本分類算法、簡單的機器學習算法、基本要素、距離度量、類別判定、k取值、改進策略
摘要
kNN算法是著名的模式識別統計學方法,是最好的文本分類算法之一,在機器學習分類算法中占有相當大的地位,是最簡單的機器學習算法之一。
基本信息
外文名:k-Nearest Neighbor(簡稱kNN)
中文名:k最鄰近分類算法
應用:文本分類、模式識別、圖像及空間分類
典型:懶惰學習
訓練時間開銷:0
提出時間:1968年
作者:Cover和Hart提出
關鍵字:kNN算法、k近鄰算法、機器學習、文本分類
工作原理
思想:
官方:給定測試樣本,基於某種距離度量找出訓練集中與其最靠近的k個訓練樣本,然后基於這k個"鄰居"的信息來進行預測。
通俗點說:就是計算一個點與樣本空間所有點之間的距離,取出與該點最近的k個點,然后統計這k個點里面所屬分類比例最大的(“回歸”里面使用平均法),則點A屬於該分類。
k鄰近法實際上利用訓練數據集對特征向量空間進行划分,並作為其分類的“模型”。
三個基本要素:k值的選擇、距離度量、分類決策規則
圖例說明:

上圖中,綠色圓要被決定賦予哪個類,是紅色三角形還是藍色四方形?如果K=3,由於紅色三角形所占比例為2/3,綠色圓將被賦予紅色三角形那個類,如果K=5,由於藍色四方形比例為3/5,因此綠色圓被賦予藍色四方形類。
算法計算步驟
1、算距離: 給定測試對象,計算它與訓練集中的每個對象的距離;
2、找鄰居:圈定距離最近的k個訓練對象,作為測試對象的近鄰;
3、做分類:根據這k個近鄰歸屬的主要類別,來對測試對象分類;
距離的計算方式(相似性度量):
歐式距離:

曼哈頓距離:
類別的判定:
投票法:少數服從多數,近鄰中哪個類別的點最多就分為該類。
加權投票法:根據距離的遠近,對鄰近的投票進行加權,距離越近則權重越大(權重為距離平方的倒數)。
優、缺點
優點:
1、簡單,易於理解,易於實現,無需估計參數,無需訓練;
2、適合對稀有事件進行分類;
3、特別適合於多分類問題(multi-modal,對象具有多個類別標簽), kNN比SVM的表現要好。
缺點:
1、
樣本容量較小的類域采用這種算法比較容易產生誤分。
該算法在分類時有個主要的不足是,當樣本不平衡時,如一個類的樣本容量很大,而其他類樣本容量很小時,有可能導致當輸入一個新樣本時,該樣本的K個鄰居中大容量類的樣本占多數。 該算法只計算“最近的”鄰居樣本,某一類的樣本數量很大,那么或者這類樣本並不接近目標樣本,或者這類樣本很靠近目標樣本。無論怎樣,數量並不能影響運行結果。
2、該方法的另一個不足之處是
計算量較大,因為對每一個待分類的文本都要計算它到全體已知樣本的距離,才能求得它的K個最近鄰點。
3、可理解性差,無法給出像決策樹那樣的規則。
算法實例
流程:
1、計算距離
2、選擇距離最小的k個點
3、通過投票方式,選擇點最多的標簽。

#-*- coding:utf-8 -*- import numpy as np import operator def createDataset(): #四組二維特征 group = np.array([[5,115],[7,106],[56,11],[66,9]]) #四組對應標簽 labels = ('動作片','動作片','愛情片','愛情片') return group,labels """ KNN算法 """ def classify(intX, dataSet, labels, k): ''' numpy中shape[0]返回數組的行數,shape[1]返回列數 ''' dataSetSize = dataSet.shape[0] """ 將intX在橫向重復dataSetSize次,縱向重復1次 例如intX=([1,2])--->([[1,2],[1,2],[1,2],[1,2]])便於后面計算 """ diffMat = np.tile(intX, (dataSetSize, 1)) - dataSet """ 計算距離:歐式距離, 特征相減后乘方,然后再開方 """ sqdifMax = diffMat**2 seqDistances = sqdifMax.sum(axis=1) distances = seqDistances**0.5 #返回distance中元素從小到大排序后的索引 print ("distances:",distances) sortDistance = distances.argsort() print ("sortDistance:", sortDistance) """ 取出前k個元素的類別 """ classCount = {} for i in range(k): voteLabel = labels[sortDistance[i]] s = "第{}個voteLabel={}".format(i, voteLabel) print(s) classCount[voteLabel] = classCount.get(voteLabel,0)+1 #dict.get(key,default=None),字典的get()方法,返回指定鍵的值,如果值不在字典中返回默認值。 #計算類別次數 #key=operator.itemgetter(1)根據字典的值進行排序 #key=operator.itemgetter(0)根據字典的鍵進行排序 #reverse降序排序字典 sortedClassCount = sorted(classCount.items(), key = operator.itemgetter(1), reverse = True) #結果sortedClassCount = [('動作片', 2), ('愛情片', 1)] print ("sortedClassCount:") print(sortedClassCount) return sortedClassCount[0][0] if __name__ == '__main__': group,labels = createDataset() test = [20,101] test_class = classify(test,group,labels,3) print (test_class)
運行結果 :

改進策略
1、對樣本屬性進行約簡。——刪除對分類結果影響較小的屬性。
2、采用權值的方法(和該樣本距離小的鄰居權值大)來改進。——依照訓練集合中各種分類的樣本數量,選取不同數目的最近鄰居,來參與分類。
常見問題
1、k值設定
k值選擇過小,得到的近鄰數過少,會降低分類精度,同時也會放大噪聲數據的干擾;而如果k值選擇過大,並且待分類樣本屬於訓練集中包含數據數較少的類,那么在選擇k個近鄰的時候,實際上並不相似的數據亦被包含進來,造成噪聲增加而導致分類效果的降低。
如何選取恰當的K值也成為KNN的研究熱點。k值通常是采用交叉檢驗來確定(以k=1為基准)。
經驗規則:k一般低於訓練樣本數的平方根。
投票法沒有考慮近鄰的距離的遠近,距離更近的近鄰也許更應該決定最終的分類,所以加權投票法更恰當一些。
3、距離度量方式的選擇
高維度對距離衡量的影響:眾所周知當變量數越多,歐式距離的區分能力就越差。
變量值域對距離的影響:值域越大的變量常常會在距離計算中占據主導作用,因此應先對變量進行標准化。
4、訓練樣本的參考原則
學者們對於訓練樣本的選擇進行研究,以達到減少計算的目的,這些算法大致可分為兩類。第一類,減少訓練集的大小。KNN算法存儲的樣本數據,這些樣本數據包含了大量冗余數據,這些冗余的數據增了存儲的開銷和計算代價。縮小訓練樣本的方法有:在原有的樣本中刪掉一部分與分類相關不大的樣本樣本,將剩下的樣本作為新的訓練樣本;或在原來的訓練樣本集中選取一些代表樣本作為新的訓練樣本;或通過聚類,將聚類所產生的中心點作為新的訓練樣本
在訓練集中,有些樣本可能是更值得依賴的。可以給不同的樣本施加不同的權重,加強依賴樣本的權重,降低不可信賴樣本的影響。
5、性能問題
kNN是一種懶惰算法,而懶惰的后果:構造模型很簡單,但在對測試樣本分類地的系統開銷大,因為要掃描全部訓練樣本並計算距離。
已經有一些方法提高計算的效率,例如壓縮訓練樣本量等。
參考文獻
推薦
