机器学习笔记 K近邻(附Python与R代码)

K近邻算法

原理:通过计算新数据和训练数据特征值之间的距离,然后选取K个距离最近的邻居进行分类判断(投票法)或者回归。

特点:不具有显示的学习过程,直接预测。实际上式利用训练数据集对特征向量空间进行划分,并且作为其分类的“模型”。

k值选择

  • k=1,称为最近邻算法。此时将训练集中与测试样本最近的点类别作为测试样本的分类。
  • k较小,用较小的邻域中的训练实例进行预测。偏差较小,方差较大,对近邻的实例点较为敏感,易受噪声影响,导致过拟合。
  • k较大,用较大的邻域中的训练实例进行预测。偏差较大,方差较小。
  • 一般k选取较小的数值,采用交叉验证法来选取最优的k值。

距离度量

  • 非数值型数据需转换成数值型,便于计算距离;
  • 避免不同特征的取值范围影响距离计算,需对特征数据采取归一化处理;
  • 不同的距离度量所确定的最近林点不同,一般情况下,选欧式距离作为距离度量。

分类决策规则
多数表决。也可基于距离的远近进行加权投票。

PYTHON实战

导入包

import numpy as np 
import matplotlib.pyplot as plt 
from sklearn import neighbors, datasets,cross_validation 

加载数据

def load_classification_data():     
'''     加载分类模型使用的数据集。       :return: 一个元组,依次为:训练样本集、测试样本集、训练样本的标记、测试样本的标记     '''     
digits=datasets.load_digits() # 使用 scikit-learn 自带的手写识别数据集 Digit Dataset     
X_train=digits.data     
y_train=digits.target     
return cross_validation.train_test_split(X_train, y_train,test_size=0.25,random_state=0,stratify=y_train) # 进行分层采样拆分,测试集大小占 1/4 

定义knn分类器

def test_KNeighborsClassifier(*data):     
'''     测试 KNeighborsClassifier 的用法       :param data: 可变参数。它是一个元组,这里要求其元素依次为:训练样本集、测试样本集、训练样本的标记、测试样本的标记     :return: None     '''     
X_train,X_test,y_train,y_test=data     
clf=neighbors.KNeighborsClassifier()     
clf.fit(X_train,y_train)     
print("Training Score:%f"%clf.score(X_train,y_train))     
print("Testing Score:%f"%clf.score(X_test,y_test)) 

参数优化

def test_KNeighborsClassifier_k_w(*data):     
'''     测试 KNeighborsClassifier 中 n_neighbors 和 weights 参数的影响       :param data: 可变参数。它是一个元组,这里要求其元素依次为:训练样本集、测试样本集、训练样本的标记、测试样本的标记     :return: None     '''     
X_train,X_test,y_train,y_test=data     
Ks=np.linspace(1,y_train.size,num=100,endpoint=False,dtype='int')     
weights=['uniform','distance']       
fig=plt.figure()     
ax=fig.add_subplot(1,1,1)     ### 绘制不同 weights 下, 预测得分随 n_neighbors 的曲线     
for weight in weights:         
training_scores=[]         
testing_scores=[]         
for K in Ks:             
clf=neighbors.KNeighborsClassifier(weights=weight,n_neighbors=K)             
clf.fit(X_train,y_train)             
testing_scores.append(clf.score(X_test,y_test))              
training_scores.append(clf.score(X_train,y_train))         
ax.plot(Ks,testing_scores,label="testing score:weight=%s"%weight)         
ax.plot(Ks,training_scores,label="training score:weight=%s"%weight)     
ax.legend(loc='best')     
ax.set_xlabel("K")     
ax.set_ylabel("score")     
ax.set_ylim(0,1.05)     
ax.set_title("KNeighborsClassifier")     
plt.show() 
    
def test_KNeighborsClassifier_k_p(*data):    
     '''     测试 KNeighborsClassifier 中 n_neighbors 和 p 参数的影响       :param data: 可变参数。它是一个元组,这里要求其元素依次为:训练样本集、测试样本集、训练样本的标记、测试样本的标记     :return: None     '''     
X_train,X_test,y_train,y_test=data     
Ks=np.linspace(1,y_train.size,endpoint=False,dtype='int')     
Ps=[1,2,10]       
fig=plt.figure()     
ax=fig.add_subplot(1,1,1)     ### 绘制不同 p 下, 预测得分随 n_neighbors 的曲线     
for P in Ps:         
training_scores=[]         
testing_scores=[]         
for K in Ks:             
clf=neighbors.KNeighborsClassifier(p=P,n_neighbors=K)             
clf.fit(X_train,y_train)             
testing_scores.append(clf.score(X_test,y_test))             
training_scores.append(clf.score(X_train,y_train))         
ax.plot(Ks,testing_scores,label="testing score:p=%d"%P)         
ax.plot(Ks,training_scores,label="training score:p=%d"%P)     
ax.legend(loc='best')     
 ax.set_xlabel("K")     
 ax.set_ylabel("score")     
 ax.set_ylim(0,1.05)     
 ax.set_title("KNeighborsClassifier")     
 plt.show()   

运行代码

if __name__=='__main__':     
X_train,X_test,y_train,y_test=load_classification_data() # 获取分类模型的数据集     
test_KNeighborsClassifier(X_train,X_test,y_train,y_test) # 调用 test_KNeighborsClassifier     
test_KNeighborsClassifier_k_w(X_train,X_test,y_train,y_test)# 调用 test_KNeighborsClassifier_k_w     
test_KNeighborsClassifier_k_p(X_train,X_test,y_train,y_test)# 调用 test_KNeighborsClassifier_k_p

R实战

目标:采用rpart包中的car.test.frame数据,取最后10个观测值为测试集,其余为训练集。以Mileage(定量变量)为因变量,以定量变量Price、Weight、Disp. 、HP为自变量,在训练集中找出最优的参数设置值(采用留一交叉验证,邻居个数在48个及以内),并采用最优的参数值在测试集中预测,给出预测的效果评价。

代码

library(rpart)
data(car.test.frame)
head(car.test.frame)
alldata<-cbind(car.test.frame[,4],car.test.frame[,c(1,6:8)])
names(alldata)[1] <- "y"
dim(alldata)
str(alldata)
library(VIM)
aggr(alldata)
train<-alldata[1:50,]
test<-alldata[51:60,]
(car_fit.knn<- train.kknn(y~ .,train,scale=T, kmax =48, kernel = 
 c("rectangular","triangular","epanechnikov","biweight",
"triweight","cos","inv","gaussi","rank","optimal"),distance = 2))
plot(car_fit.knn,main="最优参数选择")
test.fit.knn<- kknn(y~.,train,test[,-1],k=2,scale=T,distance=2,kernel= "inv")
a<-test.fit.knn$fitted.values 
b<-test$y
c<-mean(test$y)
(test.knn.RMSE<-sqrt(mean((a-b)^2)))
(test.knn.RRSE<-1-sum((a-b)^2)/sum((b-c)^2))
(test.knn.MAE<-mean(abs(a-b)))
(test.knn.RAE<-sum(abs(a-b))/sum(abs(b-c)))
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值