import numpy as np import os from scipy.spatial 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 = "202210423117" name = "程悦" def classify(input_vector, dataSet, labels, k=5): """ KNN 分类算法。 Args: - input_vector (numpy array): 输入待分类的样本。 - dataSet (numpy array): 训练数据集。 - labels (list or numpy array): 训练集对应的标签。 - k (int): kNN 算法参数,请**自行设置默认值**,评测时仅会使用其默认值,不修改默认值将**无法通过**评测,**成绩为零**。 Returns: - int: 预测的分类标签。 """ kdtree = KDTree(dataSet) distances, indices = kdtree.query(input_vector, k=k) k_nearest_labels = [labels[i] for i in indices] unique_labels, counts = np.unique(k_nearest_labels, return_counts=True) return unique_labels[np.argmax(counts)] def img_to_vector(filename): """ 将二值图像转换为向量。 该部分应为 load_dataset 函数的辅助子函数,可单独在这里实现,也可直接集成至 load_dataset 函数中。 Args: - filename (str): 图像文件路径。 Returns: - np.array: 二值图像向量。 """ with open(filename, 'r') as f: lines = f.readlines() return np.array([int(char) for line in lines for char in line.strip()]) def load_dataset(directory): """ 从文件夹中加载数据,若不自行正确实现,则无法通过评测,**不记录成绩**。 Args: - directory (str): 数据文件夹路径。 Returns: - np.array: 特征数据。 - np.array: 标签数据。 """ data = [] labels = [] for filename in os.listdir(directory): if filename.endswith(".txt"): label = int(filename[0]) vector = img_to_vector(os.path.join(directory, filename)) data.append(vector) labels.append(label) return np.array(data), np.array(labels) def load_test_dataset(directory): return load_dataset(directory) def calculate_accuracy(): train_data, train_labels = load_dataset("trainingDigits") test_data, test_labels = load_test_dataset("testDigits") correct_count = 0 for i in range(len(test_data)): predicted_label = classify(test_data[i].reshape(1, 1024), train_data, train_labels) if predicted_label == test_labels[i]: correct_count += 1 accuracy = correct_count / len(test_data) print(f"分类精度: {accuracy}") def test_different_k(): train_data, train_labels = load_dataset("trainingDigits") test_data, test_labels = load_test_dataset("testDigits") k_values = [1, 3, 5, 7, 9] for k in k_values: correct_count = 0 for i in range(len(test_data)): predicted_label = classify(test_data[i].reshape(1, 1024), train_data, train_labels, k=k) if predicted_label == test_labels[i]: correct_count += 1 accuracy = correct_count / len(test_data) print(f"k = {k}时的分类精度: {accuracy}") if __name__ == "__main__": # 测试不同k值的分类精度 test_different_k() # 计算分类精度 calculate_accuracy()