diff --git a/function.py b/function.py index b1f8c16..dc0508f 100644 --- a/function.py +++ b/function.py @@ -25,8 +25,8 @@ import os """ 请在这里填写学号和姓名,不填写即成绩无效。 """ -id = "202210423xxx" -name = "test_name" +id = "202210423114" +name = "龙鑫辉" """ @@ -54,6 +54,77 @@ def classify(input_vector, dataSet, labels, k=0): Returns: - int: 预测的分类标签。 """ +import numpy as np + +def validate_inputs(input_vector, dataSet, labels, k): + """ + 验证输入参数的有效性。 + """ + if not isinstance(input_vector, np.ndarray) or input_vector.ndim != 1: + raise ValueError("input_vector 必须是一维 numpy 数组") + + if not isinstance(dataSet, np.ndarray) or dataSet.ndim != 2: + raise ValueError("dataSet 必须是二维 numpy 数组") + + if not isinstance(labels, (list, np.ndarray)): + raise ValueError("labels 必须是列表或一维 numpy 数组") + + if len(dataSet) != len(labels): + raise ValueError("dataSet 和 labels 的长度必须相同") + + if not isinstance(k, int) or k <= 0: + raise ValueError("k 必须是正整数") + +def calculate_distances(input_vector, dataSet): + """ + 计算输入向量与数据集中每个样本的距离。 + """ + distances = np.linalg.norm(dataSet - input_vector, axis=1) + return distances + +def get_k_nearest_labels(distances, labels, k): + """ + 获取最近的 k 个邻居的标签。 + """ + k_nearest_indices = np.argsort(distances)[:k] + k_nearest_labels = labels[k_nearest_indices] + return k_nearest_labels + +def majority_vote(k_nearest_labels): + """ + 投票决定最频繁出现的标签。 + """ + from collections import Counter + label_counts = Counter(k_nearest_labels) + most_common_label = label_counts.most_common(1)[0][0] + return most_common_label + +def classify(input_vector, dataSet, labels, k=3): + """ + KNN 分类算法。 + + Args: + - input_vector (numpy array): 输入待分类的样本。 + - dataSet (numpy array): 训练数据集。 + - labels (list or numpy array): 训练集对应的标签。 + - k (int): kNN 算法参数,默认值为 3。 + + Returns: + - int: 预测的分类标签。 + """ + # 验证输入参数 + validate_inputs(input_vector, dataSet, labels, k) + + # 计算距离 + distances = calculate_distances(input_vector, dataSet) + + # 获取最近的 k 个邻居的标签 + k_nearest_labels = get_k_nearest_labels(distances, labels, k) + + # 投票决定最频繁出现的标签 + predicted_label = majority_vote(k_nearest_labels) + + return predicted_label # 这里也写自己的代码实现 @@ -68,7 +139,61 @@ def load_dataset(directory): - np.array: 特征数据。 - np.array: 标签数据。 """ +import os +import numpy as np +def load_dataset(directory): + """ + 从文件夹中加载数据,若不自行正确实现,则无法通过评测,**不记录成绩**。 + + Args: + - directory (str): 数据文件夹路径。 + + Returns: + - np.array: 特征数据。 + - np.array: 标签数据。 + """ + # 规范化路径 + directory = os.path.abspath(os.path.realpath(directory)) + + # 检查路径是否为目录 + if not os.path.isdir(directory): + raise ValueError(f"指定的路径 {directory} 不是一个有效的目录") + + features = [] + labels = [] + + try: + # 遍历目录中的文件 + for filename in os.listdir(directory): + file_path = os.path.join(directory, filename) + + # 检查文件是否为预期的格式 + if not filename.endswith('.npy'): + continue + + # 读取文件 + data = np.load(file_path) + + # 假设每个文件包含一个特征数组和一个标签 + feature = data[0] + label = data[1] + + features.append(feature) + labels.append(label) + + except FileNotFoundError: + raise FileNotFoundError(f"指定的目录 {directory} 不存在") + except PermissionError: + raise PermissionError(f"没有权限访问目录 {directory}") + except Exception as e: + raise RuntimeError(f"读取文件时发生错误: {e}") + + # 处理空目录的情况 + if not features: + return np.array([]), np.array([]) + + return np.array(features), np.array(labels) # 这里还写自己的代码实现 def img_to_vector(filename): @@ -82,7 +207,61 @@ def img_to_vector(filename): Returns: - np.array: 二值图像向量。 """ +import numpy as np +from PIL import Image +import os +def img_to_vector(filename): + """ + 将二值图像转换为向量。 + 该部分应为 load_dataset 函数的辅助子函数,可单独在这里实现,也可直接集成至 load_dataset 函数中。 + + Args: + - filename (str): 图像文件路径。 + + Returns: + - np.array: 二值图像向量。 + """ + try: + # 路径规范化 + filename = os.path.abspath(filename) + + # 验证文件是否存在 + if not os.path.isfile(filename): + raise FileNotFoundError(f"文件 {filename} 不存在") + + # 验证文件是否为有效的图像文件 + with Image.open(filename) as img: + if img.format not in ['PNG', 'JPEG', 'BMP']: + raise ValueError(f"文件 {filename} 不是有效的图像文件") + + # 转换为灰度图像 + img = img.convert('L') + + # 转换为二值图像 + img = img.point(lambda p: p > 128 and 1 or 0, mode='1') + + # 获取图像尺寸 + width, height = img.size + + # 检查图像是否为空或尺寸为零 + if width == 0 or height == 0: + raise ValueError(f"图像 {filename} 尺寸为零") + + # 将图像转换为向量 + vector = np.array(img).flatten() + + return vector + + except FileNotFoundError as e: + print(f"错误: {e}") + return None + except ValueError as e: + print(f"错误: {e}") + return None + except Exception as e: + print(f"未知错误: {e}") + return None if __name__ == "__main__": # 以下代码可用于测试,可自行随意修改