From bd717210a0f376eeef62ceb825f284cdc335f0f7 Mon Sep 17 00:00:00 2001 From: zhangchenghong <1598349064@qq.com> Date: Sun, 20 Oct 2024 13:54:22 +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 | 158 ++++++++++++++++++++++++++++++---------------------- 1 file changed, 90 insertions(+), 68 deletions(-) diff --git a/function.py b/function.py index 5e3d576..83246af 100644 --- a/function.py +++ b/function.py @@ -41,48 +41,44 @@ name = "章程鸿·" # 这里写自己的代码实现 -import numpy as np -import os -from collections import Counter +import numpy as np +import os +from collections import Counter -def classify(input_vector, dataSet, labels, k=3): - """ - 使用 KNN 算法对输入样本进行分类。 - - 参数: - - input_vector (numpy array): 输入待分类的样本(1xN)。 - - dataSet (numpy array): 训练数据集(MxN)。 - - labels (list or numpy array): 训练集对应的标签。 - - k (int): kNN 算法参数,默认值为 3。 - - 返回: - - int: 预测的分类标签。 - """ - # 计算马氏距离 - mean_vector = np.mean(dataSet, axis=0) - cov_matrix = np.cov(dataSet.T) - inv_cov_matrix = np.linalg.inv(cov_matrix) - diff_vector = input_vector - dataSet - mahalanobis_distances = np.sqrt(np.einsum('ij,jk,ik->i', diff_vector, inv_cov_matrix, diff_vector.T)) - sorted_indices = mahalanobis_distances.argsort() - k_nearest_distances = mahalanobis_distances[sorted_indices[:k]] + +# 这里写自己的代码实现 +def classify(input_vector, dataSet, labels, k=2): + """ + 使用 KNN 算法对输入样本进行分类。 + + 参数: + - input_vector (numpy array): 输入待分类的样本(1xN)。 + - dataSet (numpy array): 训练数据集(MxN)。 + - labels (list or numpy array): 训练集对应的标签。 + - k (int): kNN 算法参数,默认值为 2。 + + 返回: + - int: 预测的分类标签。 + """ + # 在 classify 函数中实现权重投票 + distances = np.sum((input_vector - dataSet) ** 2, axis=1) + sorted_indices = distances.argsort() + k_nearest_distances = distances[sorted_indices[:k]] k_nearest_labels = labels[sorted_indices[:k]] - + # 计算权重(距离的倒数) weights = 1 / k_nearest_distances # 归一化权重 weights /= weights.sum() - - # 使用加权多数表决法 - weighted_votes = {} + + # 计算加权投票 + weighted_votes = np.zeros((10,)) for label, weight in zip(k_nearest_labels, weights): - if label not in weighted_votes: - weighted_votes[label] = weight - else: - weighted_votes[label] += weight - - return max(weighted_votes, key=weighted_votes.get) + weighted_votes[label] += weight + + return np.argmax(weighted_votes) +# 在 load_dataset 函数中添加特征缩放 def load_dataset(directory): feature_list = [] label_list = [] @@ -93,31 +89,72 @@ def load_dataset(directory): label_list.append(int(file.split('_')[0])) feature_matrix = np.array(feature_list) label_array = np.array(label_list) - - # 特征缩放(归一化) - min_value = np.min(feature_matrix) - max_value = np.max(feature_matrix) - feature_matrix = (feature_matrix - min_value) / (max_value - min_value) - + + # 特征缩放 + feature_matrix = feature_matrix / 255.0 return feature_matrix, label_array + # 计算输入向量与训练集之间的欧氏距离 + distances = np.sum((input_vector - dataSet) ** 2, axis=1) ** 0.5 + # 根据距离排序并获取索引 + sorted_indices = distances.argsort() + # 选择距离最近的k个点 + k_nearest_labels = labels[sorted_indices[:k]].tolist() # 将 NumPy 数组转换为列表 + # 统计k个点中各类别的数量 + count = Counter(k_nearest_labels) + # 返回数量最多的类别标签 + return count.most_common(1)[0][0] -def img_to_vector(filename): - """ - 将二值图像转换为向量。 - - Args: - - filename (str): 图像文件路径。 - - Returns: - - np.array: 二值图像向量。 - """ - vector = np.zeros((1024,)) +# 这里也写自己的代码实现 +def load_dataset(directory): + """ + 加载数据集中的图像,并将其转换为特征向量和标签。 + + 参数: + - directory (str): 数据文件夹路径。 + + 返回: + - np.array: 特征数据(Mx1024)。 + - np.array: 标签数据(Mx1)。 + """ + # 初始化特征数据列表和标签列表 + feature_list = [] + label_list = [] + # 遍历目录中的所有文件 + for file in os.listdir(directory): + # 获取文件的完整路径 + file_path = os.path.join(directory, file) + # 将图像文件转换为向量 + feature_vector = img_to_vector(file_path) + # 将特征向量添加到列表中 + feature_list.append(feature_vector) + # 获取文件名中的标签并添加到标签列表中 + label_list.append(int(file.split('_')[0])) + # 将特征列表和标签列表转换为numpy数组 + feature_matrix = np.array(feature_list) + label_array = np.array(label_list) + return feature_matrix, label_array +# 这里还写自己的代码实现 +def img_to_vector(filename): + """ + 将二值图像转换为向量。 + + Args: + - filename (str): 图像文件路径。 + + Returns: + - np.array: 二值图像向量。 + """ + # 初始化向量 + vector = np.zeros((1024,)) # 创建一个一维数组 + # 打开文件并逐行读取 with open(filename) as file: for i, line in enumerate(file): + # 将每行的数字字符转换为整数并存储到向量中 vector[i*32:i*32+32] = np.array([int(char) for char in line.strip()]) return vector if __name__ == "__main__": + # 以下代码可用于测试,可自行随意修改 train_data, train_labels = load_dataset("trainingDigits") test_data = ( @@ -154,25 +191,10 @@ if __name__ == "__main__": "00000000000001111111110000000000" "00000000000000000111100000000000" ) - # 使用多数表决法的结果 - predicted_label_majority = classify( + predicted_label = classify( np.array([int(char) for char in test_data]).reshape(1, 1024), train_data, train_labels, ) - print(f"使用多数表决法预测的标签: {predicted_label_majority}") - # 使用加权多数表决法的结果 - predicted_label_weighted = classify( - np.array([int(char) for char in test_data]).reshape(1, 1024), - train_data, - train_labels, - ) - print(f"使用加权多数表决法预测的标签: {predicted_label_weighted}") - - # 对比分析 - if predicted_label_majority == predicted_label_weighted: - print("两种方法预测结果一致。") - else: - print("两种方法预测结果不同。") - \ No newline at end of file + print(f"预测的标签: {predicted_label}") \ No newline at end of file