K最近邻法(KNN)的Python和R语言简单实现鸢尾花分类

一、KNN算法简介

K最近邻算法简称为KNN算法,属于监督学习中的一种分类算法,是最简单最基本的一种分类算法。所谓K最近邻,就是k个最近的邻居的意思,说的是每个样本都可以用它最接近的k个邻居来代表。

算法流程:

  1. 将每个样本视作一个点
  2. 载入数据集,对数据进行必要的预处理
  3. 设置参数K,K最好选择奇数,因为后续进行归类的策略是少数服从多数,设置K为奇数的话总会有结果。
  4. 计算待预测点与已知点之间的距离,在K近邻算法中计算样本之间的距离,一般采用欧式距离。

在这里插入图片描述

  1. 之前确定了参数K,计算了待预测点与已知点之间的距离衡量,将计算的结果进行从小到大排序,取前K个点
  2. 将待预测点归类为多数的那一个类别,这便是对于未知点的类别预测结果了。

Knn流程图

在这里插入图片描述

在这里插入图片描述在这里插入图片描述

算法优缺点

优点:

  • 简单,易于理解,易于实现,无需估计参数,无需训练
  • 适合对稀有事件进行分类
  • 特别适合于多分类问题(multi-modal,对象具有多个类别标签), kNN比SVM的表现要好

缺点:

  • 当样本不平衡时,如一个类的样本容量很大,而其他类样本容量很小时,有可能导致当输入一个新样本时,该样本的K个邻居中大容量类的样本占多数。 该算法只计算“最近的”邻居样本,某一类的样本数量很大,那么或者这类样本并不接近目标样本,或者这类样本很靠近目标样本。无论怎样,数量并不能影响运行结果
  • 计算量较大,因为对每一个待分类的文本都要计算它到全体已知样本的距离,才能求得它的K个最近邻点
  • 可理解性差,无法给出像决策树那样的规则

二. 实现鸢尾花分类

Iris data set也称鸢尾花卉数据集,是一类多重变量分析的数据集。其数据集包含了150个样本,都属于鸢尾属下的三个亚属,分别是山鸢尾(Iris setosa)变色鸢尾(Iris versicolor)
和维吉尼亚鸢尾(Iris virginica)。四个特征被用作样本的定量分析,分别是花等和花瓣的长度和宽度。实验中所用的数据集已经分为三类,第一组为山鸢尾数据,第二组为变色鸢尾数据

1. 用R语言分类

library(kknn)#加载kknn数据包
data(iris)#导入鸢尾花数据集
m <- dim(iris)[1]#数据集维数
val <- sample(1:m, size =round(m/3), replace = FALSE,prob= rep(1/m, m))#无放回随机抽样,50个数据
iris.train <- iris[-val,]#训练数据
iris.test  <- iris[val,]#测试数据
#建立模型
iris.kknn <- kknn(Species~.,iris.train, iris.test,k=5, distance = 5,kernel= "triangular")
summary(iris.kknn)#输出分类结果
fit <- fitted(iris.kknn)#拟合值
table(iris.test$Species, fit)#真实值和拟合值组合的计数表
pcol <- as.character(as.numeric(iris.test$Species))#将分类名称转换为用数字的代替的字符,用于下面画图的点的形状
pairs(iris.test[1:4], pch = pcol, col = c("green3", "red")[(iris.test$Species!= fit)+1])# 绘画散点图

在这里插入图片描述
在这里插入图片描述
可以看出,只有一个分类错误,分类效果也非常好。

2. python代码

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
from pandas import Series,DataFrame
from sklearn.datasets import load_iris
from sklearn.cross_validation import train_test_split
from matplotlib.colors import ListedColormap
from sklearn.neighbors import KNeighborsClassifier 


# 获取训练数据
iris=load_iris()#导入数据
data=iris.data##样本数据150*4二维数据,代表150个样本,每个样本4个属性分别为花瓣和花萼的长、宽
target=iris.target##长150的以为数组,样本数据的标签
target_names=iris.target_names#['setosa' 'versicolor' 'virginica']
feature_names=iris.feature_names#属性名称
features=DataFrame(data=data,columns=feature_names) #将数据集转为dataframe类型,列明为属性名称

# 训练数据取130条   总数据150条   
X_train=features.iloc[0:130,2:4]#取130行,数据集后两列作为训练集
y_train=target[:130]#前130行标签
# 测试数据取20条   总数据150条
x_test=features.iloc[130:,2:4]#后20行为测试集
y_test=target[130:]#后20行的标签
#display(X_train.shape,y_train.shape,x_test.shape,y_test.shape)#显示训练集和测试集的大小

knn=KNeighborsClassifier()#建立模型
knn.fit(X_train,y_train)# 训练数据
print("得分:",knn.score(x_test[:20],y_test[:20]))# 计算精确度
y_predict=knn.predict(x_test)# 预测
# 模型准确度的评估    
print("真实的鸢尾花分类:",y_test)# y_test真实的鸢尾花分类
print("预测的鸢尾花分类",y_predict)# 预测的鸢尾花分类
# 依然使用sklearn.metrics里面的classification_report模块对预测结果做更加详细的分析。
from sklearn.metrics import classification_report
print (classification_report(y_test, y_predict, target_names=iris.target_names))


#画图
#%matplotlib inline
samples=features.iloc[:,2:4]#取data中所有行后两列为训练数据
# display(samples)
# 横坐标花瓣的长度    纵坐标花瓣的宽度   颜色不同代表花瓣种类不同
plt.scatter(samples.iloc[:,0],samples.iloc[:,1],c=target)
cmap=ListedColormap(['#FF0000','#00FF00','#0000FF'])#颜色板
# 花瓣的长度最小值到最大值范围
xmin,xmax=samples.iloc[:,0].min(),samples.iloc[:,0].max()
# 花瓣的宽度最小值到最大值范围
ymin,ymax=samples.iloc[:,1].min(),samples.iloc[:,1].max()
x=np.linspace(xmin,xmax,100)#构造等差数列x,在最大与最小值的区间分成100个数据
y=np.linspace(ymin,ymax,100)
xx,yy=np.meshgrid(x,y)#绘制分类边界
x_test=np.c_[xx.ravel(),yy.ravel()]#生成10000个坐标点
y_=knn.predict(x_test)#预测训练数据
plt.scatter(x_test[:,0],x_test[:,1],c=y_,cmap=cmap)#绘制散点图形
plt.scatter(samples.iloc[:,0],samples.iloc[:,1],c=target)

在这里插入图片描述
在这里插入图片描述
分析:
从预测结果得分看出,预测效果非常不错,达到95%。因为测试集只选取后20行数据,在预测的鸢尾花分类中,有一个分类错误。从主要分类指标的文本报告中看出,预测精度很高,Knn的分类图中只有少数几个点分错。

发布了120 篇原创文章 · 获赞 7 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_42374697/article/details/105210230