背景
監督學習中數據是有標籤的,比較入門。而在監督學習中,有分類和迴歸兩個任務。其中分類又是比較簡單的,那我們從分類入手,介紹第一個基礎分類算法——KNN。
簡介
KNN,全稱K-NearestNeighbor,也叫K近鄰。是監督學習中的一種基礎的常用分類算法。
所謂K近鄰,即選取k個最近的鄰居,來代表每個樣本。
說起來比較抽象,我們從圖上來看一下。
已分類數據:
圖中有兩個類別:紅色的三角形和藍色的正方形。他們的樣本數據散落在圖中。
待分類數據:
綠色圓圈,上面打着問號,也就是我們要將他分到兩個類別中。
好了,那麼我們現在要看綠色的圓圈到底分到哪個類別中。
首先解決k=?
1.當k=3時,即圖中邊框爲實線的圈中。包含了兩個三角形和一個正方形,所以此時綠色圓圈屬於三角形的分類。
2.當k=5時,即圖中邊框爲虛線的圈中,包含了兩個三角形和三個正方形,綠色圓圈屬於正方形的分類。(對!就是這麼簡單粗暴)
由上可見:
1.待分類元素的k個最近鄰居不包含其本身。
2.k近鄰算法中,k最好不要選擇偶數,以免出現鄰居中類別個數相同的情況。
3.k的選取十分關鍵,他幾乎主導着最終的分類結果。
其中,上面所說的“距離”,在KNN中常見的表現方式有:歐式距離、曼哈頓距離。
1.歐式距離
最常用、最簡單。(數學符號不好打,偷個懶,貼圖了)
2.曼哈頓距離
也叫城市街區距離,即|x1-x2|+|y1-y2|。
實例
Demo1:
直接給出座標軸中的幾個點和他們所屬類別,判斷新數據的類別。
from numpy import *
import operator
import matplotlib
import matplotlib.pyplot as plt
'''創建數據集和標籤'''
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
'''用歐式距離求k近鄰'''
def classfiy0(intX,dataSet,labels,k):
dataSetSize=dataSet.shape[0]
diffMat=tile(intX,(dataSetSize,1))-dataSet
sqDiffMat=diffMat**2
sqDistances=sqDiffMat.sum(axis=1)
distance=sqDistances**0.5
sortedDistIndicies=distance.argsort();#返回的是數組值從小到大的索引值
classCount={}
for i in range(k):
voteIlabel=labels[sortedDistIndicies[i]]
classCount[voteIlabel]=classCount.get(voteIlabel,0)+1
#排序
sortedClassCount=sorted(classCount.iteritems(),key=operator.itemgetter(1),reverse = True)
return sortedClassCount[0][0]
開始調用:
group,label=createDataSet()
print(classfiy0([0,0],group,label,3))
打印結果:
B
Tips:可以切換調用時的k取值,查看最終分類結果的變化。
Demo2:
根據收集處理好的文本文件使用,使用該算法,並繪製圖像。
對於下面要用到的datingTestSet2.txt,我們簡單看其中的幾條數據:
第一列:每年的飛行旅程數;
第二列:玩遊戲所耗時間佔比;
第三列:每週消費的冰淇淋公斤數;
第四列:所屬分類:不喜歡、一般、喜歡。
40920 8.326976 0.953952 3
14488 7.153469 1.673904 2
26052 1.441871 0.805124 1
75136 13.147394 0.428964 1
38344 1.669788 0.134296 1
72993 10.141740 1.032955 1
35948 6.830792 1.213192 3
42666 13.276369 0.543880 3
67497 8.631577 0.749278 1
35483 12.273169 1.508053 3
50242 3.723498 0.831917 1
63275 8.385879 1.669485 1
5569 4.875435 0.728658 2
51052 4.680098 0.625224 1
77372 15.299570 0.331351 1
整個分類的需求就比較清楚了,我們需要根據女主人公所記錄的以往約會對象以上三個指標和自己是否喜歡的判斷,設計好分類器。用來幫助女主人公在後面的約會中,只需要收集前面三個指標,就能推斷出相親對象的魅力程度。
#加載並解析數據
datingDataMat,datingLabels=file2matrix('file/datingTestSet2.txt')
print("開始繪製")
fig=plt.figure()
ax=fig.add_subplot(111)
#ax.scatter(datingDataMat[:,1],datingDataMat[:,2])
ax.scatter(datingDataMat[:,1],datingDataMat[:,2],15.0*array(datingLabels),15.0*array(datingLabels))
plt.show()
'''測試算法'''
def datingClassTest():
hoRatio=0.10
datingDataMat,datingLabels=file2matrix('file/datingTestSet2.txt')
normMat,ranges,minVals=autoNorm(datingDataMat)
m=normMat.shape[0]
numTestVecs=int(m*hoRatio)
errorCount=0.0
for i in range(numTestVecs):
classifierResult=classfiy0(normMat[i,:],normMat[numTestVecs:m,:],
datingLabels[numTestVecs:m],3)
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)))
散點圖:
步驟
KNN實驗可以分爲以下幾個步驟:
- 收集數據:提供文件。
- 準備數據:若不是分類器能直接使用的數據格式,則需要進行轉換,如圖像格式等。
- 分析數據:檢查數據,看是否符合要求。
- 訓練算法(該算法不涉及)
- 測試算法:編寫函數使用提供的部分數據集作爲測試樣本,如果預測分類與實際分類不符,則標記爲一個錯誤。
- 使用算法:本例未涉及。
小結
KNN算法簡單有效,易於理解。但他的缺點也十分突出。
- 計算中需保存全部數據集,佔用大量內存空間。
- k個鄰近距離,需要對每條距離進行計算,會十分耗時。
- 對於該算法給出的分類結果,我們無法知道正確與否。且依賴k值的選取。