昇思25天学习打卡营第21天|热门LLM及其他AI应用-K近邻算法实现红酒聚类
K近邻算法是机器学习的一个分支
- 新的数据点进行分类时,算法会找到离该数据点最近的K个数据点(即K个邻居),然后根据这些邻居的类别来决定新数据点的类别(投票方式,如果多数为类别2,这新数据点也会被判别为类别2)
- 所以K值的选择十分重要,一般会选择奇数(利于投票),也会遍历多个K值来计算损失,以此达到较高的准确率(但要小心过拟合)
- 邻居点的确定取决于距离的计算,一般会选择欧式距离(高中理解的两点距离),其他距离要根据实际用途进行选择
数据集准备
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)
数据处理
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)
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]
-
X
data[:178]
:假设data
是一个包含数据的列表或数组,这里取前178行数据。[[float(x) for x in s[1:]] for s in data[:178]]
:对于每一行数据中的每个元素(假设每行数据是一个列表或数组),将其转换为浮点数,并且忽略第一个元素(假设第一个元素是类别或标签)。np.float32
:指定生成的NumPy数组的数据类型为32位浮点数。 -
Y
[s[0] for s in data[:178]]
:对于每一行数据,取第一个元素,这通常是类别或标签。np.int32
:指定生成的NumPy数组的数据类型为32位整数 -
train_idx
np.random.choice(178, 128, replace=False)
:使用NumPy的随机选择函数np.random.choice
从范围为0到177(即总共178个数据点)中随机选择128个索引,且不允许替换(replace=False)。
模型构建-计算距离
class KnnNet(nn.Cell):
def __init__(self, k):
super(KnnNet, self).__init__()
self.k = k
#构建函数,接受输入x和训练集X_train作为参数
def construct(self, x, X_train):
x_tile = ops.tile(x, (128, 1)) # 平铺输入x以匹配X_train中的样本数
square_diff = ops.square(x_tile - X_train) # 计算平方差
square_dist = ops.sum(square_diff, 1) # 沿第二维度求和,得到平方距离
dist = ops.sqrt(square_dist) # 对平方距离进行开方,得到欧式距离
values, indices = ops.topk(-dist, self.k) # 获取距离最小的前k个样本的索引
return indices
def knn(knn_net, x, X_train, Y_train):
x, X_train = ms.Tensor(x), ms.Tensor(X_train) # 转换输入x和训练集X_train为MindSpore张量
indices = knn_net(x, X_train) # 使用KnnNet类进行预测,得到最近邻样本的索引
topk_cls = [0]*len(indices.asnumpy()) # 初始化一个列表,用于统计最近邻样本中每个类别的数量
for idx in indices.asnumpy():
topk_cls[Y_train[idx]] += 1 # 统计每个最近邻样本的类别数量
cls = np.argmax(topk_cls) # 找出数量最多的类别作为预测结果
return cls
预测
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)))