KNN算法原理
计算测试样本与每个训练样本的距离,取前k个距离最小的训练样本,最后选择这k个样本中出现最多的分类,作为测试样本的分类。
如图所示,绿色的为测试样本,当k取3时,该样本就属于红色类;当k取5时,就属于蓝色类了。所以k值的选择很大程度影响着该算法的结果,通常k的取值不大于20。
实战-糖尿病预测
数据的下载与导入
本数据可以再kaggle中进行下载, 也可以在百度网盘链接中进行下载
(链接:https://pan.baidu.com/s/1gqaGuQ9kWZFfc-SXbYFDkA 密码:lxfx)
该数据为csv格式文件,我们通过pandas读入:
import numpy as npimport pandas as pddata = pd.read_csv('./diabetes.csv')data.head()

我们简单看下各字段的意思:
- Pregnancies:怀孕的次数
- Glucose:血浆葡萄糖浓度
- BloodPressure:舒张压
- SkinThickness:肱三头肌皮肤皱皱厚度
- Insulin: 胰岛素
- BMI:身体质量指数
- Dia….:糖尿病血统指数
- Age:年龄
- Outcone:是否糖尿病,1为是
划分数据集
在模型训练前, 需要将数据集切分为训练集和测试集(7,3开或者其它开), 这里选择28开,使用sklearn中的model_selection模块中的train_test_split方法.from sklearn.model_selection import train_test_splitX_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=0.2, random_state=22)print(X_train.shape)print(X_test.shape)print(Y_train.shape)print(Y_test.shape)
(614, 8) (154, 8) (614,) (154,)
使用不同的k邻近算法进行分类
:::success
sklearn.neighbors.KNeighborsClassifier(n_neighbors, weights)
n_neighbors: 整数, 也就是k值
weights: 默认为’uniform’, 这个参数可以针对不同的邻居指定不同的权重, 也就是说, 越近的可以权重越高, 默认是一样的权重, ‘distance’可以设置不同的权重
:::
:::tips
在sklearn.neighbors还有一个变种KNN算法,为RadiusNeighborsClassifier算法,可以使用一定半径的点来取代距离最近的k个点。
接下来,我们通过设置weight和RadiusNeighborsClassifier,对算法进行比较。
:::
from sklearn.neighbors import KNeighborsClassifier, RadiusNeighborsClassifiermodel1 = KNeighborsClassifier(n_neighbors=2)model1.fit(X_train, Y_train.squeeze())score1 = model1.score(X_test, Y_test)print(score1)model2 = KNeighborsClassifier(n_neighbors=2, weights='distance')model2.fit(X_train, Y_train.squeeze())score2 = model2.score(X_test, Y_test)print(score2)model3 = RadiusNeighborsClassifier(radius=500.0)model3.fit(X_train, Y_train.squeeze())score3 = model3.score(X_test, Y_test)print(score3)
0.7142857142857143
0.7012987012987013 0.6493506493506493
:::info
可以看到使用三种不同的k邻近算法得到的结果
其中默认情况下的结果看起来是最好的, 但是不是最好, 还需要使用k折交叉验证 进行一下验证
:::
交叉验证
:::tips 通过上述结果可以看出:默认情况的KNN算法结果最好。这个判断准确么?答案是不准确,因为我们只是随机分配了一次训练和测试样本,可能下次随机选择训练和测试样本,结果就不一样了。这里的方法为:交叉验证。我们把数据集划分为10折,每次用9折训练,1折测试,就会有10次结果,求十次的平均即可。当然,可以设置cv的值,选择不同的折数。 :::
from sklearn.model_selection import cross_val_scoreresult1 = cross_val_score(model1, X, Y, cv=10)result2 = cross_val_score(model2, X, Y, cv=10)result3 = cross_val_score(model3, X, Y, cv=10)print(result1.mean(), result2.mean(), result3.mean())# result# 0.712235133288 0.67966507177 0.64976076555
:::info 可以看出,还是默认情况的KNN算法结果最好。 :::
