一.算法原理
1.1 核心思想
kNN算法的核心思想是如果一個(gè)樣本在特征空間中的k個(gè)最相鄰的樣
本中的大多數(shù)屬于某一個(gè)類別,則該樣本也屬于這個(gè)類別,并具有
這個(gè)類別上樣本的特性。
一般來說,只選擇樣本數(shù)據(jù)集中前k個(gè)最相似的數(shù)據(jù),這就是k-近鄰
算法中k的出處,通常k是不大于20的整數(shù)。最后,選擇k個(gè)最相似數(shù)
據(jù)中出現(xiàn)次數(shù)最多的分類,作為新數(shù)據(jù)的分類。
距離度量常見有:歐氏距離(最常用)、曼哈頓距離、夾角余弦。
1.2 算法步驟
? 計(jì)算已知類別數(shù)據(jù)集中的點(diǎn)與當(dāng)前點(diǎn)之間的距離;
? 按照距離遞增次序排序;
? 選取與當(dāng)前點(diǎn)距離最小的k個(gè)點(diǎn);
? 確定前k個(gè)點(diǎn)所在類別的出現(xiàn)頻率;
? 返回前k個(gè)點(diǎn)所出現(xiàn)頻率最高的類別作為當(dāng)前點(diǎn)的預(yù)測分類。
案例一.k-近鄰算法代碼實(shí)現(xiàn)電影分類
創(chuàng)建數(shù)據(jù)集和標(biāo)簽,測試集;
dataset=np.array([[1,101],[5,89],[108,5],[115,8]])#四組二維特征
labels = ['愛情片','愛情片','動(dòng)作片','動(dòng)作片']
test_data = [101,20]#測試集
定義計(jì)算過程
import numpy as np
import collections
def classify(inx_test,dataset,labels,k):
dist = np.sum((inx_test-dataset)**2,axis=1)**0.5 #計(jì)算距離
k_labels = [labels[index] for index in dist.argsort()[0:k]] # 距離從小到大排列,取k個(gè)索引對應(yīng)k的個(gè)最近的標(biāo)簽
label = collections.Counter(k_labels).most_common(1)[0][0]
return label
輸入數(shù)據(jù)集,獲取測試集標(biāo)簽
#kNN分類
test_class0 = classify(test_data, dataset, labels, 3)
print(test_class0)
案例二.約會網(wǎng)站配對效果判定
2.1 案例背景
? 海倫女士一直使用在線約會網(wǎng)站尋找適合自己的約會對象。盡管約
會網(wǎng)站會推薦不同的人選,但她并不是喜歡每一個(gè)人。經(jīng)過一番總
結(jié),她發(fā)現(xiàn)自己交往過的人可以進(jìn)行如下分類:
? 不喜歡的人
? 魅力一般的人
? 極具魅力的人
? 海倫收集約會數(shù)據(jù)已經(jīng)有了一段時(shí)間,她把這些數(shù)據(jù)存放在文本文
件datingTestSet.txt中,每個(gè)樣本數(shù)據(jù)占據(jù)一行,總共有1000行。
海倫收集的樣本數(shù)據(jù)主要包含以下3種特征:
? 每年獲得的飛行常客里程數(shù)
? 玩視頻游戲所消耗時(shí)間百分比
? 每周消費(fèi)的冰淇淋公升數(shù)
2.1 數(shù)據(jù)預(yù)覽
數(shù)據(jù)讀取
import numpy as np
import pandas as pd
data = pd.read_csv('data\datingTestSet.txt',sep=' ',names=['x1','x2','x3','y'])
datingDataMat = data.loc[:,'x1':'x3']
datingLabels=data.loc[:,'y']
標(biāo)簽只有三種:{'didntLike', 'largeDoses', 'smallDoses'}
但三種特征值的量級不在一個(gè)級別,需要對三組特征值做數(shù)據(jù)歸一化處理。

數(shù)據(jù)歸一化處理。

上一個(gè)案例封裝的類,這里可以調(diào)用。
#計(jì)算錯(cuò)誤率
errorCount = 0.0
#前100作為測試,后900個(gè)作為訓(xùn)練
for i in range(100):
classifierResult = classify(df_norm.values[i,:], df_norm.values[100:1001,:],list(datingLabels[100:1001]), 4)
print("預(yù)測結(jié)果:%s\t真實(shí)類別:%s" % (classifierResult, datingLabels[i]))
if classifierResult is not datingLabels[i]:
errorCount += 1.0
print('錯(cuò)誤率:%f%%'%(errorCount/float(100)*100))

案例三.sklearn中的knn-鳶尾花分類
3.1 數(shù)據(jù)下載
import numpy as np
from sklearn import datasets
iris = datasets.load_iris()
##劃分?jǐn)?shù)據(jù)集特征、標(biāo)簽
iris_X = iris.data
iris_y = iris.target
使用scikit-learn處理劃分?jǐn)?shù)據(jù)集,并送入模型
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import train_test_split
##劃分?jǐn)?shù)據(jù)集
iris_train_X,iris_test_X,iris_train_y,iris_test_y = train_test_split(iris_X,iris_y,test_size=0.2,random_state=0)
knn = KNeighborsClassifier(n_neighbors=6)
knn.fit(iris_train_X,iris_train_y)
predict_result = knn.predict(iris_test_X)
print('結(jié)果預(yù)測為',predict_result)
##計(jì)算準(zhǔn)確率
acc_rate = knn.score(iris_test_X,iris_test_y)
print('預(yù)測準(zhǔn)確率為',acc_rate)
3.2 結(jié)果
