From 2c2b4e734701b9403637064e5e3e01c52978f3d1 Mon Sep 17 00:00:00 2001 From: Dengddd <3149942468@qq.com> Date: Wed, 4 Dec 2024 11:06:32 +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 | 126 ++++++++++++++++++++++++---------------------------- 1 file changed, 58 insertions(+), 68 deletions(-) diff --git a/function.py b/function.py index c0c2a4e..188e49b 100644 --- a/function.py +++ b/function.py @@ -40,12 +40,13 @@ from sklearn.metrics import classification_report, accuracy_score from sklearn.preprocessing import StandardScaler +# 数据加载函数保持不变 def load_data(filepath): """ 从文件中加载数据,若不自行正确实现,则无法通过评测,**不记录成绩**。 Args: - - filepath (str): 数据文件路径。 + - directory (str): 数据文件路径。 Returns: - np.array: 特征数据。 @@ -63,96 +64,66 @@ def load_data(filepath): # 特征为其他列(不包含倒数第6列标签) features = np.array(fields[: -6] + fields[-5:], dtype=float) # 标签映射:将 1->0, 2->1, 3->2 - label_mapping = {1: 0, 2: 1, 3: 2} - if label in label_mapping: - label = label_mapping[label] + if label == 1: + label = 0 + elif label == 2: + label = 1 + elif label == 3: + label = 2 else: print(f"无效标签,跳过此样本:{label}") continue # 跳过无效标签 + # 添加数据和标签 data.append(features) labels.append(label) - return np.array(data), np.array(labels) + # 转换为numpy数组 + data = np.array(data) + labels = np.array(labels) + return data, labels -def train_svm(X, y, C): +# 封装训练和评估模型的函数 +def train_and_evaluate_model(X_train_fold, y_train_fold, X_val_fold, y_val_fold, C): + model = SVC(kernel='rbf', C=C, gamma='scale', random_state=42) + model.fit(X_train_fold, y_train_fold) + y_pred_fold = model.predict(X_val_fold) + accuracy_fold = accuracy_score(y_val_fold, y_pred_fold) + return accuracy_fold, model + + +def train_svm(X, y, other_params=None): """ - 训练支持向量机模型。 + 支持向量机训练函数。 Args: - X (numpy array): 特征数据。 - y (numpy array): 标签数据。 - - C (float): SVM的正则化参数C。 + - other_params (str): 其它参数,可选设置。若需设置其它参数,必须设置其默认值,否则将无法通过自动评测,成绩为零。 Returns: - SVC: 训练好的SVM模型。 """ - model = SVC(kernel='rbf', C=C, gamma='scale', random_state=42) + model = SVC(kernel='rbf', C=1.0, gamma='scale', random_state=42) model.fit(X, y) return model -def cross_validation(X_full_train, y_full_train, C_values): +def predict_svm(inX, model): """ - 进行交叉验证,选出最佳模型。 + 支持向量机预测函数。 Args: - - X_full_train (numpy array): 完整训练集的特征数据。 - - y_full_train (numpy array): 完整训练集的标签数据。 - - C_values (list): 要尝试的SVM正则化参数C的取值列表。 + - inX (numpy array): 输入待分类的样本。 + - model (SVC): 训练得到的支持向量机模型。 Returns: - - SVC: 在交叉验证中表现最佳的模型。 + - int: 预测的分类标签。 """ - best_accuracy = 0 - best_model = None - kf = KFold(n_splits=5, shuffle=True, random_state=42) - for C in C_values: - avg_accuracy = 0 - for train_index, val_index in kf.split(X_full_train): - X_train_fold, X_val_fold = X_full_train[train_index], X_full_train[val_index] - y_train_fold, y_val_fold = y_full_train[train_index], y_full_train[val_index] - model = train_svm(X_train_fold, y_train_fold, C) - y_pred_fold = model.predict(X_val_fold) - accuracy_fold = accuracy_score(y_val_fold, y_pred_fold) - avg_accuracy += accuracy_fold - avg_accuracy /= 5 - if avg_accuracy > best_accuracy: - best_accuracy = avg_accuracy - best_model = model - return best_model - - -def evaluate_model(model, X_final_test, y_final_test): - """ - 使用模型在最终测试集上进行评估并输出相关结果。 - - Args: - - model (SVC): 训练好的模型。 - - X_final_test (numpy array): 最终测试集的特征数据。 - - y_final_test (numpy array): 最终测试集的标签数据。 - """ - y_pred = model.predict(X_final_test) - print("\n分类报告:") - print(classification_report(y_final_test, y_pred, target_names=["存活", "安乐死", "死亡"])) - accuracy = accuracy_score(y_final_test, y_pred) - print(f"测试集准确率: {accuracy * 100:.2f}%") - - -def predict_single_sample(model, test_sample, actual_result): - """ - 使用模型对单个样本进行预测并输出预测结果和实际结果对比。 - - Args: - - model (SVC): 训练好的模型。 - - test_sample (numpy array): 单个测试样本的特征数据。 - - actual_result (int): 单个测试样本的实际标签。 - """ - y_pred_single = model.predict(test_sample.reshape(1, -1))[0] - print(f"\n单个样本预测结果: {y_pred_single}, 实际结果: {actual_result}") + return model.predict(inX.reshape(1, -1))[0] if __name__ == "__main__": - # 加载训练数据和测试数据 + # 加载数据 X_train, y_train = load_data("./horse-colic.data") X_test, y_test = load_data("./horse-colic.test") @@ -166,14 +137,33 @@ if __name__ == "__main__": # 定义要尝试的C值列表 C_values = [0.1, 1, 10] - - # 进行交叉验证选出最佳模型 - best_model = cross_validation(X_full_train, y_full_train, C_values) + best_accuracy = 0 + best_model = None + kf = KFold(n_splits=5, shuffle=True, random_state=42) + for C in C_values: + total_accuracy = 0 + for train_index, val_index in kf.split(X_full_train): + X_train_fold, X_val_fold = X_full_train[train_index], X_full_train[val_index] + y_train_fold, y_val_fold = y_full_train[train_index], y_full_train[val_index] + accuracy_fold, model = train_and_evaluate_model(X_train_fold, y_train_fold, X_val_fold, y_val_fold, C) + total_accuracy += accuracy_fold + avg_accuracy = total_accuracy / 5 + if avg_accuracy > best_accuracy: + best_accuracy = avg_accuracy + best_model = model # 使用在交叉验证中选出的最佳模型在最终测试集上进行评估 - evaluate_model(best_model, X_final_test, y_final_test) + y_pred = best_model.predict(X_final_test) + + # 输出评估结果 + print("\n分类报告:") + print(classification_report(y_final_test, y_pred, target_names=["存活", "安乐死", "死亡"])) + + # 输出准确率 + accuracy = accuracy_score(y_final_test, y_pred) + print(f"测试集准确率: {accuracy * 100:.2f}%") # 测试单个数据 test_sample = X_final_test[11] # 选择第12个样本(从0开始计数) - predict_single_sample(best_model, test_sample, y_final_test[11]) - \ No newline at end of file + y_pred_single = predict_svm(test_sample, best_model) + print(f"\n单个样本预测结果: {y_pred_single}, 实际结果: {y_final_test[11]}") \ No newline at end of file