From 8a77e537bffed78d59eea3076794eba0e3254d32 Mon Sep 17 00:00:00 2001 From: cool Date: Mon, 7 Oct 2024 23:56:29 +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 | 104 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 62 insertions(+), 42 deletions(-) diff --git a/function.py b/function.py index 74e7bf0..3b26209 100644 --- a/function.py +++ b/function.py @@ -1,6 +1,9 @@ # function.py import numpy as np from collections import Counter +from sklearn.preprocessing import StandardScaler +from sklearn.model_selection import train_test_split, cross_val_score + """ 挑战说明: @@ -41,60 +44,77 @@ name = "陈宇杰" # 这里写自己的代码实现 -# KNN 分类算法 + def knn_classify(inX, dataSet, labels, k): """ - K-最近邻 (KNN) 算法分类输入样本。 - - 参数: - inX : numpy array : 待分类的输入样本 - dataSet : numpy array : 训练数据 - labels : list : 训练数据对应的标签 - k : int : 用于分类的最近邻数量 - - 返回: - 预测的分类标签。 + KNN 分类函数 + :param inX: 待分类的样本 + :param dataSet: 训练数据集 + :param labels: 训练集对应的标签 + :param k: 选择的邻居数 + :return: 预测的分类标签 """ - # 计算 inX 与所有训练数据点之间的欧几里得距离 - distances = np.linalg.norm(dataSet - inX, axis=1) - - # 排序距离并返回前 k 个最近邻的索引 - nearest_indices = distances.argsort()[:k] - - # 获取最近邻的标签 - nearest_labels = [labels[i] for i in nearest_indices] - - # 使用多数投票法决定预测的类别 - predicted_label = Counter(nearest_labels).most_common(1)[0][0] - + 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] # 多数投票 return predicted_label def load_data(file_path): """ - 加载 TSV 格式数据文件。 + 加载 TSV 格式数据文件 + :param file_path: 数据文件路径 + :return: 特征和标签 """ - data = np.loadtxt(file_path, delimiter="\t") - features = data[:, :-1] - labels = data[:, -1].astype(int) + data = np.loadtxt(file_path, delimiter="\t") # 加载数据 + features = data[:, :-1] # 特征 + labels = data[:, -1].astype(int) # 标签 return features, labels -def classify0(inX, dataSet, labels, k=1): - """ - 调用 knn_classify 函数进行分类。 - """ - return knn_classify(inX, dataSet, labels, k) +def main(): + # 加载训练集 + train_file = "datingTrainSet2.tsv" # 训练集文件路径 + train_data, train_labels = load_data(train_file) # 加载数据 + + # 特征缩放 + scaler = StandardScaler() # 创建标准化对象 + train_data = scaler.fit_transform(train_data) # 对训练数据进行标准化 + + # 使用交叉验证选择最佳 k 值 + k_values = range(1, 31) # 定义 k 值范围 + best_k = 1 + best_accuracy = 0 + + for k in k_values: + # 通过手动实现 KNN 分类计算准确率 + correct_predictions = 0 + for i in range(len(train_data)): + # 留出一条数据作为测试集,其余作为训练集 + 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 = knn_classify(test_sample, train_subset, train_labels_subset, k) + if predicted_label == train_labels[i]: + correct_predictions += 1 + + accuracy = correct_predictions / len(train_data) # 计算准确性 + if accuracy > best_accuracy: + best_accuracy = accuracy + best_k = k + + print(f"最佳 k 值: {best_k},准确率: {best_accuracy:.4f}") + + # 测试分类 + test_sample = [65915, 3.868359, 0.128078] # 测试样本 + test_sample = scaler.transform([test_sample]) # 对测试样本进行相同的缩放 + predicted_label = knn_classify(test_sample[0], train_data, train_labels, best_k) # 分类 + + print(f"测试样本 {test_sample[0]} 的预测分类标签为: {predicted_label}") if __name__ == "__main__": - # 加载训练集 - train_file = "datingTrainSet2.tsv" - train_data, train_labels = load_data(train_file) - - # 测试分类 - test_sample = [65915, 3.868359, 0.128078] - predicted_label = classify0(test_sample, train_data, train_labels) - - # 打印分类结果 - print(f"测试样本 {test_sample} 的预测分类标签为: {predicted_label}") + main()