From 609fb67c25f71d0269d150554330976657a1b629 Mon Sep 17 00:00:00 2001 From: cool Date: Tue, 8 Oct 2024 01:17:31 +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 | 78 +++++++++++++++-------------------------------------- 1 file changed, 22 insertions(+), 56 deletions(-) diff --git a/function.py b/function.py index 51257c1..56aa076 100644 --- a/function.py +++ b/function.py @@ -1,50 +1,14 @@ -# function.py -import numpy as np -from collections import Counter -from scipy.spatial.distance import cdist -from sklearn.preprocessing import StandardScaler - - -""" -挑战说明: -- 自行编写实现 KNN 分类算法。 -- 函数输入: 待分类的样本 inX, 训练数据集 dataSet, 训练集对应的标签 labels。 -- 函数返回: 预测的分类标签。 - -注意事项: -- 可以自行导入其他库,需要在 requirements.txt 添加依赖,若未在 requirements.txt 中添加使用到的依赖,则无法自动评测,成绩为零。 -- 在 function.py 中实现 KNN 分类算法。 -- 自动评测脚本仅会加载 classify0 函数,请勿修改函数名。 -- 训练集在本目录下的 datingTrainSet2.tsv 中。 -- 评测数据集在本目录下的 datingTestSet2.tsv 中。 - -挑战环境: -- 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 = "202210423210" name = "陈宇杰" +import numpy as np +from collections import Counter +from sklearn.preprocessing import StandardScaler +from sklearn.model_selection import train_test_split +from sklearn.datasets import load_iris # 示例数据集 +from sklearn.metrics import accuracy_score -""" -参数说明: -- inX (numpy array): 输入待分类的样本。 -- dataSet (numpy array): 训练数据集。 -- labels (list or numpy array): 训练集对应的标签。 -返回值: -- int: 预测的分类标签。 -""" - - -# 这里写自己的代码实现 -def classify0(inX, dataSet, labels, k=2): +def classify0(inX, dataSet, labels, k=3): """ KNN 分类函数 :param inX: 待分类的样本 @@ -56,7 +20,14 @@ def classify0(inX, dataSet, labels, k=2): distances = np.linalg.norm(dataSet - inX, axis=1) # 计算欧几里得距离 nearest_indices = distances.argsort()[:k] # 获取最近的 k 个邻居 nearest_labels = [labels[i] for i in nearest_indices] # 获取这些邻居的标签 - predicted_label = Counter(nearest_labels).most_common(1)[0][0] # 多数投票 + + # 加权投票 + weights = 1 / (distances[nearest_indices] + 1e-5) # 加1e-5防止除以零 + weighted_votes = Counter() + for label, weight in zip(nearest_labels, weights): + weighted_votes[label] += weight + + predicted_label = weighted_votes.most_common(1)[0][0] # 多数投票 return predicted_label def load_data(file_path): @@ -79,27 +50,22 @@ def main(): scaler = StandardScaler() # 创建标准化对象 train_data = scaler.fit_transform(train_data) # 对训练数据进行标准化 - # 设置 K 值 - k = 8 # 将 K 值设置为 3 + # 划分训练集和测试集 + X_train, X_test, y_train, y_test = train_test_split(train_data, train_labels, test_size=0.2, random_state=42) # 手动实现 KNN 分类计算准确率 correct_predictions = 0 - total_tests = len(train_data) # 测试的总数 + total_tests = len(X_test) # 测试的总数 for i in range(total_tests): - # 留出一条数据作为测试集,其余作为训练集 - test_sample = train_data[i] - train_subset = np.delete(train_data, i, axis=0) - train_labels_subset = np.delete(train_labels, i) - # 使用 KNN 分类器预测 - predicted_label = classify0(test_sample, train_subset, train_labels_subset) + predicted_label = classify0(X_test[i], X_train, y_train) # 输出分类结果 - if predicted_label == train_labels[i]: + if predicted_label == y_test[i]: correct_predictions += 1 else: - print(f"第 {i + 1} 次测试错误,数据 {test_sample} 被分类到 {predicted_label},实际是 {train_labels[i]}") + print(f"第 {i + 1} 次测试错误,数据 {X_test[i]} 被分类到 {predicted_label},实际是 {y_test[i]}") accuracy = correct_predictions / total_tests # 计算准确性 print(f"使用 K 值 {k} 的准确率: {accuracy:.4f}") @@ -107,7 +73,7 @@ def main(): # 测试分类 test_sample = [65915, 3.868359, 0.128078] # 测试样本 test_sample = scaler.transform([test_sample]) # 对测试样本进行相同的缩放 - predicted_label = classify0(test_sample[0], train_data, train_labels) # 分类 + predicted_label = classify0(test_sample[0], X_train, y_train, k) # 分类 print(f"测试样本 {test_sample[0]} 的预测分类标签为: {predicted_label}")