From 69846d9951fe32ae33ddfcfaffb4c1d7e438cd81 Mon Sep 17 00:00:00 2001 From: Xionghaoran <719929980@qq.com> Date: Wed, 23 Oct 2024 14:38:57 +0800 Subject: [PATCH] =?UTF-8?q?=E6=9B=B4=E6=96=B0=20function.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- function.py | 103 ++++++++++++++++++++++------------------------------ 1 file changed, 43 insertions(+), 60 deletions(-) diff --git a/function.py b/function.py index 3ec38b5..ccf495b 100644 --- a/function.py +++ b/function.py @@ -1,24 +1,47 @@ +# function.py import numpy as np import os -from sklearn.neighbors import KDTree """ 实验说明: - - 自行编写实现数据加载与 kNN 的手写数字分类算法。 - - 函数输入: 待分类的样本 input_vector, 训练数据集 dataSet, 训练集对应的标签 labels。 - - 函数返回: 预测的分类标签。 -请在这里填写学号和姓名,不填写即成绩无效。 +注意事项: +- 在 function.py 中实现 kNN 分类算法。 +- 可以自行导入其他库,需要在 requirements.txt 添加依赖,若未在 requirements.txt 中添加使用到的依赖,则无法自动评测,成绩为零。 +- 自动评测脚本仅会加载 classify 和 load_data 函数,请勿修改函数名。 +- 训练集和测试集需手动下载解压,并放入当前目录下。 + +测评环境: +- CPU: Intel Xeon(R) CPU E3-1231 v3 @ 3.40GHz +- OS: Ubuntu 22.04.4 LTS +- Python: 3.10.12 +- numpy: 2.1.1 """ + +""" +请在这里填写学号和姓名,不填写即成绩无效。 +""" id = "202210423213" name = "熊浩燃" -def classify(input_vector, dataSet, labels, k=1, distance_metric='euclidean', weighted=False): +""" +参数说明: +- input_vector (numpy array): 输入待分类的样本。 +- dataSet (numpy array): 训练数据集。 +- labels (list or numpy array): 训练集对应的标签。 +- k (int): kNN 算法参数,请**自行设置默认值**,评测时仅会使用其默认值,不修改默认值将**无法通过**评测,**成绩为零**。 +返回值: +- int: 预测的分类标签。 +""" + + +# 这里写自己的代码实现 +def classify(input_vector, dataSet, labels, k=1): """ KNN 分类算法。 @@ -26,61 +49,25 @@ def classify(input_vector, dataSet, labels, k=1, distance_metric='euclidean', we - input_vector (numpy array): 输入待分类的样本。 - dataSet (numpy array): 训练数据集。 - labels (list or numpy array): 训练集对应的标签。 - - k (int): kNN 算法参数,默认值为1。 - - distance_metric (str): 距离度量方式,支持'euclidean'和'manhattan'。 - - weighted (bool): 是否使用加权投票。 + - k (int): kNN 算法参数,请**自行设置默认值**,评测时仅会使用其默认值,不修改默认值将**无法通过**评测,**成绩为零**。 Returns: - int: 预测的分类标签。 """ - # 选择距离度量 - if distance_metric == 'euclidean': - distances = np.linalg.norm(dataSet - input_vector, axis=1) - elif distance_metric == 'manhattan': - distances = np.sum(np.abs(dataSet - input_vector), axis=1) - else: - raise ValueError(f"Unsupported distance metric: {distance_metric}") - + # 计算欧氏距离 + distances = np.linalg.norm(dataSet - input_vector, axis=1) # 获取距离最近的 k 个样本的索引 nearest_neighbors_indices = distances.argsort()[:k] # 获取这些样本的标签 nearest_labels = np.array(labels)[nearest_neighbors_indices] - - if weighted: - # 使用加权投票:距离越近,权重越大 - nearest_distances = distances[nearest_neighbors_indices] - weights = 1 / (nearest_distances + 1e-5) # 防止距离为0 - weighted_vote = np.bincount(nearest_labels, weights=weights) - predicted_label = weighted_vote.argmax() - else: - predicted_label = np.bincount(nearest_labels).argmax() - - return predicted_label - - -def classify_with_kdtree(input_vector, dataSet, labels, k=1): - """ - 使用 KD-tree 进行加速的 kNN 分类算法。 - - Args: - - input_vector (numpy array): 输入待分类的样本。 - - dataSet (numpy array): 训练数据集。 - - labels (list or numpy array): 训练集对应的标签。 - - k (int): kNN 算法参数,默认值为1。 - - Returns: - - int: 预测的分类标签。 - """ - tree = KDTree(dataSet) # 构建 KD-tree - dist, indices = tree.query(input_vector.reshape(1, -1), k=k) # 查询最近邻 - nearest_labels = np.array(labels)[indices[0]] + # 统计出现次数最多的标签并返回 predicted_label = np.bincount(nearest_labels).argmax() return predicted_label - +# 这里也写自己的代码实现 def load_dataset(directory): """ - 从文件夹中加载数据,若不自行正确实现,则无法通过评测,不记录成绩。 + 从文件夹中加载数据,若不自行正确实现,则无法通过评测,**不记录成绩**。 Args: - directory (str): 数据文件夹路径。 @@ -99,10 +86,12 @@ def load_dataset(directory): data_list.append(vector) return np.array(data_list), np.array(labels) - +# 这里还写自己的代码实现 def img_to_vector(filename): """ 将二值图像转换为向量。 + 该部分应为 load_dataset 函数的辅助子函数,可单独在这里实现,也可直接集成至 load_dataset 函数中。 + Args: - filename (str): 图像文件路径。 @@ -119,10 +108,9 @@ def img_to_vector(filename): if __name__ == "__main__": - # 加载训练数据 + # 测试代码 train_data, train_labels = load_dataset("trainingDigits") - # 测试数据 test_data = ( "00000000000000110000000000000000" "00000000000011111000000000000000" @@ -157,13 +145,8 @@ if __name__ == "__main__": "00000000000001111111110000000000" "00000000000000000111100000000000" ) - + test_vector = np.array([int(char) for char in test_data]).reshape(1, 1024) - - # 使用曼哈顿距离分类 - predicted_label = classify(test_vector, train_data, train_labels, distance_metric='manhattan') - print(f"预测的标签(曼哈顿距离): {predicted_label}") - - # 使用 KD-tree 进行加速的分类 - predicted_label_kdtree = classify_with_kdtree(test_vector, train_data, train_labels) - print(f"预测的标签(KD-tree 加速): {predicted_label_kdtree}") + + predicted_label = classify(test_vector, train_data, train_labels) + print(f"预测的标签: {predicted_label}") \ No newline at end of file