算法大悲赋之KNN算法

一、描述

首先,KNN算法是一个初级算吧,书面解释是: KNN是通过测量不同特征值之间的距离进行分类。它的思路是:如果一个样本在特征空间中的k个最相似(即特征空间中最邻近)的样本中的大多数属于某一个类别,则该样本也属于这个类别,其中K通常是不大于20的整数。KNN算法中,所选择的邻居都是已经正确分类的对象。该方法在定类决策上只依据最邻近的一个或者几个样本的类别来决定待分样本所属的类别。
太繁琐晦涩了,所以我用KNN算法的实际事例来分部解释。

二、秘籍部分

算法是用Python开发的,首先导包,不解释

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

算法事例体现,要使用到表数据,导入表。

#读取CSV文件,去除头部,默认为0,第一行,如果不去重,可以使用pd.read_csv("iris.csv",header=None)None。
data=pd.read_csv("iris.csv")
#从头开始取
#data.head(5)
#从尾部开始取
#data.tail(5)
#抽样方法,默认输出一条数据
#data.sample(10)
data

这是原始表,列名一次为:id,花瓣宽度,花瓣长度,花蕊长度,花蕊宽度,种类。可以猜测到,这是一种花的数据,品种是鸢尾花,就是种类不同,这边定义了3种种类。
在这里插入图片描述

为了后续优化操作,将花种类换成数字,一共三种花。

#将文本类型转成 数字类型
data["Species"]=data["Species"].map({"virginica":0,"setosa":1,"versicolor":2})
#data.sample(10)
data

表Id这列用不到,所以将之删除。Python删除表一列,方法是:将每列id删除。可以看到代码。axis=1代表的是行操作。

#将Id这列删除 inplace设置为true,修改当前对象的值
data.drop("Id",axis=1,inplace=True)
data

下面是清洗表的重复数据

#判断是否有重复,false没有重复值,true数据重复
data.duplicated()
#返回true表示有重复值
data.duplicated().any()
#去除重复值
data.drop_duplicates(inplace=True)
len(data)

表已经初步完成操作,2、1、0代表的是花的种类。

#data["Species"]=data["Species"].map({"virginica":0,"setosa":1,"versicolor":2})
data["Species"].value_counts()

在这里插入图片描述

事例逻辑:
1、首先这里有149条花朵数据,分成100和49两部分。100这部分定义为训练集合,49定义为测试集合。
2、训练集合中取20条定义为 未知种类 但知道其余信息的 数据x,另外80条为y已知数据。用y数据的中的花瓣宽度,花瓣长度,花蕊长度,花蕊宽度依次去和x数据中的数据运算。即y中80条花瓣宽度,花瓣长度,花蕊长度,花蕊宽度和x中20条花瓣宽度,花瓣长度,花蕊长度,花蕊宽度,一一对应进行运算。运算为:4个数据对应相减,再进行平方,得到的4个平方数相加,再开根号。结果定义为length,length代表的是y中数据到x数据的距离。数值小,距离近。
3、每个x中的数据,取其距离该数据最近的k个数据,根据k个数据,来预测该数据的种类。比如:x_1是x中的一个数据,y_1、y_2、y_3是y中的数据,且是距离x_1最近的三个数据。根据y_1、y_2、y_3的花朵种类,来判断x_1的花朵种类。

class KNN:
#self在我个人理解中,是一个方式,在方法中,定义参数k,参数k传入到self中,在后续									        的方法中,就可以调用方法的,传递参数。
    """实现KNN算法 邻近算法 (分类)"""    				
    def __init__(self,k):
        """初始化方法
        k:int3
            获取邻居的个数
        """
        self.k=k
#训练集,这里参数X是鸢尾花的属性: 花瓣宽度,花瓣长度,花蕊长度,花蕊宽度;y代表的是鸢尾花的种类。
    def fit(self,X,y):
        """
        训练数据
        X:类数组类型,形状为:[样本数量,特征数量]
          训练样本特征(属性)
        y:类数组类型,形状为:[标签数量]
          每个样本的目标值(标签)
        """
        #将X,y转化成np array
        self.X=np.asarray(X)
        self.y=np.asarray(y)
#测试集,开始逻辑运算。这里为了方便理解,x20条数据定义为V。    
    def predict(self,V):
        """
        根据样本传过来的属性,预测特征
        V:类数组类型,形状为:[样本数量,特征数量]
        result:数组类型
            预测结果
        """
        V=np.asarray(V)
        result=[]
        #对测试数据集进行遍历,取出每条数据与训练数据集时进行计算
        for v in V:
            #获取每一个测试集到每一个训练集的距离
            dis=np.sqrt(np.sum((v-self.X)**2,axis=1))
            #将距离按照下标排序,如果将值排序,则找不到对应的花朵种类。
            index=dis.argsort()
            #取出前K表距离最近的邻居
            index=index[:self.k]
            #根据index获取y中对应的特征值,即获取花朵种类的各数量。
            count=np.bincount(self.y[index])
            #将数据存放到result集合中,去count中数量对多的数值对应的花朵种类。作为结果。
            result.append(count.argmax())
        #返回预测数据集合

        return np.asarray(result)

      
      #推算数据,这里是以花的三个数据,推算第四个数据。
    def predict(self,V):
        V=np.asarray(V)
        result=[]
        for v in V:
            dis=np.sqrt(np.sum((v-self.X)**2,axis=1))#计算测试集中数据到训练集数据的距离
            index=dis.argsort()#将距离,按照下标排序,不会打乱结果特征顺便
            index=index[:self.k]#根据选定的k值,截取前k个数据点
            result.append(np.mean(self.y[index]))#将前k个结算结果求平均值后,放入result
        return np.asarray(result)
    
    
    def predict2(self,V):
        """加权重"""
        V=np.asarray(V)
        result=[]
        for v in V:
            dis=np.sqrt(np.sum((v-self.X)**2,axis=1))#计算测试集中数据到训练集数据的距离
            index=dis.argsort()#将距离,按照下标排序,不会打乱结果特征顺便
            index=index[:self.k]#根据选定的k值,截取前k个数据点
            
            he=np.sum(1/(dis[index]+0.0001))#计算所有k个距离的倒数和
            weight=(1/(dis[index]+0.0001))/he #计算每个k点的权重值
            
            result.append(np.sum(self.y[index]*weight))#将前k个的计算结果(计算结果要与改点所占的权重比相乘)求平均值后放入result
        return np.asarray(result)




#data["Species"].value_counts()
t0=data[data["Species"]==0]
t1=data[data["Species"]==1]
t2=data[data["Species"]==2]
#len(t0)
#len(t1)
#len(t2)
#数据可以重现
t0=t0.sample(len(t0),random_state=0)
t1=t1.sample(len(t1),random_state=0)
t2=t2.sample(len(t2),random_state=0)
#准备训练和测试数据
train_X=pd.concat([t0.iloc[:40,:-1],t1.iloc[:40,:-1],t2.iloc[:40,:-1]],axis=0)
train_y=pd.concat([t0.iloc[:40,-1],t1.iloc[:40,-1],t2.iloc[:40,-1]],axis=0)
test_X=pd.concat([t0.iloc[40:,:-1],t1.iloc[40:,:-1],t2.iloc[40:,:-1]],axis=0)
test_y=pd.concat([t0.iloc[40:,-1],t1.iloc[40:,-1],t2.iloc[40:,-1]],axis=0)
#创建KNN对象
knn = KNN(k=80)
knn.fit(train_X,train_y) 
result=knn.predict(test_X)
result

在这里插入图片描述

#计算预测结果正确的个数
np.sum(result == test_y)
#计算预测结果正确率
np.sum(result == test_y)/len(test_y)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值