From 0f1f08fa3990df033b694f670b2afe3fd4228ee3 Mon Sep 17 00:00:00 2001 From: Xionghaoran <719929980@qq.com> Date: Mon, 14 Oct 2024 21:46:36 +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 | 86 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 57 insertions(+), 29 deletions(-) diff --git a/function.py b/function.py index efa5a03..e95bc5d 100644 --- a/function.py +++ b/function.py @@ -1,10 +1,7 @@ # function.py import numpy as np import pandas as pd -from sklearn.model_selection import train_test_split, GridSearchCV from sklearn.preprocessing import StandardScaler -from sklearn.neighbors import KNeighborsClassifier -from sklearn.metrics import accuracy_score """ 挑战说明: @@ -46,6 +43,40 @@ name = "熊浩燃" # 这里写自己的代码实现 +def classify0(inX, dataSet, labels, k=3): + """ + KNN 分类算法,使用马氏距离。 + + Args: + - inX (numpy array): 输入待分类的样本。 + - dataSet (numpy array): 训练数据集。 + - labels (list or numpy array): 训练集对应的标签。 + - k (int): kNN 算法参数,默认值为 3。 + + Returns: + - int: 预测的分类标签。 + """ + # 标准化数据 + scaler = StandardScaler() + dataSet = scaler.fit_transform(dataSet) + inX = scaler.transform([inX])[0] + + # 计算协方差矩阵的逆 + cov_matrix = np.cov(dataSet, rowvar=False) + inv_cov_matrix = np.linalg.inv(cov_matrix) + + # 计算马氏距离 + diff = dataSet - inX + distances = np.sqrt(np.sum(diff @ inv_cov_matrix * diff, axis=1)) + + # 按距离排序并返回 k 个最近的标签 + sorted_indices = distances.argsort() + nearest_labels = [labels[i] for i in sorted_indices[:k]] + + # 找出出现次数最多的标签 + label_counts = np.bincount(nearest_labels) + return label_counts.argmax() + def load_data(file_path): """ 加载 TSV 格式数据文件。 @@ -57,41 +88,38 @@ def load_data(file_path): def find_best_k(X_train, y_train): """ - 使用交叉验证找到最佳的 k 值。 + 寻找最佳 k 值。 """ - param_grid = {'n_neighbors': range(1, 21), 'weights': ['uniform', 'distance']} - knn = KNeighborsClassifier() - grid_search = GridSearchCV(knn, param_grid, cv=5) - grid_search.fit(X_train, y_train) - return grid_search.best_params_ + best_k = 1 + best_accuracy = 0 + + for k in range(1, 21): + # 使用 classify0 进行预测 + y_pred = [classify0(x, X_train, y_train, k) for x in X_train] + accuracy = np.mean(y_pred == y_train) + + if accuracy > best_accuracy: + best_accuracy = accuracy + best_k = k + + return best_k, best_accuracy if __name__ == "__main__": - # 加载数据 train_file = "datingTestSet2.tsv" X, y = load_data(train_file) - # 分割数据集 - X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) - # 标准化特征 scaler = StandardScaler() - X_train = scaler.fit_transform(X_train) - X_test = scaler.transform(X_test) + X = scaler.fit_transform(X) # 寻找最佳 k 值 - best_params = find_best_k(X_train, y_train) - best_k = best_params['n_neighbors'] - best_weights = best_params['weights'] - - # 使用最佳参数训练模型并评估 - knn = KNeighborsClassifier(n_neighbors=best_k, weights=best_weights) - knn.fit(X_train, y_train) - y_pred = knn.predict(X_test) - - # 输出准确率 - accuracy = accuracy_score(y_test, y_pred) - print(f"最佳 k 值: {best_k}, 权重: {best_weights}, 准确率: {accuracy:.2f}") - - + best_k, best_accuracy = find_best_k(X, y) + # 输出最佳 k 值和对应的准确率 + print(f"最佳 k 值: {best_k}, 准确率: {best_accuracy:.2f}") + # 进行预测 + sample = np.array([65915, 3.868359, 0.128078]) + sample = scaler.transform([sample])[0] # 标准化样本 + predicted_label = classify0(sample, X, y, best_k) + print(f"预测结果: {predicted_label}")