From 1d18e60f9136174e539aa13ba0fe0e794630e202 Mon Sep 17 00:00:00 2001 From: cool Date: Tue, 8 Oct 2024 00:38: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 | 106 ++++++++++++++++++++++++++-------------------------- 1 file changed, 52 insertions(+), 54 deletions(-) diff --git a/function.py b/function.py index c51abf3..0280b4b 100644 --- a/function.py +++ b/function.py @@ -1,8 +1,7 @@ # 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 +from scipy.spatial.distance import cdist """ @@ -44,66 +43,65 @@ name = "陈宇杰" # 这里写自己的代码实现 -def classify0(inX, dataSet, labels, k): + +def knn_classify(inX, dataSet, labels, k): """ - KNN 分类函数 - :param inX: 待分类的样本 - :param dataSet: 训练数据集 - :param labels: 训练集对应的标签 - :param k: 选择的邻居数 - :return: 预测的分类标签 + K-最近邻 (KNN) 算法分类输入样本。 + + 参数: + inX : numpy array : 待分类的输入样本 + dataSet : numpy array : 训练数据 + labels : list : 训练数据对应的标签 + k : int : 用于分类的最近邻数量 + + 返回: + 预测的分类标签。 """ - 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] # 多数投票 + # 计算 inX 与所有训练数据点之间的欧几里得距离 + distances = cdist([inX], dataSet, 'euclidean')[0] + + # 获取 k 个最近邻的索引 + nearest_indices = distances.argsort()[:k] + + # 获取最近邻的标签 + nearest_labels = [labels[i] for i in nearest_indices] + + # 使用多数投票法决定预测的类别,考虑距离权重 + weights = 1 / (distances[nearest_indices] + 1e-10) # 防止除以零 + weighted_labels = Counter() + for label, weight in zip(nearest_labels, weights): + weighted_labels[label] += weight + + # 获取权重最高的标签 + predicted_label = weighted_labels.most_common(1)[0][0] + return predicted_label def load_data(file_path): """ - 加载 TSV 格式数据文件 - :param file_path: 数据文件路径 - :return: 特征和标签 + 加载 TSV 格式数据文件。 """ - 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 main(): - # 加载训练集 - train_file = "datingTrainSet2.tsv" # 训练集文件路径 - train_data, train_labels = load_data(train_file) # 加载数据 - - # 特征缩放 - scaler = StandardScaler() # 创建标准化对象 - train_data = scaler.fit_transform(train_data) # 对训练数据进行标准化 - - # 设置 K 值 - k = 1 # 直接定义 K 值为 1 - - # 手动实现 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 = classify0(test_sample, train_subset, train_labels_subset, k) - if predicted_label == train_labels[i]: - correct_predictions += 1 - - accuracy = correct_predictions / len(train_data) # 计算准确性 - print(f"使用 K 值 {k} 的准确率: {accuracy:.4f}") - - # 测试分类 - test_sample = [65915, 3.868359, 0.128078] # 测试样本 - test_sample = scaler.transform([test_sample]) # 对测试样本进行相同的缩放 - predicted_label = classify0(test_sample[0], train_data, train_labels, k) # 分类 - - print(f"测试样本 {test_sample[0]} 的预测分类标签为: {predicted_label}") +def classify0(inX, dataSet, labels, k=1): + """ + 调用 knn_classify 函数进行分类。 + """ + if k > len(labels) or k <= 0: + raise ValueError("k must be between 1 and the number of training samples.") + return knn_classify(inX, dataSet, labels, k) if __name__ == "__main__": - 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}")