python机器学习课程笔记

【KNN分类】

学习课程:B站【超实用】Python实现机器学习算法(全) BV1V7411P7wL

KNN(k-nearest neighbor),K近邻算法,当需要表示一个样本值的时候,就使用与该样本最接近的K个邻居来决定。可用于分类,也可用于回归。

算法过程:

  1. 从训练集中选择离待测样本最近的k个样本

  1. 根据这k个样本计算待预测样本的值(属于哪个类别或一个具体数值)

k的取值会影响到结果

数据集:鸢尾花(Iris.csv)

jupyter notebook

数据处理

import numpy as np
import pandas as pd
# 读取鸢尾花数据集,header参数来指定标题的行,默认为0,如果没有标题,则使用None
data=pd.read.csv(r"Iris.csv)
## 显示前n行,默认n=5,括号内更改参数
# data.head()
## 显示最后n行,默认n=5
# data.tail()
## 随机抽取样本,默认为1
# data.sample()
## 显示全部数据
# data
# 将species的分类文本映射为数值类型
data["species"]=data["species"].map({"virginica":0,"setosa":1,"versicolor":2})
# 检查是否重复,.any()表示所有结果中只要有一项为True则输出结果为True
data.duplicated().any()
# 查看数据集样本数
len(data)
# 删除重复记录(括号内表示在原有的数据集上进行操作)
data.drop_duplicates(inplace=True)
len(data)
# 查看各个类别的鸢尾花各有多少条样本
data["species"].value_counts()

定义KNN分类

# 定义KNN的类
class KNN:
    """使用python语言实现KNN算法(分类)"""
    def __init__(self, k):
        """初始化方法
        parameters
        ----
        k:int   表示邻居的个数
    
        """
        self.k=k
        
    def fit(self,X,y):
        """训练方法
        parameters
        ----
        X:类数组类型,形状为:{样本数量,特征数量}
          待训练的样本特征(属性)
        y:类数组类型,形状为:{样本数量}
          每个样本的目标值(标签)
        """
        
        ## 将X转换成ndarray数据类型
        self.X=np.asarray(X)
        self.y=np.asarray(y)
    
    def predict(self,X):
        """根据参数传递的样本,对样本数据进行预测
        parameters
        ----
        X:类数组类型,形状为:{样本数量,特征数量}
          待训练的样本特征(属性)
          
        returns
        ----
        result:数组类型
          预测的结果
        """
        
        X=np.asarray(X)
        result=[]
        # 对ndarray数组进行遍历,每次取数组中的一行
        for x in X:
            # 测试集中的每一个样本与训练集中样本的距离,按行的平方和开根号
            dis=np.sqrt(np.sum((x-self.X) ** 2,axis=1))
            # 返回数组排序后,每个元素在原数组(排序前)中的索引
            index=dis.argsort()
            # 进行截断,只取前k个元素(取距离最近的k各元素的索引)
            index=index[:self.k]
            # 返回数组中每个元素出现的次数,元素必须是非负整数
            count=np.bincount(self.y[index])
            # 返回ndarray数组中,值最大的元素对应的索引,该索引就是我们判定的类别
            # 最大元素索引,就是出现次数最多的元素
            result.append(count.argmax())
        return np.asarray(result)        

数据训练及测试

# 提取出每个类型的鸢尾花数据
t0=data[data["species"]==0]
t1=data[data["species"]==1]
t2=data[data["species"]==2]
# 对每个类别进行洗牌,random_state使得每次运行打乱顺序的结果是相同的
t0=t0.sample(len(t0),random_state=0)
t1=t1.sample(len(t1),random_state=0)
t2=t2.sample(len(t2),random_state=0)
# 把t0、t1、t2进行整合,name.iloc切片,列不应该包含最后的类别列,按照纵向方式拼接
# 构建训练集与测试集
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=3)
# 进行训练
knn.fit(train_X,train_y)
# 进行测试,获得测试的结果
result=knn.predict(test_X)
# display(result)
# display(test_y)
display(np.sum(result==test_y))
display(np.sum(result==test_y)/len(result))

KNN结果可视化

# KNN可视化
import matplotlib as mpl
import matplotlib.pyplot as plt

# 默认情况下,matplotlib不支持中文显示,需要进行设置
# 设置字体为黑体,以支持中文显示
mpl.rcParams["font.family"]="SimHei"
# 设置在中文字体时,能够正常显示负号(-)
mpl.rcParams["axes.unicode_minus"]=False

# "virginica":0,"setosa":1,"versicolor":2
# 原数据集包含四个维度,不方便展示,可以挑选两个位置绘制散点图进行展示
# 设置画布大小
plt.figure(figsize=(10,10))
# 绘制训练集数据
plt.scatter(x=t0["sepal_length"][:40],y=t0["petal_length"][:40],color="r",label="virginica")
plt.scatter(x=t1["sepal_length"][:40],y=t1["petal_length"][:40],color="g",label="setosa")
plt.scatter(x=t2["sepal_length"][:40],y=t2["petal_length"][:40],color="b",label="versicolor")
# 绘制测试集数据,将正确预测和错误预测分开
right=test_X[result==test_y]
wrong=test_X[result!=test_y]
plt.scatter(x=right["sepal_length"],y=right["petal_length"],color="c",marker="x",label="right")
plt.scatter(x=wrong["sepal_length"],y=wrong["petal_length"],color="m",marker=">",label="wrong")
plt.xlabel("花萼长度")
plt.ylabel("花瓣长度")
plt.title("KNN分类结果显示")
plt.legend(loc="best")
plt.show()

被预测点周围的点可能与之距离不同,距离近的影响大,距离远的影响小,因此需要相应赋权

在原KNN分类定义上做改动

# 相对于predict而言是考虑权重的,可以使用距离的倒数来作为权重
    def predict2(self,X):
        """根据参数传递的样本,对样本数据进行预测
        parameters
        ----
        X:类数组类型,形状为:{样本数量,特征数量}
          待训练的样本特征(属性)
          
        returns
        ----
        result:数组类型
          预测的结果
        """
        
        X=np.asarray(X)
        result=[];
        # 对ndarray数组进行遍历,每次取数组中的一行
        for x in X:
            # 对于测试集中的每一个样本,依次与训练集中的所有样本求距离
            dis=np.sqrt(np.sum((x-self.X)**2,axis=1))
            # 返回数组排序后,每个元素在原数组(排序之前的数组)中的索引
            index=dis.argsort()
            # 进行截断,只取前k个元素(取距离最近的k各元素的索引)
            index=index[:self.k]
            ### 在这一步有所改动
            # 返回数组中每个元素出现的次数,元素必须是非负的整数,使用weights考虑权重,权重为距离的倒数
            count=np.bincount(self.y[index],weights=1/dis[index])
            # 返回ndarray数组中,值最大元素对应的索引,该索引就是需要判定的类别
            # 最大元素索引,就是出现次数最多的元素
            result.append(count.argmax())
        return np.asarray(result)

测试

# 考虑权重进行一下测试
result2=knn.predict2(test_X)
display(np.sum(result2==test_y))

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值