KNN最近邻分类器

1.KNN原理

KNN的算法原理,可以简单如下描述:一个数据集中存在多个已有标签的样本值,这些样本值共有的n个特征构成了一个多维空间N。当有一个需要预测/分类的样本x出现,我们把这个x放到多维空间n中,找到离其距离最近的k个样本,并将这些样本称为最近邻(nearest
neighbour)。对这k个最近邻,查看他们的标签都属于何种类别,根据”少数服从多数,一点算一票”的原则进行判断,数量最多标签类别就是x的标签类别。其中涉及到的原理是“越相近越相似”,这也是KNN的基本假设。

若数据集只有两个特征,则针对于数据集的描述可用二维平面空间图来表示。如下图,二位平面空间的横坐标是特征1,纵坐标是特征2,每个样本点的分类(正或负)是该组样本的标签。图中给出了位于平面中心的,需要分类的数据点x,并用绿色分别标注了k为1,2,3时的最近邻状况。在图a中,x的1-最近邻是一个负例,因此x被指派到负类。图c中,3-最近邻中包括两个正例和一个负例,根据“少数服从多数原则”,点x被指派到正类。在最近邻中正例和负例个数相同的情况下(图b),算法将随机选择一个类标号来分类该点。

在这里插入图片描述
由上可知,KNN算法的实现步骤其实非常简单,假设现在我们有一个预测样本X,则判断X的分类的方法为:

  1. 计算X到所有训练集上的点的距离
  2. 按照距离递增次序对样本点进行排序
  3. 取前K个离X最近的点,查看他们的标签
  4. 对这K个点的标签加和,采取少数服从多数策略,占多数的标签则为点X的预测标签。

2. KNN在sklearn中的实现

  1. 导入需要的包
import numpy as np
import pandas as pd
from sklearn.neighbors import KNeighborsClassifier  #KNN分类器
from sklearn.datasets import load_breast_cancer  #导入乳腺癌数据集
from sklearn.model_selection import train_test_split#切分训练集和测试集的包
import matplotlib.pyplot as plt
data = load_breast_cancer()#给数据赋名
X = data.data#特征
Y = data.target#标签(好瓜、坏瓜)
  1. 分测试集、训练集
Xtrain,Xtest,Ytrain,Ytest = train_test_split(X,y #特征和标签
                                ,test_size=0.3 #测试集所占的比例,默认是0.25
                                            )#给特征和标签分训练集和测试集
  1. 建模
# 建立模型并评估模型

score = []
krange = range(1,20)#k取值
for i in krange:
    clf = KNeighborsClassifier(n_neighbors=i)#对每一个不同的K取值建模
    clf = clf.fit(Xtrain,Ytrain)#训练
    score.append(clf.score(Xtest,Ytest))#记录每个模型的分数
plt.plot(krange,score);#绘制学习曲线
bestindex = krange[score.index(max(score))]-1#得到最优K

得到的学习曲线如下。

注意!这里该模型为惰性学习模型,其实不产生模型。

在这里插入图片描述

  1. 数据归一化

即将数据归一到[0,1],一般按列

from sklearn.preprocessing import MinMaxScaler as mms 
Xtrain,Xtest,Ytrain,Ytest = train_test_split(X_,y,test_size=0.3,random_state=420) #切分训练集和测试集
#random_state=420代表着一种随机方式

MMS = mms().fit(Xtrain) #这一步是在学习训练集,生成训练集上的极小值和极差
Xtest_ = MMS.transform(Xtest) #用训练集上的极小值和极差归一化测试集
Xtrain_ = MMS.transform(Xtrain) #用训练集上的极小值和极差归一化训练集

5.真的建模

#带交叉验证的学习曲线

score = []
var_ = []
krange = range(1,20)
for i in krange:
    clf = KNeighborsClassifier(n_neighbors=i) #实例化KNN模型
    cvresult = CVS(clf,X,y,cv=5) #把全部数据放入,进行5折交叉验证
    score.append(cvresult.mean()) #把交叉验证的均值放入score
    var_.append(cvresult.var())  #把交叉验证的方差放入var_
plt.plot(krange,score,color="k")
plt.plot(krange,np.array(score)+np.array(var_)*2,c="red",linestyle="--")
plt.plot(krange,np.array(score)-np.array(var_)*2,c="red",linestyle="--");#作图
bestindex = krange[score.index(max(score))]-1#得到最优K k=8

在这里插入图片描述

6.验证模型效果

#测试模型效果
clf = KNeighborsClassifier(n_neighbors=8).fit(Xtrain_,Ytrain) #实例化模型并进行训练
score = clf.score(Xtest_,Ytest) #对测试集进行训练并返回结果
score

在这里插入图片描述

#加上参数weights,改变一点一票原则为距离
score = []
var_ = []
krange = range(1,20)
for i in krange:
    clf = KNeighborsClassifier(n_neighbors=i,weights="distance")#改变一点一票制规则,以距离作为惩罚因子
    cvresult = CVS(clf,Xtrain_,Ytrain,cv=5)
    score.append(cvresult.mean())
    var_.append(cvresult.var())
plt.plot(krange,score,color="k")
plt.plot(krange,np.array(score)+np.array(var_)*2,c="red",linestyle="--")
plt.plot(krange,np.array(score)-np.array(var_)*2,c="red",linestyle="--")
bestindex = krange[score.index(max(score))]-1
print(bestindex)#k=8
print(score[bestindex])
#测试模型效果
clf = KNeighborsClassifier(n_neighbors=8
                           ,weights="distance"
                          ).fit(Xtrain_,Ytrain)
score = clf.score(Xtest_,Ytest)
score
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值