昇思MindSpore 应用学习-K近邻算法实现红酒聚类-CSDN

嚴華  论坛元老 | 2024-7-24 07:39:26 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 1017|帖子 1017|积分 3051

K近邻算法实现红酒聚类-AI代码剖析

本实验重要介绍使用MindSpore在部分wine数据集上举行KNN实验。
1、实验目的



  • 了解KNN的基本概念;
  • 了解如何使用MindSpore举行KNN实验。
2、K近邻算法原理介绍

K近邻算法(K-Nearest-Neighbor, KNN)是一种用于分类和回归的非参数统计方法,最初由 Cover 和 Hart 于 1968 年提出,是机器学习最基础的算法之一。它的基本思想是:要确定一个样本的类别,可以计算它与全部训练样本的距离,然后找出和该样本最接近的 k 个样本,统计出这些样本的类别并举行投票,票数最多的谁人类就是分类的结果。
KNN的三个基本要素:


  • K值:一个样本的分类是由 K 个邻居的“多数表决”确定的。K 值越小,容易受噪声影响,反之,会使类别之间的边界变得含糊。
  • 距离度量:反映了特性空间中两个样本间的相似度,距离越小,越相似。常用的有 Lp 距离(p=2 时,即为欧式距离)、曼哈顿距离、海明距离等。
  • 分类决策规则:通常是多数表决,或者基于距离加权的多数表决(权值与距离成反比)。
2.1 分类题目

推测算法(分类)的流程如下:

  • 在训练样本集中找出距离待测样本 x_test 最近的 k 个样本,并生存至集合 N 中;
  • 统计集合 N 中每一类样本的个数 (C_{i}, i=1,2,3,…,c);
  • 终极的分类结果为 ( \text{argmax} C_{i} )(最大的对应的 (C_{i}))谁人类。
在上述实现过程中,k 的取值尤为紧张。它可以根据题目和数据特点来确定。在详细实现时,可以思量样本的权重,即每个样本有差异的投票权重,这种方法称为带权重的 k 近邻算法,它是一种变种的 k 近邻算法。
2.2 回归题目

假设离测试样本最近的 k 个训练样本的标签值为 (y_{i}),则对样本的回归推测输出值为:

即为全部邻居的标签均值。
带样本权重的回归推测函数为:

此中 (w_{i}) 为第个 (i) 样本的权重。
2.3 距离的界说

KNN算法的实现依靠于样本之间的距离,此中最常用的距离函数就是欧氏距离(欧几里得距离)。( \mathbb{R}^{n} )空间中的两点 (x) 和 (y),它们之间的欧氏距离界说为:

必要特别留意的是,使用欧氏距离时,应将特性向量的每个分量归一化,以减少因为特性值的标准范围差异所带来的干扰,否则数值小的特性分量会被数值大的特性分量沉没。
别的的距离计算方式还有 Mahalanobis 距离、Bhattacharyya 距离等。
3、实验环境

预备知识:


  • 熟练使用 Python;
  • 具备一定的机器学习理论知识,如 KNN、无监督学习、欧式距离等。
实验环境:


  • MindSpore 2.0(MindSpore 版本会定期更新,本引导也会定期革新,与版本配套);
  • 本案例支持 win_x86 和 Linux 系统,CPU/GPU/Ascend 均可运行;
  • 如果在本地运行此实验,请参考《MindSpore 环境搭建实验手册》在本地安装 MindSpore。
4、数据处理

4.1 数据准备

Wine 数据集是模式识别最著名的数据集之一,Wine 数据集的官网:Wine Data Set。这些数据是对来自意大利同一地区但来自三个差异品种的葡萄酒举行化学分析的结果。数据集分析了三种葡萄酒中每种所含 13 种身分的量。这些 13 种属性是:

  • Alcohol,酒精
  • Malic acid,苹果酸
  • Ash,灰
  • Alcalinity of ash,灰的碱度
  • Magnesium,镁
  • Total phenols,总酚
  • Flavanoids,类黄酮
  • Nonflavanoid phenols,非黄酮酚
  • Proanthocyanins,原花青素
  • Color intensity,色彩强度
  • Hue,色调
  • OD280/OD315 of diluted wines,稀释酒的OD280/OD315
  • Proline,脯氨酸


  • 方式一,从 Wine 数据集官网下载 wine.data 文件。
  • 方式二,从华为云 OBS 中下载 wine.data 文件。
    | Key | Value | Key | Value |
    | — | — | — | — |
    | Data Set Characteristics: | Multivariate | Number of Instances: | 178 |
    | Attribute Characteristics: | Integer, Real | Number of Attributes: | 13 |
    | Associated Tasks: | Classification | Missing Values? | No |
  1. %%capture captured_output
  2. # 实验环境已经预装了 mindspore==2.2.14,如需更换 mindspore 版本,可更改下面 mindspore 的版本号
  3. !pip uninstall mindspore -y  # 卸载当前的 mindspore 版本
  4. !pip install -i https://pypi.mirrors.ustc.edu.cn/simple mindspore==2.2.14  # 从指定的镜像源安装指定版本的 mindspore
  5. # 查看当前 mindspore 版本
  6. !pip show mindspore  # 显示当前安装的 mindspore 包的信息
  7. from download import download  # 导入 download 函数用于下载文件
  8. # 下载红酒数据集
  9. url = "https://ascend-professional-construction-dataset.obs.cn-north-4.myhuaweicloud.com:443/MachineLearning/wine.zip"  
  10. path = download(url, "./", kind="zip", replace=True)  # 下载红酒数据集压缩文件
复制代码
剖析:

  • %%capture captured_output:这是一个 Jupyter Notebook 的邪术命令,用于捕获单位格的输出,防止输出在屏幕上显示。
  • !pip uninstall mindspore -y:使用 pip 命令卸载当前安装的 mindspore 包,-y 参数表示自动确认卸载,避免提示用户。
  • !pip install -i https://pypi.mirrors.ustc.edu.cn/simple mindspore==2.2.14:安装指定版本(2.2.14)的 mindspore 包,-i 后面跟的是安装源的地址,这里使用的是中国科学技术大学的 PyPI 镜像。
  • !pip show mindspore:该命令用于显示当前安装的 mindspore 包的详细信息,包括版本、位置等。
  • from download import download:导入 download 函数,假设该函数用于处理文件下载。
  • url = "https://ascend-professional-construction-dataset.obs.cn-north-4.myhuaweicloud.com:443/MachineLearning/wine.zip":界说一个变量 url,它包含了要下载的红酒数据集的链接。
  • path = download(url, "./", kind="zip", replace=True):调用 download 函数下载红酒数据集。参数阐明:

    • url: 要下载的文件的地址;
    • "./": 下载的目的路径,这里表示当前目录;
    • kind="zip": 指定下载文件的范例为 zip 格式;
    • replace=True: 如果目的路径已存在同名文件,是否更换,True 表示更换。

4.2 数据读取与处理

导入 MindSpore 模块和辅助模块

在生成数据之前,导入必要的 Python 库。
目前使用到 os 库,为方便理解,其他必要的库,我们在详细使用到时再阐明。
详细的 MindSpore 的模块阐明,可以在 MindSpore API 页面中搜刮查询。
可以通过 context.set_context 来配置运行必要的信息,比方运行模式、后端信息、硬件等信息。
导入 context 模块,配置运行必要的信息。
  1. %matplotlib inline
  2. # 使得在 Jupyter Notebook 中绘制的图形被嵌入在输出单元格中,而不是在新窗口中显示
  3. import os  # 导入 os 模块,用于与操作系统进行交互
  4. import csv  # 导入 csv 模块,用于处理 CSV 文件
  5. import numpy as np  # 导入 numpy,用于科学计算和数组操作
  6. import matplotlib.pyplot as plt  # 导入 matplotlib 的 pyplot 模块,用于绘制图形
  7. import mindspore as ms  # 导入 mindspore 库
  8. from mindspore import nn, ops  # 从 mindspore 中导入 nn(神经网络模块)和 ops(操作模块)
  9. ms.set_context(device_target="CPU")  # 设置 MindSpore 的运行环境为 CPU
复制代码
剖析:

  • %matplotlib inline:这是一个 Jupyter Notebook 的邪术命令,它使得生成的图形可以直接嵌入在 Notebook 的输出单位格中,而不是在新窗口中弹出。
  • import os:导入 os 模块,它提供了一些与操作系统交互的功能,比如文件和目录操作。
  • import csv:导入 csv 模块,用于读取和写入 CSV 格式的数据文件。
  • import numpy as np:导入 numpy 库,并将其简写为 np,它是用于数组计算和科学计算的基础库。
  • import matplotlib.pyplot as plt:导入 matplotlib.pyplot 模块,并简写为 plt,该模块提供了绘制图形的功能。
  • import mindspore as ms:导入 mindspore 库,并将其简写为 ms,它是华为开发的深度学习框架。
  • from mindspore import nn, ops:从 mindspore 库中导着迷经网络模块 nn 和操作模块 ops,这两个模块包含了构建深度学习模子和实行各种运算的工具。
  • ms.set_context(device_target="CPU"):设置 MindSpore 的上下文环境,指定计算装备为 CPU。这意味着接下来的计算将在 CPU 上举行,而不是使用 GPU 或其他计算装备。
读取 Wine 数据集 wine.data,并查看部分数据。

  1. with open('wine.data') as csv_file:
  2.     # 以默认模式(只读)打开名为 'wine.data' 的 CSV 文件
  3.     data = list(csv.reader(csv_file, delimiter=','))  
  4.     # 使用 csv.reader 读取文件内容,并将其转换为列表
  5.     # delimiter=',' 指定 CSV 文件的分隔符为逗号
  6. print(data[56:62] + data[130:133])  
  7. # 打印数据列表中第 57 到 62 行(不包括第 62 行)以及第 131 到 133 行(不包括第 133 行)的内容
复制代码
剖析:

  • with open('wine.data') as csv_file::以上下文管理器的方式打开名为 wine.data 的文件。这种方式确保文件在处理完成后可以或许自动关闭。
  • data = list(csv.reader(csv_file, delimiter=',')):

    • csv.reader(csv_file, delimiter=','):使用 csv 模块的 reader 函数读取打开的文件 csv_file,并指定分隔符为逗号(,),这实用于 CSV 格式的文件。
    • list(...):将读取的结果转换为一个列表,data 变量将存储该列表,列表的每个元素都是一个表示 CSV 行的列表。

  • print(data[56:62] + data[130:133]):

    • data[56:62]:切片操作,获取 data 列表中索引为 56 到 61 的行(共 6 行)。
    • data[130:133]:切片操作,获取 data 列表中索引为 130 到 132 的行(共 3 行)。
    • +:将这两个切片结果归并为一个新列表,并打印输出。

取三类样本(共 178 条),将数据集的 13 个属性作为自变量 (X)。将数据集的 3 个类别作为因变量 (Y)。

  1. X = np.array([[float(x) for x in s[1:]] for s in data[:178]], np.float32)
  2. # 创建一个二维 numpy 数组 X,包含前 178 行数据的特征部分
  3. # 使用列表推导式,将每行数据中的第 1 个元素到最后一个元素转换为 float 类型
  4. # np.float32 指定数组的数据类型为 32 位浮点数
  5. Y = np.array([s[0] for s in data[:178]], np.int32)
  6. # 创建一维 numpy 数组 Y,包含前 178 行数据的标签部分
  7. # 使用列表推导式,提取每行数据的第 0 个元素(标签)并转换为 int 类型
  8. # np.int32 指定数组的数据类型为 32 位整数
复制代码
剖析:

  • X = np.array([[float(x) for x in s[1:]] for s in data[:178]], np.float32):

    • 这行代码使用嵌套列表推导式,起首对 data[:178] 切片举行操作,提取前 178 行的数据。
    • for s in data[:178]:遍历前 178 行的数据,s 是每一行的内容。
    • [float(x) for x in s[1:]]:对于每一行 s,提取从索引 1 开始到行末的全部元素,将其转换为浮点数(float)。
    • np.array(..., np.float32):将生成的二维列表转换为 NumPy 数组,并指定命据范例为 32 位浮点数(np.float32)。

  • Y = np.array([s[0] for s in data[:178]], np.int32):

    • 这行代码使用列表推导式提取前 178 行数据的标签部分。
    • [s[0] for s in data[:178]]:遍历前 178 行数据,提取每行的第 0 个元素(通常为标签或目的值)。
    • np.array(..., np.int32):将生成的一维列表转换为 NumPy 数组,并指定命据范例为 32 位整数(np.int32)。

取样本的某两个属性举行 2 维可视化,可以看到在某两个属性上样本的分布情况以及可分性。

  1. attrs = ['Alcohol', 'Malic acid', 'Ash', 'Alcalinity of ash', 'Magnesium', 'Total phenols',
  2.          'Flavanoids', 'Nonflavanoid phenols', 'Proanthocyanins', 'Color intensity', 'Hue',
  3.          'OD280/OD315 of diluted wines', 'Proline']
  4. # 定义一个列表 attrs,包含不同的葡萄酒属性名称
  5. plt.figure(figsize=(10, 8))
  6. # 创建一个新的图形,设定图形的大小为 10x8 英寸
  7. for i in range(0, 4):
  8.     # 循环从 0 到 3,生成 4 个子图
  9.     plt.subplot(2, 2, i+1)
  10.     # 创建一个 2 行 2 列的子图,并选择第 i+1 个子图进行绘制
  11.    
  12.     a1, a2 = 2 * i, 2 * i + 1
  13.     # 计算当前子图中要绘制的两个属性的索引 a1 和 a2
  14.    
  15.     plt.scatter(X[:59, a1], X[:59, a2], label='1')
  16.     # 绘制前 59 个样本的属性 a1 和 a2 的散点图,标签为 '1'
  17.    
  18.     plt.scatter(X[59:130, a1], X[59:130, a2], label='2')
  19.     # 绘制第 60 到 130 个样本的属性 a1 和 a2 的散点图,标签为 '2'
  20.    
  21.     plt.scatter(X[130:, a1], X[130:, a2], label='3')
  22.     # 绘制第 131 个样本到最后的样本的属性 a1 和 a2 的散点图,标签为 '3'
  23.    
  24.     plt.xlabel(attrs[a1])
  25.     # 设置 x 轴标签为对应属性的名称
  26.    
  27.     plt.ylabel(attrs[a2])
  28.     # 设置 y 轴标签为对应属性的名称
  29.    
  30.     plt.legend()
  31.     # 添加图例,以显示不同类别的样本标签
  32. plt.show()
  33. # 显示绘制的图形
复制代码
剖析:

  • attrs = [...]:界说了一个包含葡萄酒特性名称的列表,这些特性将用于绘制图形的坐标轴标签。
  • plt.figure(figsize=(10, 8)):使用 Matplotlib 创建一个新图形,并设定其巨细为 10x8 英寸。
  • for i in range(0, 4)::循环 4 次(i 从 0 到 3),用于创建 4 个子图。
  • plt.subplot(2, 2, i+1):在 2 行 2 列的图形结构中选择第 i+1 个子图。
  • a1, a2 = 2 * i, 2 * i + 1:计算要在当前子图中绘制的两个特性的索引。每个子图显示两个特性的散点图。
  • plt.scatter(...):绘制散点图:

    • X[:59, a1] 和 X[:59, a2]:表示前 59 个样本的第 a1 和 a2 列作为 x 和 y 轴的数据。
    • X[59:130, a1] 和 X[59:130, a2]:表示第 60 到 130 个样本的数据。
    • X[130:, a1] 和 X[130:, a2]:表示第 131 个样本到最后的样本的数据。

  • plt.xlabel(attrs[a1]) 和 plt.ylabel(attrs[a2]):设置 x 轴和 y 轴的标签,显示对应的属性名称。
  • plt.legend():添加图例,表示每个类别的样本。
  • plt.show():显示终极绘制的图形。
将数据集按 128:50 分别为训练集(已知类别样本)和验证集(待验证样本):

  1. train_idx = np.random.choice(178, 128, replace=False)
  2. # 随机选择 128 个不重复的索引从 0 到 177(共 178 个样本),用于训练集
  3. # np.random.choice 的参数为样本总数、选择的数量和是否允许重复选择
  4. test_idx = np.array(list(set(range(178)) - set(train_idx)))
  5. # 创建测试集的索引
  6. # set(range(178)) 生成一个包含 0 到 177 的集合
  7. # set(train_idx) 生成训练集索引的集合
  8. # 通过集合的差集操作得到未被选择的索引,转化为 NumPy 数组
  9. X_train, Y_train = X[train_idx], Y[train_idx]
  10. # 根据训练集索引 train_idx 提取训练数据 X 和标签 Y 的相应部分
  11. X_test, Y_test = X[test_idx], Y[test_idx]
  12. # 根据测试集索引 test_idx 提取测试数据 X 和标签 Y 的相应部分
复制代码
剖析:

  • train_idx = np.random.choice(178, 128, replace=False):

    • 使用 np.random.choice 从 0 到 177 的范围内随机选择 128 个索引。
    • replace=False 表示不允许重复选择,即每个索引只能选择一次。

  • test_idx = np.array(list(set(range(178)) - set(train_idx))):

    • set(range(178)) 创建一个包含 0 到 177 的集合。
    • set(train_idx) 创建一个包含训练集索引的集合。
    • 通过集合的差集操作 - 得到未被选择的索引。
    • 最后将结果转换为 NumPy 数组,存储为 test_idx。

  • X_train, Y_train = X[train_idx], Y[train_idx]:

    • 根据 train_idx 提取训练集的特性数据 X 和对应的标签 Y。
    • X[train_idx] 获取训练样本的特性数据,Y[train_idx] 获取训练样本的标签。

  • X_test, Y_test = X[test_idx], Y[test_idx]:

    • 根据 test_idx 提取测试集的特性数据 X 和对应的标签 Y。
    • X[test_idx] 获取测试样本的特性数据,Y[test_idx] 获取测试样本的标签。

5、模子构建–计算距离

利用 MindSpore 提供的 tile, square, ReduceSum, sqrt, TopK 等算子,通过矩阵运算的方式同时计算输入样本 x 和已明白分类的其他样本 X_train 的距离,并计算出 top k 近邻。
  1. class KnnNet(nn.Cell):
  2.     def __init__(self, k):
  3.         super(KnnNet, self).__init__()
  4.         self.k = k
  5.         # 初始化 KNN 网络,k 表示最近邻的数量
  6.     def construct(self, x, X_train):
  7.         # 平铺输入 x 以匹配 X_train 中的样本数
  8.         x_tile = ops.tile(x, (128, 1))
  9.         # 使用 ops.tile 将输入 x 复制 128 次,以便与训练样本 X_train 的形状匹配
  10.         
  11.         square_diff = ops.square(x_tile - X_train)
  12.         # 计算 x_tile 和 X_train 之间的平方差
  13.         
  14.         square_dist = ops.sum(square_diff, 1)
  15.         # 对每一行的平方差求和,以得到每个样本的平方距离
  16.         
  17.         dist = ops.sqrt(square_dist)
  18.         # 计算每个样本的欧几里得距离
  19.         
  20.         # -dist 表示值越大,样本就越接近
  21.         values, indices = ops.topk(-dist, self.k)
  22.         # 获取距离最近的 k 个样本的索引,-dist 确保距离越小的样本排在前面
  23.         
  24.         return indices
  25.         # 返回 k 个最近邻的索引
  26. def knn(knn_net, x, X_train, Y_train):
  27.     x, X_train = ms.Tensor(x), ms.Tensor(X_train)
  28.     # 将输入 x 和训练样本 X_train 转换为 Tensor 类型,适合后续计算
  29.    
  30.     indices = knn_net(x, X_train)
  31.     # 使用 knn_net 模型对输入 x 和训练样本 X_train 进行预测,获取最近邻的索引
  32.    
  33.     topk_cls = [0] * len(indices.asnumpy())
  34.     # 初始化一个计数器列表,用于记录每个类的出现次数
  35.     for idx in indices.asnumpy():
  36.         topk_cls[Y_train[idx]] += 1
  37.         # 根据最近邻的索引,增加对应类在 topk_cls 中的计数
  38.    
  39.     cls = np.argmax(topk_cls)
  40.     # 找到计数最多的类作为最终的预测结果
  41.    
  42.     return cls
  43.     # 返回预测的类标签
复制代码
剖析:

  • KnnNet 类

    • class KnnNet(nn.Cell)::界说一个 KNN 网络类,继承自 nn.Cell。
    • def __init__(self, k)::构造函数,初始化 KNN 中的 k 值。
    • self.k = k:生存 k 的值。

  • construct 方法

    • def construct(self, x, X_train)::界说前向传播的方法,接收输入 x 和训练数据 X_train。
    • x_tile = ops.tile(x, (128, 1)):对输入样本 x 举行平铺,以与 X_train 的样本数匹配。
    • square_diff = ops.square(x_tile - X_train):计算 x 和每个训练样本之间的平方差。
    • square_dist = ops.sum(square_diff, 1):计算每个样本的平方距离。
    • dist = ops.sqrt(square_dist):计算每个样本的欧几里得距离。
    • values, indices = ops.topk(-dist, self.k):获取距离最近的 k 个样本的索引(使用负值确保较小的距离优先)。

  • knn 函数

    • def knn(knn_net, x, X_train, Y_train)::界说 KNN 函数,实行推测。
    • x, X_train = ms.Tensor(x), ms.Tensor(X_train):将输入数据转换为适合计算的 Tensor 格式。
    • indices = knn_net(x, X_train):调用 KNN 网络举行推测,获取最近邻的索引。
    • topk_cls = [0] * len(indices.asnumpy()):初始化一个计数器列表,记录最近邻的类别。
    • for idx in indices.asnumpy()::遍历最近邻索引,更新计数器。
    • cls = np.argmax(topk_cls):找到出现次数最多的类别作为推测结果。
    • return cls:返回终极的推测类别。

6、模子推测

在验证集上验证 KNN 算法的有效性,取 (k = 5),验证精度接近 80%,阐明 KNN 算法在该 3 分类任务上有效,能根据酒的 13 种属性判断出酒的品种。
  1. acc = 0
  2. # 初始化准确率计数器 acc 为 0
  3. knn_net = KnnNet(5)
  4. # 创建一个 KNN 网络实例,指定最近邻数量 k 为 5
  5. for x, y in zip(X_test, Y_test):
  6.     # 遍历测试集中的每个样本 x 和其对应的标签 y
  7.     pred = knn(knn_net, x, X_train, Y_train)
  8.     # 使用 knn 函数进行预测,得到预测结果 pred
  9.    
  10.     acc += (pred == y)
  11.     # 如果预测结果 pred 与真实标签 y 相同,则 acc 加 1
  12.    
  13.     print('label: %d, prediction: %s' % (y, pred))
  14.     # 打印每个样本的真实标签和预测结果
  15. print('Validation accuracy is %f' % (acc / len(Y_test)))
  16. # 计算并打印验证集的准确率,准确率为正确预测的数量除以测试样本总数
复制代码
剖析:

  • 初始化准确率计数器

    • acc = 0:初始化一个变量 acc 作为正确推测的数量计数器,初始值为 0。

  • 创建 KNN 网络实例

    • knn_net = KnnNet(5):实例化 KnnNet 类,设置最近邻数 k 为 5。

  • 遍历测试集

    • for x, y in zip(X_test, Y_test)::将测试数据 X_test 和对应的标签 Y_test 举行配对,逐一遍历。
    • pred = knn(knn_net, x, X_train, Y_train):调用 knn 函数举行推测,传入当前测试样本 x 和训练数据,得到推测结果 pred。

  • 更新准确率计数器

    • acc += (pred == y):查抄推测结果 pred 是否等于真实标签 y,如果相称则将 acc 加 1,表示正确推测。

  • 打印每个样本的结果

    • print('label: %d, prediction: %s' % (y, pred)):输出每个测试样本的真实标签和推测结果,以便观察模子性能。

  • 计算并打印验证集的准确率

    • print('Validation accuracy is %f' % (acc / len(Y_test))):计算验证集的准确率,将正确推测的数量 acc 除以测试样本总数 len(Y_test),并格式化输出。

实验小结

本实验使用 MindSpore 实现了 KNN 算法,用来办理 3 分类题目。取 wine 数据集上的 3 类样本,分为已知类别样本和待验证样本,从验证结果可以看出 KNN 算法在该任务上有效,能根据酒的 13 种属性判断出酒的品种。
整体代码

  1. # K近邻算法实现红酒聚类
  2. # 本实验主要介绍使用MindSpore在部分wine数据集上进行KNN实验。
  3. ## 1、实验目的
  4. # - 了解KNN的基本概念;
  5. # - 了解如何使用MindSpore进行KNN实验。
  6. ## 2、K近邻算法原理介绍
  7. # K近邻算法(K-Nearest-Neighbor, KNN)是一种用于分类和回归的非参数统计方法,最初由 Cover和Hart于1968年提出。
  8. # 它正是基于以上思想:要确定一个样本的类别,可以计算它与所有训练样本的距离,然后找出和该样本最接近的k个样本,
  9. # 统计出这些样本的类别并进行投票,票数最多的那个类就是分类的结果。
  10. # KNN的三个基本要素:
  11. # - K值,一个样本的分类是由K个邻居的“多数表决”确定的。
  12. # - 距离度量,反映了特征空间中两个样本间的相似度。
  13. # - 分类决策规则,通常是多数表决,或者基于距离加权的多数表决。
  14. ### 2.1 分类问题
  15. # 预测算法(分类)的流程如下:
  16. # (1)在训练样本集中找出距离待测样本x_test最近的k个样本,并保存至集合N中;
  17. # (2)统计集合N中每一类样本的个数C_{i}, i=1,2,3,...,c;
  18. # (3)最终的分类结果为argmaxC_{i} (最大的对应的C_{i})那个类。
  19. ### 2.2 回归问题
  20. # 假设离测试样本最近的k个训练样本的标签值为y_{i},则对样本的回归预测输出值为:
  21. # $\hat y = (\sum_{i=1}^{n}{y_{i}})/k$
  22. ### 2.3 距离的定义
  23. # KNN算法的实现依赖于样本之间的距离,其中最常用的距离函数就是欧氏距离。
  24. ## 3、实验环境
  25. # 实验环境:
  26. # - MindSpore 2.0;
  27. # - 支持win_x86和Linux系统,CPU/GPU/Ascend均可运行。
  28. ## 4、数据处理
  29. ### 4.1 数据准备
  30. # Wine数据集是模式识别最著名的数据集之一,分析了三种葡萄酒中每种所含13种成分的量。
  31. # 方式一,从Wine数据集官网下载[wine.data文件](http://archive.ics.uci.edu/ml/machine-learning-databases/wine/wine.data)。
  32. # 实验环境已经预装了mindspore==2.2.14。
  33. !pip uninstall mindspore -y
  34. !pip install -i https://pypi.mirrors.ustc.edu.cn/simple mindspore==2.2.14
  35. # 查看当前 mindspore 版本
  36. !pip show mindspore
  37. from download import download
  38. # 下载红酒数据集
  39. url = "https://ascend-professional-construction-dataset.obs.cn-north-4.myhuaweicloud.com:443/MachineLearning/wine.zip"  
  40. path = download(url, "./", kind="zip", replace=True)
  41. ### 4.2 数据读取与处理
  42. import os
  43. import csv
  44. import numpy as np
  45. import matplotlib.pyplot as plt
  46. import mindspore as ms
  47. from mindspore import nn, ops
  48. ms.set_context(device_target="CPU")
  49. # 读取Wine数据集`wine.data`
  50. with open('wine.data') as csv_file:
  51.     data = list(csv.reader(csv_file, delimiter=','))
  52. print(data[56:62]+data[130:133])
  53. # 取三类样本(共178条),将数据集的13个属性作为自变量X。将数据集的3个类别作为因变量Y。
  54. X = np.array([[float(x) for x in s[1:]] for s in data[:178]], np.float32)
  55. Y = np.array([s[0] for s in data[:178]], np.int32)
  56. # 取样本的某两个属性进行2维可视化
  57. attrs = ['Alcohol', 'Malic acid', 'Ash', 'Alcalinity of ash', 'Magnesium', 'Total phenols',
  58.          'Flavanoids', 'Nonflavanoid phenols', 'Proanthocyanins', 'Color intensity', 'Hue',
  59.          'OD280/OD315 of diluted wines', 'Proline']
  60. plt.figure(figsize=(10, 8))
  61. for i in range(0, 4):
  62.     plt.subplot(2, 2, i+1)
  63.     a1, a2 = 2 * i, 2 * i + 1
  64.     plt.scatter(X[:59, a1], X[:59, a2], label='1')
  65.     plt.scatter(X[59:130, a1], X[59:130, a2], label='2')
  66.     plt.scatter(X[130:, a1], X[130:, a2], label='3')
  67.     plt.xlabel(attrs[a1])
  68.     plt.ylabel(attrs[a2])
  69.     plt.legend()
  70. plt.show()
  71. # 将数据集按128:50划分为训练集和验证集
  72. train_idx = np.random.choice(178, 128, replace=False)
  73. test_idx = np.array(list(set(range(178)) - set(train_idx)))
  74. X_train, Y_train = X[train_idx], Y[train_idx]
  75. X_test, Y_test = X[test_idx], Y[test_idx]
  76. ## 5、模型构建
  77. class KnnNet(nn.Cell):
  78.     def __init__(self, k):
  79.         super(KnnNet, self).__init__()
  80.         self.k = k
  81.     def construct(self, x, X_train):
  82.         # 平铺输入x以匹配X_train中的样本数
  83.         x_tile = ops.tile(x, (128, 1))
  84.         square_diff = ops.square(x_tile - X_train)
  85.         square_dist = ops.sum(square_diff, 1)
  86.         dist = ops.sqrt(square_dist)
  87.         # -dist表示值越大,样本就越接近
  88.         values, indices = ops.topk(-dist, self.k)
  89.         return indices
  90. def knn(knn_net, x, X_train, Y_train):
  91.     x, X_train = ms.Tensor(x), ms.Tensor(X_train)
  92.     indices = knn_net(x, X_train)
  93.     topk_cls = [0]*len(indices.asnumpy())
  94.     for idx in indices.asnumpy():
  95.         topk_cls[Y_train[idx]] += 1
  96.     cls = np.argmax(topk_cls)
  97.     return cls
  98. ## 6、模型预测
  99. acc = 0
  100. knn_net = KnnNet(5)
  101. for x, y in zip(X_test, Y_test):
  102.     pred = knn(knn_net, x, X_train, Y_train)
  103.     acc += (pred == y)
  104.     print('label: %d, prediction: %s' % (y, pred))
  105. print('Validation accuracy is %f' % (acc/len(Y_test)))
  106. ## 实验小结
  107. # 本实验使用MindSpore实现了KNN算法,用来解决3分类问题。
复制代码
剖析:


  • 实验目的

    • 学习 KNN 的基本概念和使用 MindSpore 实现 KNN 的方法。

  • KNN 原理

    • KNN 是一种基于距离的分类和回归算法,通过计算样本距离来判断样本的类别或输出值。

  • 数据处理

    • 下载和读取 Wine 数据集,并将数据分为特性和标签(X 和 Y)。
    • 可视化数据集中的样本分布。

  • 模子构建

    • 界说 KNN 网络类 KnnNet,实现距离计算和最近邻索引获取。
    • 界说 knn 函数举行推测,包括分类计数和返回终极的推测结果。

  • 模子推测

    • 在验证集上测试模子的准确性,输出每个样本的真实标签和推测结果,最后计算整体准确率。

  • 实验小结

    • 通过实验验证 KNN 算法在 Wine 数据集分类任务上的有效性。


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

嚴華

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表