From 4c0d41e48a21cb67c476e378d4b756e5af124a01 Mon Sep 17 00:00:00 2001 From: dong <2938690875@qq.com> Date: Sat, 2 Nov 2024 16:16:46 +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 | 115 +++++++++++++++++++++++++--------------------------- 1 file changed, 56 insertions(+), 59 deletions(-) diff --git a/function.py b/function.py index d339f7f..70a2171 100644 --- a/function.py +++ b/function.py @@ -1,37 +1,24 @@ -# function.py import numpy as np """ 实验说明: -- 自行编写实现数据加载与预测病马死亡的对率回归算法。 - +- 自行编写实现数据加载与预测病马死亡的对率回归算法。 注意事项: - 在 function.py 中实现对率回归算法。 - 可以自行导入其他库,需要在 requirements.txt 添加依赖,若未在 requirements.txt 中添加使用到的依赖,则无法自动评测,成绩为零。 - 自动评测脚本仅会加载 train_logreg、predict_logreg 和 load_data 函数,请勿修改函数名。 - -测评环境: -- 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 = "202210423130" name = "董秋" -import numpy as np -from sklearn.preprocessing import MinMaxScaler -from sklearn.model_selection import train_test_split - def sigmoid(z): + """计算sigmoid函数""" return 1.0 / (1 + np.exp(-z)) def compute_gradient(X_batch, y_batch, weights, lambda_reg): + """计算梯度,包含L2正则化""" z = np.dot(X_batch, weights) h = sigmoid(z) gradient = np.dot(X_batch.T, (h - y_batch)) / len(y_batch) @@ -39,11 +26,22 @@ def compute_gradient(X_batch, y_batch, weights, lambda_reg): return gradient def train_logreg(X, y, learning_rate=0.001, iterations=10000, batch_size=64, lambda_reg=0.1): + """ + 对率回归训练函数。 + + Args: + - X (numpy array): 特征数据。 + - y (numpy array): 标签数据。 + - learning_rate (float): 学习率。 + - iterations (int): 迭代次数。 + - batch_size (int): 批量大小。 + - lambda_reg (float): L2正则化参数。 + + Returns: + - numpy array: 训练得到的权重。 + """ m, n = X.shape weights = np.random.randn(n) * np.sqrt(2. / n) # He初始化 - best_weights = weights.copy() - best_accuracy = 0 - for _ in range(iterations): indices = np.random.permutation(m) X_shuffled = X[indices] @@ -54,25 +52,35 @@ def train_logreg(X, y, learning_rate=0.001, iterations=10000, batch_size=64, lam y_batch = y_shuffled[j:j + batch_size] gradient = compute_gradient(X_batch, y_batch, weights, lambda_reg) weights -= learning_rate * gradient + + return weights - # 计算训练集准确率 - train_accuracy = accuracy(X, y, weights) - if train_accuracy > best_accuracy: - best_accuracy = train_accuracy - best_weights = weights.copy() +def predict_logreg(inX, weights): + """ + 对率回归预测函数。 - # 动态调整学习率 - if _ % 100 == 0 and train_accuracy > 0.95: # 达到高准确率时减小学习率 - learning_rate *= 0.9 + Args: + - inX (numpy array): 输入待分类的样本。 + - weights (numpy array): 训练得到的权重。 - return best_weights - -def predict_logreg(X, weights): - z = np.dot(X, weights) + Returns: + - int: 预测的分类标签。 + """ + z = np.dot(inX, weights) h = sigmoid(z) - return np.where(h >= 0.5, 1, 0) + return 1 if h >= 0.5 else 0 def load_data(filepath): + """ + 从文件中加载数据,若不自行正确实现,则无法通过评测,**不记录成绩**。 + + Args: + - filepath (str): 数据文件路径。 + + Returns: + - np.array: 特征数据。 + - np.array: 标签数据。 + """ data, labels = [], [] with open(filepath, 'r') as f: for line in f: @@ -82,41 +90,30 @@ def load_data(filepath): data.append(line_data) labels.append(int(line[-1])) + # 将数据转换为numpy数组 data = np.array(data) labels = np.array(labels) - # 将标签二分类化,2和3为0,其余为1 + # 特征选择:去掉特征3、特征24~28 + # 特征3的索引是2,特征24~28的索引是23到27 + data = np.delete(data, [2] + list(range(23, 28)), axis=1) + + # 将标签二分类化,2(死亡)和3(安乐死)合并为0,其余为1 target_variable = np.where((labels == 2) | (labels == 3), 0, 1) return data, target_variable -def accuracy(X, y, weights): - predictions = predict_logreg(X, weights) - return np.mean(predictions == y) - if __name__ == "__main__": - # 加载数据 - X, y = load_data("./data/horse-colic.data") - - # 拆分训练集和验证集 - X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=42) - - # 数据归一化 - scaler = MinMaxScaler() - X_train = scaler.fit_transform(X_train) - X_val = scaler.transform(X_val) - - # 训练模型 - final_weights = train_logreg(X_train, y_train, learning_rate=0.001, iterations=10000, batch_size=64, lambda_reg=0.1) - - # 验证模型 - val_accuracy = accuracy(X_val, y_val, final_weights) - print(f"验证集的准确率: {val_accuracy:.4f}") + # 以下代码可用于测试,可自行随意修改 + # 加载训练集 + X_train, y_train = load_data("./data/horse-colic.data") # 加载测试集 X_test, y_test = load_data("./data/horse-colic.test") - X_test = scaler.transform(X_test) - # 测试模型 - final_test_accuracy = accuracy(X_test, y_test, final_weights) - print(f"最终测试集的准确率: {final_test_accuracy:.4f}") + # 训练对率回归模型 + weights = train_logreg(X_train, y_train, learning_rate=0.01, iterations=1000) + + # 测试单个数据 + y_pred = predict_logreg(X_test[11], weights) + print(f"预测结果: {y_pred}, 实际结果: {y_test[11]}")