機(jī)器學(xué)習(xí)、python
算法流程
對未知類別屬性的數(shù)據(jù)集中的每個(gè)點(diǎn)依次執(zhí)行以下操作:
step1:計(jì)算已知類別數(shù)據(jù)集中的點(diǎn)與當(dāng)前點(diǎn)之間的距離
step2:按照距離遞增持續(xù)排序
step3:選取與當(dāng)前點(diǎn)距離最小的k個(gè)點(diǎn)
step4:確定前k個(gè)端所在類別的出現(xiàn)頻率
step5:返回前k個(gè)點(diǎn)出現(xiàn)頻率最高的類別作為當(dāng)前點(diǎn)的預(yù)測分類
詳細(xì)講解
首先對這個(gè)算法舉個(gè)例子罐孝,一個(gè)樣本距離一個(gè)標(biāo)記點(diǎn)的距離在所有的標(biāo)記點(diǎn)中是最近的懦冰,我們當(dāng)然可以把這個(gè)樣本點(diǎn)和這個(gè)標(biāo)記點(diǎn)歸于一類塌碌,但是這個(gè)叫做最近鄰算法。k-近鄰算法的意思是找出這個(gè)樣本點(diǎn)距離所有標(biāo)記點(diǎn)的距離并進(jìn)行排序,選擇其中距離最短的k個(gè)數(shù)據(jù)蝠咆,根據(jù)出現(xiàn)的頻率進(jìn)行分類康聂。很明顯這樣的分類更具有正確性贰健。
下面放出一段利用kNN算法的代碼,具體的講解都在注釋里:
# -*- coding: UTF-8 -*-
import numpy as np
import operator
#構(gòu)造數(shù)據(jù)集
def createDataSet():
#四組二維數(shù)據(jù)
group = np.array([[1, 101],[5, 89],[108, 5],[115, 8]])
#特征標(biāo)簽
labels = ['愛情片','愛情片','動作片','動作片']
return group, labels
#kNN算法實(shí)現(xiàn)
def classify0(inX, dataSet, labels, k):
#numpy函數(shù)shape[0]返回dataSet的行數(shù)
dataSetSize = dataSet.shape[0]
#在列向量方向上重復(fù)inX共1次(橫向)恬汁,行向量方向上重復(fù)inX共dataSetSize次(縱向)
diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet
#二維特征相減后平方
sqDiffMat = diffMat**2
#sum()所有元素相加伶椿,sum(0)列相加,sum(1)行相加
sqDistances = sqDiffMat.sum(axis=1)
#開方氓侧,計(jì)算出距離
distances = sqDistances**0.5
#返回distances中元素從小到大排序后的索引值
sortedDistIndices = distances.argsort()
#定一個(gè)記錄類別次數(shù)的字典
classCount = {}
for i in range(k):
#取出前k個(gè)元素的類別
voteIlabel = labels[sortedDistIndices[i]]
#dict.get(key,default=None),字典的get()方法,返回指定鍵的值,如果值不在字典中返回默認(rèn)值脊另。
#計(jì)算類別次數(shù)
classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1
#python3中用items()替換python2中的iteritems()
#key=operator.itemgetter(1)根據(jù)字典的值進(jìn)行排序
#key=operator.itemgetter(0)根據(jù)字典的鍵進(jìn)行排序
#reverse降序排序字典
sortedClassCount = sorted(classCount.items(),key=operator.itemgetter(1),reverse=True)
#返回次數(shù)最多的類別,即所要分類的類別
return sortedClassCount[0][0]
if __name__ == '__main__':
#創(chuàng)建數(shù)據(jù)集
group, labels = createDataSet()
#打印數(shù)據(jù)集
print(group)
print(labels)
#測試集
test= [101, 20]
#kNN分類
test_class = classify0(test, group, labels, 3)
print(test_class)
我們從這里可以看出,k-近鄰算法沒有進(jìn)行數(shù)據(jù)的訓(xùn)練甘苍、沒有學(xué)習(xí)的過程尝蠕,只是直接武斷的將未知的數(shù)據(jù)根據(jù)特征并于已有的類型當(dāng)中。
k-近鄰算法實(shí)戰(zhàn)(約會網(wǎng)站配對效果判定)
基本功能
一名女士對自己交往的人進(jìn)行如下分類:不喜歡的人载庭、魅力一般的人看彼、極具魅力的人,然后根據(jù)他們的喜好選出了自己的指標(biāo)(特征):每年獲得的飛行城艟郏客里程數(shù)靖榕、玩視頻游戲所消耗時(shí)間百分比、每周消費(fèi)的冰淇淋公升數(shù).下面代碼就是先將數(shù)據(jù)文件從datingTestSet.txt里面導(dǎo)入顽铸,然后將數(shù)據(jù)格式更改為分類器可以接受的格式(特征矩陣和響應(yīng)的分類標(biāo)簽向量)
# -*- coding: UTF-8 -*-
import numpy as np
def file2matrix(filename):
fr= open(filename)
arrayOflines=fr.readlines()
numberOflines=len(arrayOflines)
returnMat = np.zeros((numberOflines, 3))
classLabelVector=[]
index=0
for line in arrayOflines:
# s.strip(rm)茁计,當(dāng)rm空時(shí),默認(rèn)刪除空白符(包括'\n','\r','\t',' ')
line = line.strip()
# 使用s.split(str="",num=string,cout(str))將字符串根據(jù)'\t'分隔符進(jìn)行切片。
listFromLine = line.split('\t')
returnMat[index, :] = listFromLine[0:3]
if listFromLine[-1] == 'didntLike':
classLabelVector.append(1)
elif listFromLine[-1] == 'smallDoses':
classLabelVector.append(2)
elif listFromLine[-1] == 'largeDoses':
classLabelVector.append(3)
index += 1
return returnMat, classLabelVector
if __name__ == '__main__':
#打開的文件名
filename = "datingTestSet.txt"
#打開并處理數(shù)據(jù)
datingDataMat, datingLabels = file2matrix(filename)
print(datingDataMat)
print(datingLabels)
輸出結(jié)果如下:
是不是根本不知道這些數(shù)據(jù)是干什么的谓松,是的星压,這就是我們?yōu)槭裁葱枰M(jìn)行圖像化處理的原因。
數(shù)據(jù)可視化
我們需要利用matplotlib庫進(jìn)行繪圖鬼譬,最后結(jié)果圖是這樣的:
圖像的完整代碼可以看我的github娜膘。
進(jìn)階思考
但是仔細(xì)思考一下,這樣利用歐氏距離將三個(gè)特征的差值平方和相加后优质,進(jìn)行樣本的分類是否可取呢竣贪?我認(rèn)為不是的军洼,比如一組數(shù)據(jù)中某個(gè)特征的差值比較大,這樣必然會影響整體的數(shù)據(jù)演怎,進(jìn)而影響分類匕争。從題干中我們也知道,這位女士是視她定的三個(gè)標(biāo)準(zhǔn)是同樣的爷耀,所以我們必須要對數(shù)據(jù)進(jìn)行處理甘桑。這也是我們在拿到數(shù)據(jù)后經(jīng)常做的事:數(shù)據(jù)歸一化。什么叫數(shù)據(jù)歸一化畏纲?意思就是消除諸如量綱扇住、大小等明顯會造成誤差的因素:
newValue = (oldValue - min) / (max - min)
這里我們將所有的數(shù)據(jù)(特征值)轉(zhuǎn)化為0到1區(qū)間內(nèi)的值。
調(diào)整后我們進(jìn)行檢測盗胀,一般的檢測方法就是在訓(xùn)練集中選擇10%-30%的數(shù)據(jù)作為檢驗(yàn)集艘蹋,剩下的作為學(xué)習(xí)集;這里我們選用10%作為測試票灰,得到的結(jié)果為: