机器学习基础算法一:KNN算法分类实验

【KNN分类实验】

什么是KNN?

  • 概念: KNN(K-nearest neighbor),即K近邻算法。当需要一个样本(值)的时候,就使用与该样本最接近的K个邻居来决定。KNN既可用于分类,也能用于回归。(“近”朱者赤,“近”墨者黑)
    在这里插入图片描述
  • KNN算法的实现过程:
    1. 从训练集中选择离待预测样本最近的k个样本。
    2. 根据这k个样本计算待预测样本的值(属于哪个类别或者一个具体数值)。
      在这里插入图片描述
      k的取值会影响分类的结果,如上图所示,k取最里面圆圈的大小则三角形多正方形少,则把圆形归类于三角形一类。如果k取虚线圆圈的大小,正方形多,三角形少,则把圆形归类于正方形一类

算法实现:

  • 要进行knn的实验,首先得要有可用的数据集,这里可以去网上下载经典的鸢尾花数据集进行实验,在csdn中搜索“鸢尾花数据集”就可以找到很多好心博主的分享,随便找一个下载即可。
    一、导入数据集

    import numpy as np
    import pandas as pd   # 导入包
    data = pd.read_csv(r"E:\Machine learning data\Iris\Iris.csv",header=0)  # 读取数据集
    print(data)
    
    • E:\Machine learning data\Iris\Iris.csv 是我的数据集存放路径,你们自己的存放位置可以自己去找到然后复制路径粘贴过来,还有一点要注意的是保存的路径都是英文比较好(就是你的文件夹用英文取名)。
    • 打印结果:在这里插入图片描述
      打印的结果被省略了很多内容,应该是pandas函数对初始对显示的行数列数和宽度有限制。通过增加这几行代码就能显示所有的内容了:
      pd.set_option('display.max_rows', 1000) #增加行数
      pd.set_option('display.max_columns', 1000) #增加列数
      pd.set_option('display.width', 1000) #增加每行宽度
    • 更改后的代码:
      import numpy as np
      import pandas as pd   # 导入包
      pd.set_option('display.max_rows', 1000)
      pd.set_option('display.max_columns',1000)
      pd.set_option('display.width', 1000)  #增加表格的列数行数和每行的宽度以此让数据集完整表示
      data = pd.read_csv(r"E:\Machine learning data\Iris\Iris.csv",header=0)  #读取数据集,header参数用来指定标题的行,默认值是0。如果没有标题则使header=None
      print (data)
      # print(data.head(10))  # 显示数据集前十行
      # print(data.tail(10))  # 显示数据集后十行
      # print(data.sample(2))  # 随机抽取2个样本
      

    二、对原始数据集进行处理,把文本映射成数值便于后面数据的使用

    • 映射代码 :
      data["Species"] = data["Species"].map({"setosa": 0,"versicolor": 1,"virginica": 2})  #把花的种类名称映射成数字
      print(data.sample(20))
      
    • 打印结果:
      在这里插入图片描述
      可以发现Species那一列的名称变成了数字表示。

    三、对数据集金进一步处理

    • 删除无用的列:
      data.drop("Unnamed: 0",axis=1,inplace=True)  # 删除没有用的 Unamed: 0 的那一列
      
    • 检查数据集中有无重复的数据,并删除无用的数据:
      print(data.duplicated().any()) #检查数据集中有没有重复的数据
      data.drop_duplicates(inplace=True)  # 删除数据集中的重复数据
      
    • 我们在运用机器学习的方法来分析数据时,首要的步骤就是处理原始的数据,使得原始的数据可以被机器学习方法所使用。

    四、初始化

    class KNN:
    """使用Python语言实现k近邻算法。(实现分类)"""
    def __init__(self, k):
        """初始化方法
        parameters
        -----
        k : int
            邻居的个数。
        """
        self.k = k   #用当前的k来初始化KNN对象中的k
    

    五、训练方法

    def fit(self, X, y):   # 训练样本中X是大写的,而标签y是小写的,因为矩阵习惯用大写字母表示,向量习惯用小写字母来表示。
        """训练方法
        Parameters
        -----
        X: 类数组类型,形状为:[样本数量,特征的数量]
            带训练的样本特征(属性)
        y:类数组类型,形状为:[样本数量]
            每个样本的目标值(标签)
        """
        self.X = np.asarray(X)  # 把X,y转化成ndarray数组类型。
        self.y = np.asarray(y) 
    

    六、预测

     def predict(self,X):
        """根据参数传递的样本,对样本数据进行预测。
        Parameters
        ------
        X: 类数组类型,形状为:[样本数量,特征的数量]
            带训练的样本特征(属性)
        Returns
        ------
        result:数组类型
            预测的结果
        """
        X = np.array(X)
        result = []
        # 对ndarray数组进行遍历,每次取数组中的一行。
        for x in X:
            # 求测试集中的每个样本与训练集中所有点的距离。
            # x代表测试集中的一行,X代表训练集中的所有行。ndarray数组可以自己广播扩展然后对位运算。
            dis = np.sqrt(np.sum((x - self.X) ** 2,axis=1))
            # argsort可以将数组排序后,每个元素在原数组中的索引位置。
            index = dis.argsort()
            # 进行截断,只取前k个元素【取距离最近的k个元素的索引】
            index = index[:self.k]
            # 返回数组中每个元素出现的次数。元素必须是非负的整数。
            count = np.bincount(self.y[index])
            #  返回ndarray数组中,值最大的元素对应的索引,该索引就是我们判定的类别。
            result.append(count.argmax())
        return np.asarray(result)
    

    七、测试KNN的分类效果

    • 首先要将初始的数据分成训练集和测试集两部分。
    # 提取出每个类别花的数据
    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)
    #构建训练集和测试集
    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)
    text_X = pd.concat([t0.iloc[40:,:-1],t1.iloc[40:,:-1],t2.iloc[40:,:-1]],axis=0)
    text_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)
    print(result)  # 打印预测的结果
    print(test_y)  # 打印原来测试的答案
    print(result == test_y)  # 直接判断是否预测正确
    print(np.sum(result == test_y))  # 进行求和运算看分类对了多少个
    print(len(result))
    print(np.sum(result == test_y)/len(result))
    
    • 结果截图
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述

    八、可视化操作

    #可视化操作
    import matplotlib as mpl
    import matplotlib.pyplot as plt
    # 默认情况下,matplotlib不支持中文显示,我们需要进行设置
    # 设置字体为黑体,以支持中文显示。
    mpl.rcParams["font.family"] = "SimHei"
    # 设置在中文字体时,能够正常的显示负号(-)
    mpl.rcParams["axes.unicode_minus"] = False
    
    # {"setosa": 0, "versicolor": 1, "virginica": 2}
    # 绘制训练集数据
    plt.scatter(x=t0["Sepal.Length"][:40],y=t0["Petal.Length"][:40],color='r',label="setosa")
    plt.scatter(x=t1["Sepal.Length"][:40],y=t1["Petal.Length"]	[:40],color='g',label="versicolor")
    plt.scatter(x=t2["Sepal.Length"][:40],y=t2["Petal.Length"][:40],color='b',label="virginica")
    plt.show()  # 显示图片得有这一句
    
    • 要显示图像的话需要加上代码 plt.show()
    • 图像截图如下:
      在这里插入图片描述

    九、完整代码

    import numpy as np
    import pandas as pd  # 导入包
    import pandas as pd
    
    pd.set_option('display.max_rows', 500)
    pd.set_option('display.max_columns', 500)
    pd.set_option('display.width', 1000)  # 增加表格的列数行数和每行的宽度以此让数	据集完整表示
    data = pd.read_csv(r"E:\Machine learning data\Iris\Iris.csv", header=0)  # 读取数据集,header参数用来指定标题的行,默认值是0。如	果没有标题则使header=None
    # print(data.head(10))  # 显示数据集前十行
    # print(data.tail(10))  # 显示数据集后十行
    # print(data.sample(2))  # 随机抽取2个样本
    data["Species"] = data["Species"].map({"setosa": 0, "versicolor": 1, "virginica": 2})  # 把花的种类名称映射成数字
    data.drop("Unnamed: 0", axis=1, inplace=True)  # 删除没有用的 Unamed: 0 的那一列
    
    
    # print(data.duplicated().any()) #检查数据集中有没有重复的数据
    # data.drop_duplicates(inplace=True)  # 删除数据集中的重复数据
    # print(len(data))  # 查看数据的总条数
    # print(data.sample(20)) # 随机显示数据
    # print(data["Species"].value_counts())  # 显示每个类别的记录各有多少个
    
    
    class KNN:
    """使用Python语言实现k近邻算法。(实现分类)"""
    def __init__(self, k):
        """初始化方法
        parameters
        -----
        k : int
            邻居的个数。
        """
        self.k = k   #用当前的k来初始化KNN对象中的k
    
    def fit(self, X, y):   # 训练样本中X是大写的,而标签y是小写的,因为矩阵习惯用大写字母表示,向量习惯用小写字母来表示。
        """训练方法
        Parameters
        -----
        X: 类数组类型,形状为:[样本数量,特征的数量]
            带训练的样本特征(属性)
        y:类数组类型,形状为:[样本数量]
            每个样本的目标值(标签)
        """
        self.X = np.asarray(X)  # 把X,y转化成ndarray数组类型。
        self.y = np.asarray(y)
    
    def predict(self,X):
        """根据参数传递的样本,对样本数据进行预测。
        Parameters
        ------
        X: 类数组类型,形状为:[样本数量,特征的数量]
            带训练的样本特征(属性)
        Returns
        ------
        result:数组类型
            预测的结果
        """
        X = np.array(X)
        result = []
        # 对ndarray数组进行遍历,每次取数组中的一行。
        for x in X:
            # 求测试集中的每个样本与训练集中所有点的距离。
            # x代表测试集中的一行,X代表训练集中的所有行。ndarray数组可以自己广播扩展然后对位运算。
            dis = np.sqrt(np.sum((x - self.X) ** 2,axis=1))
            # argsort可以将数组排序后,每个元素在原数组中的索引位置。
            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)
    
    # 提取出每个类别花的数据
    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)
    #构建训练集和测试集
    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)
    print(result)  # 打印预测的结果
    print(test_y)  # 打印原来测试的答案
    print(result == test_y)  # 直接判断是否预测正确
    print(np.sum(result == test_y))  # 进行求和运算看分类对了多少个
    print(len(result))
    print(np.sum(result == test_y)/len(result))
    #可视化操作
    import matplotlib as mpl
    import matplotlib.pyplot as plt
    # 默认情况下,matplotlib不支持中文显示,我们需要进行设置
    # 设置字体为黑体,以支持中文显示。
    mpl.rcParams["font.family"] = "SimHei"
    # 设置在中文字体时,能够正常的显示负号(-)
    mpl.rcParams["axes.unicode_minus"] = False
    
    # {"setosa": 0, "versicolor": 1, "virginica": 2}
    # 绘制训练集数据
    plt.scatter(x=t0["Sepal.Length"][:40],y=t0["Petal.Length"][:40],color='r',label="setosa")
    plt.scatter(x=t1["Sepal.Length"][:40],y=t1["Petal.Length"][:40],color='g',label="versicolor")
    plt.scatter(x=t2["Sepal.Length"][:40],y=t2["Petal.Length"][:40],color='b',label="virginica")
    # 绘制测试集数据
    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=">",label="right")
    plt.scatter(x=wrong["Sepal.Length"],y=wrong["Petal.Length"],color='m',marker="x",label="wrong")
    plt.xlabel("花萼长度")
    plt.ylabel("花瓣长度")
    plt.title("KNN分类结果显示")
    plt.legend(loc="best")
    plt.show()  # 显示图片得有这一句
    

    十、最后实验截图
    在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值