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

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 分类问题

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

  1. 在训练样本集中找出距离待测样本 x_test 最近的 k 个样本,并保存至集合 N 中;
  2. 统计集合 N 中每一类样本的个数 (C_{i}, i=1,2,3,…,c);
  3. 最终的分类结果为 ( \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 种属性是:

  1. Alcohol,酒精
  2. Malic acid,苹果酸
  3. Ash,灰
  4. Alcalinity of ash,灰的碱度
  5. Magnesium,镁
  6. Total phenols,总酚
  7. Flavanoids,类黄酮
  8. Nonflavanoid phenols,非黄酮酚
  9. Proanthocyanins,原花青素
  10. Color intensity,色彩强度
  11. Hue,色调
  12. OD280/OD315 of diluted wines,稀释酒的OD280/OD315
  13. 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 |
%%capture captured_output
# 实验环境已经预装了 mindspore==2.2.14,如需更换 mindspore 版本,可更改下面 mindspore 的版本号
!pip uninstall mindspore -y  # 卸载当前的 mindspore 版本
!pip install -i https://pypi.mirrors.ustc.edu.cn/simple mindspore==2.2.14  # 从指定的镜像源安装指定版本的 mindspore
# 查看当前 mindspore 版本
!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"  
path = download(url, "./", kind="zip", replace=True)  # 下载红酒数据集压缩文件

解析:

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

%matplotlib inline
# 使得在 Jupyter Notebook 中绘制的图形被嵌入在输出单元格中,而不是在新窗口中显示import os  # 导入 os 模块,用于与操作系统进行交互
import csv  # 导入 csv 模块,用于处理 CSV 文件
import numpy as np  # 导入 numpy,用于科学计算和数组操作
import matplotlib.pyplot as plt  # 导入 matplotlib 的 pyplot 模块,用于绘制图形import mindspore as ms  # 导入 mindspore 库
from mindspore import nn, ops  # 从 mindspore 中导入 nn(神经网络模块)和 ops(操作模块)ms.set_context(device_target="CPU")  # 设置 MindSpore 的运行环境为 CPU

解析:

  1. %matplotlib inline:这是一个 Jupyter Notebook 的魔法命令,它使得生成的图形可以直接嵌入在 Notebook 的输出单元格中,而不是在新窗口中弹出。
  2. import os:导入 os 模块,它提供了一些与操作系统交互的功能,比如文件和目录操作。
  3. import csv:导入 csv 模块,用于读取和写入 CSV 格式的数据文件。
  4. import numpy as np:导入 numpy 库,并将其简写为 np,它是用于数组计算和科学计算的基础库。
  5. import matplotlib.pyplot as plt:导入 matplotlib.pyplot 模块,并简写为 plt,该模块提供了绘制图形的功能。
  6. import mindspore as ms:导入 mindspore 库,并将其简写为 ms,它是华为开发的深度学习框架。
  7. from mindspore import nn, ops:从 mindspore 库中导入神经网络模块 nn 和操作模块 ops,这两个模块包含了构建深度学习模型和执行各种运算的工具。
  8. ms.set_context(device_target="CPU"):设置 MindSpore 的上下文环境,指定计算设备为 CPU。这意味着接下来的计算将在 CPU 上进行,而不是使用 GPU 或其他计算设备。
读取 Wine 数据集 wine.data,并查看部分数据。
with open('wine.data') as csv_file:# 以默认模式(只读)打开名为 'wine.data' 的 CSV 文件data = list(csv.reader(csv_file, delimiter=','))  # 使用 csv.reader 读取文件内容,并将其转换为列表# delimiter=',' 指定 CSV 文件的分隔符为逗号print(data[56:62] + data[130:133])  
# 打印数据列表中第 57 到 62 行(不包括第 62 行)以及第 131 到 133 行(不包括第 133 行)的内容

解析:

  1. with open('wine.data') as csv_file::以上下文管理器的方式打开名为 wine.data 的文件。这种方式确保文件在处理完成后能够自动关闭。
  2. data = list(csv.reader(csv_file, delimiter=','))
    • csv.reader(csv_file, delimiter=','):使用 csv 模块的 reader 函数读取打开的文件 csv_file,并指定分隔符为逗号(,),这适用于 CSV 格式的文件。
    • list(...):将读取的结果转换为一个列表,data 变量将存储该列表,列表的每个元素都是一个表示 CSV 行的列表。
  3. 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)。
X = np.array([[float(x) for x in s[1:]] for s in data[:178]], np.float32)
# 创建一个二维 numpy 数组 X,包含前 178 行数据的特征部分
# 使用列表推导式,将每行数据中的第 1 个元素到最后一个元素转换为 float 类型
# np.float32 指定数组的数据类型为 32 位浮点数Y = np.array([s[0] for s in data[:178]], np.int32)
# 创建一维 numpy 数组 Y,包含前 178 行数据的标签部分
# 使用列表推导式,提取每行数据的第 0 个元素(标签)并转换为 int 类型
# np.int32 指定数组的数据类型为 32 位整数

解析:

  1. 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)。
  2. 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 维可视化,可以看到在某两个属性上样本的分布情况以及可分性。
attrs = ['Alcohol', 'Malic acid', 'Ash', 'Alcalinity of ash', 'Magnesium', 'Total phenols','Flavanoids', 'Nonflavanoid phenols', 'Proanthocyanins', 'Color intensity', 'Hue','OD280/OD315 of diluted wines', 'Proline']
# 定义一个列表 attrs,包含不同的葡萄酒属性名称plt.figure(figsize=(10, 8))
# 创建一个新的图形,设定图形的大小为 10x8 英寸for i in range(0, 4):# 循环从 0 到 3,生成 4 个子图plt.subplot(2, 2, i+1)# 创建一个 2 行 2 列的子图,并选择第 i+1 个子图进行绘制a1, a2 = 2 * i, 2 * i + 1# 计算当前子图中要绘制的两个属性的索引 a1 和 a2plt.scatter(X[:59, a1], X[:59, a2], label='1')# 绘制前 59 个样本的属性 a1 和 a2 的散点图,标签为 '1'plt.scatter(X[59:130, a1], X[59:130, a2], label='2')# 绘制第 60 到 130 个样本的属性 a1 和 a2 的散点图,标签为 '2'plt.scatter(X[130:, a1], X[130:, a2], label='3')# 绘制第 131 个样本到最后的样本的属性 a1 和 a2 的散点图,标签为 '3'plt.xlabel(attrs[a1])# 设置 x 轴标签为对应属性的名称plt.ylabel(attrs[a2])# 设置 y 轴标签为对应属性的名称plt.legend()# 添加图例,以显示不同类别的样本标签plt.show()
# 显示绘制的图形

解析:

  1. attrs = [...]:定义了一个包含葡萄酒特征名称的列表,这些特征将用于绘制图形的坐标轴标签。
  2. plt.figure(figsize=(10, 8)):使用 Matplotlib 创建一个新图形,并设定其大小为 10x8 英寸。
  3. for i in range(0, 4)::循环 4 次(i 从 0 到 3),用于创建 4 个子图。
  4. plt.subplot(2, 2, i+1):在 2 行 2 列的图形布局中选择第 i+1 个子图。
  5. a1, a2 = 2 * i, 2 * i + 1:计算要在当前子图中绘制的两个特征的索引。每个子图显示两个特征的散点图。
  6. plt.scatter(...):绘制散点图:
    • X[:59, a1]X[:59, a2]:表示前 59 个样本的第 a1a2 列作为 x 和 y 轴的数据。
    • X[59:130, a1]X[59:130, a2]:表示第 60 到 130 个样本的数据。
    • X[130:, a1]X[130:, a2]:表示第 131 个样本到最后的样本的数据。
  7. plt.xlabel(attrs[a1])plt.ylabel(attrs[a2]):设置 x 轴和 y 轴的标签,显示对应的属性名称。
  8. plt.legend():添加图例,表示每个类别的样本。
  9. plt.show():显示最终绘制的图形。
将数据集按 128:50 划分为训练集(已知类别样本)和验证集(待验证样本):
train_idx = np.random.choice(178, 128, replace=False)
# 随机选择 128 个不重复的索引从 0 到 177(共 178 个样本),用于训练集
# np.random.choice 的参数为样本总数、选择的数量和是否允许重复选择test_idx = np.array(list(set(range(178)) - set(train_idx)))
# 创建测试集的索引
# set(range(178)) 生成一个包含 0 到 177 的集合
# set(train_idx) 生成训练集索引的集合
# 通过集合的差集操作得到未被选择的索引,转化为 NumPy 数组X_train, Y_train = X[train_idx], Y[train_idx]
# 根据训练集索引 train_idx 提取训练数据 X 和标签 Y 的相应部分X_test, Y_test = X[test_idx], Y[test_idx]
# 根据测试集索引 test_idx 提取测试数据 X 和标签 Y 的相应部分

解析:

  1. train_idx = np.random.choice(178, 128, replace=False)
    • 使用 np.random.choice 从 0 到 177 的范围内随机选择 128 个索引。
    • replace=False 表示不允许重复选择,即每个索引只能选择一次。
  2. test_idx = np.array(list(set(range(178)) - set(train_idx)))
    • set(range(178)) 创建一个包含 0 到 177 的集合。
    • set(train_idx) 创建一个包含训练集索引的集合。
    • 通过集合的差集操作 - 得到未被选择的索引。
    • 最后将结果转换为 NumPy 数组,存储为 test_idx
  3. X_train, Y_train = X[train_idx], Y[train_idx]
    • 根据 train_idx 提取训练集的特征数据 X 和对应的标签 Y
    • X[train_idx] 获取训练样本的特征数据,Y[train_idx] 获取训练样本的标签。
  4. 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 近邻。

class KnnNet(nn.Cell):def __init__(self, k):super(KnnNet, self).__init__()self.k = k# 初始化 KNN 网络,k 表示最近邻的数量def construct(self, x, X_train):# 平铺输入 x 以匹配 X_train 中的样本数x_tile = ops.tile(x, (128, 1))# 使用 ops.tile 将输入 x 复制 128 次,以便与训练样本 X_train 的形状匹配square_diff = ops.square(x_tile - X_train)# 计算 x_tile 和 X_train 之间的平方差square_dist = ops.sum(square_diff, 1)# 对每一行的平方差求和,以得到每个样本的平方距离dist = ops.sqrt(square_dist)# 计算每个样本的欧几里得距离# -dist 表示值越大,样本就越接近values, indices = ops.topk(-dist, self.k)# 获取距离最近的 k 个样本的索引,-dist 确保距离越小的样本排在前面return indices# 返回 k 个最近邻的索引def knn(knn_net, x, X_train, Y_train):x, X_train = ms.Tensor(x), ms.Tensor(X_train)# 将输入 x 和训练样本 X_train 转换为 Tensor 类型,适合后续计算indices = knn_net(x, X_train)# 使用 knn_net 模型对输入 x 和训练样本 X_train 进行预测,获取最近邻的索引topk_cls = [0] * len(indices.asnumpy())# 初始化一个计数器列表,用于记录每个类的出现次数for idx in indices.asnumpy():topk_cls[Y_train[idx]] += 1# 根据最近邻的索引,增加对应类在 topk_cls 中的计数cls = np.argmax(topk_cls)# 找到计数最多的类作为最终的预测结果return cls# 返回预测的类标签

解析:

  1. KnnNet 类
    • class KnnNet(nn.Cell)::定义一个 KNN 网络类,继承自 nn.Cell
    • def __init__(self, k)::构造函数,初始化 KNN 中的 k 值。
    • self.k = k:保存 k 的值。
  2. 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 个样本的索引(使用负值确保较小的距离优先)。
  3. 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 种属性判断出酒的品种。

acc = 0
# 初始化准确率计数器 acc 为 0knn_net = KnnNet(5)
# 创建一个 KNN 网络实例,指定最近邻数量 k 为 5for x, y in zip(X_test, Y_test):# 遍历测试集中的每个样本 x 和其对应的标签 ypred = knn(knn_net, x, X_train, Y_train)# 使用 knn 函数进行预测,得到预测结果 predacc += (pred == y)# 如果预测结果 pred 与真实标签 y 相同,则 acc 加 1print('label: %d, prediction: %s' % (y, pred))# 打印每个样本的真实标签和预测结果print('Validation accuracy is %f' % (acc / len(Y_test)))
# 计算并打印验证集的准确率,准确率为正确预测的数量除以测试样本总数

解析:

  1. 初始化准确率计数器
    • acc = 0:初始化一个变量 acc 作为正确预测的数量计数器,初始值为 0。
  2. 创建 KNN 网络实例
    • knn_net = KnnNet(5):实例化 KnnNet 类,设置最近邻数 k 为 5。
  3. 遍历测试集
    • 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
  4. 更新准确率计数器
    • acc += (pred == y):检查预测结果 pred 是否等于真实标签 y,如果相等则将 acc 加 1,表示正确预测。
  5. 打印每个样本的结果
    • print('label: %d, prediction: %s' % (y, pred)):输出每个测试样本的真实标签和预测结果,以便观察模型性能。
  6. 计算并打印验证集的准确率
    • print('Validation accuracy is %f' % (acc / len(Y_test))):计算验证集的准确率,将正确预测的数量 acc 除以测试样本总数 len(Y_test),并格式化输出。

实验小结

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

整体代码

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

解析:

  1. 实验目的
    • 学习 KNN 的基本概念和使用 MindSpore 实现 KNN 的方法。
  2. KNN 原理
    • KNN 是一种基于距离的分类和回归算法,通过计算样本距离来判定样本的类别或输出值。
  3. 数据处理
    • 下载和读取 Wine 数据集,并将数据分为特征和标签(X 和 Y)。
    • 可视化数据集中的样本分布。
  4. 模型构建
    • 定义 KNN 网络类 KnnNet,实现距离计算和最近邻索引获取。
    • 定义 knn 函数进行预测,包括分类计数和返回最终的预测结果。
  5. 模型预测
    • 在验证集上测试模型的准确性,输出每个样本的真实标签和预测结果,最后计算整体准确率。
  6. 实验小结
    • 通过实验验证 KNN 算法在 Wine 数据集分类任务上的有效性。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/47976.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

立创梁山派--移植开源的SFUD万能的串行 Flash 通用驱动库

SFUD是什么 关于SFUD库的介绍,其开源链接(gitee,github)已经详细的阐述了. 这里是截取自它的一部分介绍: SFUD 是一款开源的串行 SPI Flash 通用驱动库。由于现有市面的串行 Flash 种类居多,各个 Flash 的规格及命令存在差异, SF…

一次搞定!中级软件设计师备考通关秘籍

大家好,我是小欧! 今天我们来聊聊软考这个话题。要是你准备参加计算机技术与软件专业技术资格(软考),那么这篇文章就是为你量身定做的。话不多说,咱们直接进入正题。 什么是软考? 软考&#xf…

请你谈谈:spring bean的生命周期 - 阶段4:检查Aware相关接口

在Spring框架中,Aware 接口系列提供了一种机制,允许bean在初始化过程中感知到容器中的特定对象,如应用上下文(ApplicationContext)、Bean工厂(BeanFactory)等。如果你有一个用户自定义的对象&am…

基于词级ngram的词袋模型对twitter数据进行情感分析

按照阿光的项目做出了学习笔记,pytorch深度学习实战项目100例 基于词级ngram的词袋模型对twitter数据进行情感分析 什么是 N 符? N 格是指给定文本或语音样本中 n 个项目的连续序列。这些项目可以是音素、音节、字母、单词或碱基对,具体取…

php 存储复杂的json格式查询(如:经纬度)

在开发中,有时我们可能存了一些复杂json格式不知道怎么查。我这里提供给大家参考下: 一、先上表数据格式(location字段的possiton经纬度以逗号分开的) {"title":"澳海文澜府","position":"11…

redis高可用之主从复制、哨兵以及Cluster集群

目录 一、Redis主从复制 1)主从复制的作用 2)主从复制流程 3)搭建Redis主从复制 1、部署redis服务器 2、修改Redis配置文件(所有节点操作) 3、验证主从复制结果 二、哨兵模式 1)哨兵的作用 2&…

北醒单点激光雷达更改id和波特率以及Ubuntu20.04下CAN驱动

序言: 需要的硬件以及软件 1、USB-CAN分析仪使用顶配pro版本,带有支持ubuntu下的驱动包的,可以读取数据。 2、电源自备24V电源 3、单点激光雷达接线使用can线可以组网。 一、更改北醒单点激光雷达的id号和波特率 安装并运行USB-CAN分析仪自带…

elasticsearch8.14.1集群安装部署

elasticsearch安装部署,首先需要准备至少三台服务器,本例再windows11下安装三台vmware虚拟机,利用centOS7系统模拟服务器环境。 本例假设你已经安装了三台vmware和centOS7,且centOS7运行正常。接下来我们直接讲解elasticsearch下载…

SQL实战宝典:快速上手数据库查询与优化

文章目录 SQL 速成手册SQL 的主要功能1、基本查询语句2、表操作语句3、数据操作语句4、函数与聚合操作5、子查询与联接6、高级操作7、性能优化与安全性 基本查询语句表操作语句数据操作语句函数与聚合操作子查询与联接高级操作性能优化与安全性 SQL 速成手册 SQL(S…

BUUCTF [WUSTCTF2020]朴实无华

首先进来不知道要干啥,上dirsearch扫出个机器人协议,一看有点东西 直接访问很明显这不是flag 主页面看他说什么不能修改头部,看一下数据包 发现了好东西 看到源码,又得绕过了。不过这编码有点问题导致乱码了 找个在线网站稍微恢复…

git代码备份

终端备份常用指令 git reflog //查看更新 git add filename //提交修改 git commit -m "20240825修改" //备注修改 git reset --hard 1094a //回退版本 exit …

【深入理解SpringCloud微服务】深入理解Eureka核心原理

深入理解Eureka核心原理 Eureka整体设计Eureka服务端启动Eureka三级缓存Eureka客户端启动 Eureka整体设计 Eureka是一个经典的注册中心,通过http接收客户端的服务发现和服务注册请求,使用内存注册表保存客户端注册上来的实例信息。 Eureka服务端接收的…

FPGA-ROM IP核的使用

1.理论 ROM全称:Read-Only Memory,也就是只读型固态半导体存储器,即一旦存储信息,无法再改变,信息也不会因为电源关闭消失。但在FPGA中,实际使用的ROM IP核并不是真正的ROM,其实都是内部的RAM资…

spring security如何适配盐存在数据库中的密码

19.token认证过滤器代码实现_哔哩哔哩_bilibili19.token认证过滤器代码实现是SpringSecurity框架教程-Spring SecurityJWT实现项目级前端分离认证授权-挑战黑马&尚硅谷的第20集视频,该合集共计41集,视频收藏或关注UP主,及时了解更多相关视…

24年支付行业概况与未来

​ 一、行业背景介绍 支付行业作为现代金融体系的基石,正经历着前所未有的变革。随着科技的发展和人们对便捷支付方式的需求不断提高,支付行业在近年来得到了迅猛发展。在我国,支付行业经过多年的发展和市场竞争,已经形成了多元化…

Navicat 17 新特性 | Navicat BI 功能革新升级,助力企业深度挖掘数据潜能

随着 Navicat 17 的发布,在业界引起了广泛的共鸣与热议。我们曾深入剖析其众多革新特性,包括模型设计创新与优化、高效的查询与配置、用户界面交互体验再升级,原生适配国产平台和操作系统和数据字典提升数据结构清晰度,这些新特性…

【第12章】Spring Cloud之集成 Spring Cloud Gateway

文章目录 前言一、新建项目1. 项目结构2. 引入依赖3. 启动类4. 基本配置 二、新建配置三、新建服务1. 提供者2. 消费者 四、单元测试1. 启动网关服务2. 提供者3. 消费者 总结 前言 Spring Cloud Gateway是一个基于Spring Framework 5、Spring Boot 2和Project Reactor等技术构…

python的csv库常用操作

csv 模块是 Python 标准库中的一个模块,用于处理 CSV(逗号分隔值)文件。它提供了简单易用的功能来读取和写入 CSV 文件。以下是一些常用的操作: 一、读取 CSV 文件 新建文件data.csv,内容如下: 使用 csv.…

浪潮自研交换机系列常见问题处理

CN61108PC-V-H 不能PING通任何地址,也不能被PING 输入ip traceroute enable既可。注意视图 交换机通过console口远程登录至其他交换机,掉线后console口无法使用 例如有2台交换机A和B,在A交换机上插上console线登录后,在A通过SSH…

nodejs安装及环境配置建材商城管理系统App

✌网站介绍:✌10年项目辅导经验、专注于计算机技术领域学生项目实战辅导。 ✌服务范围:Java(SpringBoo/SSM)、Python、PHP、Nodejs、爬虫、数据可视化、小程序、安卓app、大数据等设计与开发。 ✌服务内容:免费功能设计、免费提供开题答辩P…