KNN最邻近分类算法【案例演示非常详细】

KNN算法简介

KNN(K-Nearest Neighbor) 最邻近分类算法时数据挖掘分类(classification)技术中最简单的算法之一,KNN算法用到的思想是,在相同范围内预测目标属于哪一类,看的就是范围内已知类别的数量大小,最多的则作为预测值。

KNN最邻近分类算法实现原理

为了判断位置样本的类别,以所有一直类别的样本作为参照,计算位置样本与所有一直样本的距离,从中选取与位置样本距离最近的K个已知样本,根据少数服从多数的投票法则,将位置样本与K个最临近样本中所属类别占比较多的归为一类。
以上就是KNN算法在分类任务中的基本原理,实际上K这个字母的含义就是要选取的最近邻近样本示例的个数。
K的取值决定了分类的结果。当K取值过小时,噪声成分对整体结果影响较大。
当K取值过大时,就意味着,及时离样本距离交院的点也对样本产生一定的影响,会造成预测结果的准确性降低。我们可以想象两个极端,当K取值为1时,模型整体会非常复杂,一旦最近的点是个噪声点,就意味着分类错误。当K取真个样本数时,那么分类的结果是一种先验概率,并不具有参考性。因此,k要选择恰当的取值。

KNN算法的关键

样本的所有特征都要做可比较的量化

若是样本特征中存在非数量的类型,必须采取手段将量化为数值。例如样本特征中包含颜色,可通过将颜色转换为灰度值来实现距离计算。

样本特征要做归一化处理

样本有多个参数,每个参数都有自己的定义域和取值范围,他们对距离计算的影响不一样,如取值较大的影响力会盖过取值较小的参数。所以样本参数必须做一些scale处理,最简单的方式就是所有特征的数量都采取归一化处置。

需要一个距离函数计算两个样本之间的距离

通常使用的距离函数有欧氏距离余弦距离汉明距离曼哈顿距离等,一啊不能选欧式距离作为距离度量,但是这是只适用于连续变量。在文本分类这种非连续变量清凉下,汉明距离可以用来作为度量。通常情况下,如果运用溢写特殊的算法来计算氟利昂的话,K近邻分类精度可显著提高,如运用大边缘最近邻法或者近邻成分分析法。
在这里插入图片描述

K值的确定

K值选的太大易引起拟合,太小容易过拟合,需交叉验证确定K值。

KNN算法的优点

  • 简单,容易理解,易于实现,无需估计参数。
  • 适合对西游时间进行分类
  • 特别适合与多分类问题(mulit-modal,对象具有多个类别标签)。

KNN算法的缺点

KNN算法在分类时有个主要的不足是,当样本不平衡时,如一个类的样本容量很大,而其他类样本容量很小时,有可能导致当输入一个新样本时,该样本的K个邻居中大容量类的样本站多数。该算法只计算最近的邻居样本,某一类的样本数量很大,那么或者这类样本并不接近目标样本,或者这列样本很靠近目标样本。无论怎样,数量并不能影响运行结果。可以采用权值的方法来改进。

花瓣参数判断花瓣种类的案例演示

图文解释

以随机取的10条数据为例
在这里插入图片描述

文件准备

链接:算法所用到的文件
提取码:lyq6

前期数据清洗准备

# 导入jar包
import numpy as np
import pandas as pd

# 读取csv文件 去除头部 默认 0 ,第一行,如果不去除头部,可以使用None
data = pd.read_csv("iris.csv",header=0)
# 对读取数据进行检验
# head 默认5行
data.head(10)
# 取最后20行
data.tail(20)
# 抽样方法
data.sample(10)

# 将文本类型转换成 数字类型
data["Species"] = data["Species"].map({"virginica":0,"setosa":1,"versicolor":2})
data.sample(10)
# 删除Id列 inplace设置为true,修改当前对象的值
data.drop("Id",axis=1,inplace=True)
# 判断是否有重复 False没有重复值  True有重复值
data.duplicated()
# 返回true以后表示有重复值
data.duplicated().any()

# 去除重复值
# 相当于矩阵去除线性相关
data.drop_duplicates(inplace=True)
data
data["Species"].value_counts()

KNN分类算法的编写

class KNN:
    """实现 KNN 临近算法 (分类)"""
    def __init__(self,k):
        """
        初始化方法
        
        k : int
            获取邻居的个数
        self : 相当于java中的this,名字可以随便起
        """
        self.k = k
    def fit(self,X,y):
        """
        训练数据
        
        Parameter
        X:类数组类型,形状为:【样本数量,特征数量】(表示矩阵)
          训练样本特征(属性)   5.1,,3.5,1.4,0.2
        y:类数组类型,形状为:【标签数量】(表示向量)
          每个样本的目标值(标签)    1
        """
        # 将X,y转化成np array
        self.X = np.asarray(X)
        self.y = np.asarray(y)
        
    def predict(self,V):
        """根据样本传过来的属性,预测特征
        
        X:类数组类型,形状为:【样本数量,特征数量】
        
        result:数据类型
            预测结果
            
        """
        V = np.asarray(V)
        result = []
        # 对测试数据集进行遍历,取出每条数据与训练数据集合进行计算
        for v in V:
            #获取每一个测试集到每一个训练集的距离
            dis = np.sqrt(np.sum((v - self.X)**2,axis=1))
            #将距离dis进行排序(下标进行排序)
            index = dis.argsort()
            # 取出前k个距离最近的邻居
            index = index[:self.k]
            #根据index过去y中对应的特征值
            count = np.bincount(self.y[index],weights= 1 /dis[index])
            result.append(count.argmax())
        #返回预测数据集合
        return np.asarray(result)

训练数据集和预测数据集的准备

# 将data表数据按最后一列分类成三分数据
t0 = data[data["Species"]==0]
t1 = data[data["Species"]==1]
t2 = data[data["Species"]==2]

# 将数据按随机值打乱
t0 = t0.sample(len(t0),random_state=0)
t1 = t1.sample(len(t1),random_state=0)
t2 = t2.sample(len(t2),random_state=0)

# 取每类数据的前40条数据作为训练数据
train_X = pd.concat([t0.iloc[:40,:-1],t1.iloc[:40,:-1],t2.iloc[:40,:-1]],axis=0)
# 取每类数据的前40条数据的结果集作为训练结果集
train_y = pd.concat([t0.iloc[:40,-1],t1.iloc[:40,-1],t2.iloc[:40,-1]],axis=0)
# 取第40条以后的数据作为预测所需数据
test_X = pd.concat([t0.iloc[40:,:-1],t1.iloc[40:,:-1],t2.iloc[40:,:-1]],axis=0)
# 取第40条以后的数据的结果最为标准,与预测结果进行对比
test_y = pd.concat([t0.iloc[40:,-1],t1.iloc[40:,-1],t2.iloc[40:,-1]],axis=0)

创建KNN对象,预测算法的准确性

# 创建 KNN 对象
knn = KNN(k=3)
#训练数据
knn.fit(train_X,train_y)
#预测结果
result = knn.predict(test_X)

# 计算预测结果的正确个数
np.sum(result==test_y)

# 计算预测结果准确率
np.sum(result==test_y)/len(test_y)

可视化预测结果

# 导入可视化包
import matplotlib as mpl
import matplotlib.pyplot as plt

# matplotlib 不支持中文,需要配置一下,设置一个中文字体
mpl.rcParams["font.family"] = "SimHei"
# 能够显示 中文 ,正常显示 "-"
mpl.rcParams["axes.unicode_minus"] = False

绘制点状分布图

#设置画布大小
plt.figure(figsize=(10,10))

# SepalLengthCm,SepalWidthCm,PetalLengthCm,PetalWidthCm
# 绘制 点图,需要提供  x坐标  (花蕊的长度) y坐标 (花瓣的长度)
plt.scatter(x=t0["SepalLengthCm"][:40],y=t0["PetalLengthCm"][:40],color="r",label="virginica")
plt.scatter(x=t1["SepalLengthCm"][:40],y=t1["PetalLengthCm"][:40],color="g",label="setosa")
plt.scatter(x=t2["SepalLengthCm"][:40],y=t2["PetalLengthCm"][:40],color="b",label="versicolor")

# 测试数据集  test_y(待测试数据集  真实数据集)  result(用KNN算法计算出来的数据集)
right = test_X[test_y == result]
wrong = test_X[test_y != result]

plt.scatter(x=right["SepalLengthCm"],y=right["PetalLengthCm"],color="c",label="right",marker="x")
plt.scatter(x=wrong["SepalLengthCm"],y=wrong["PetalLengthCm"],color="m",label="wrong",marker=">")

#plt.xlabel="花萼"
#plt.ylabel="花瓣"
#plt.title="KNN分类算法显示"
# 如果不显示重新启动jupyter
plt.xlabel('花萼')
plt.ylabel('花瓣')
plt.title('KNN分类算法显示')
plt.legend()

plt.show()

结果为:
在这里插入图片描述

  • 2
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值