From c37541ef3af83cbfac1cafa1eed0258404f24994 Mon Sep 17 00:00:00 2001 From: Xionghaoran <719929980@qq.com> Date: Thu, 31 Oct 2024 16:17:16 +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 | 112 ++++++++++++++++++++++++++++------------------------ 1 file changed, 60 insertions(+), 52 deletions(-) diff --git a/function.py b/function.py index f6fa7d8..6e0e038 100644 --- a/function.py +++ b/function.py @@ -1,83 +1,91 @@ +# function.py import numpy as np -# 填写学号和姓名 -id = "202210423213" # 请替换为实际学号 -name = "熊浩燃" # 请替换为实际姓名 +""" +实验说明: +- 自行编写实现数据加载与预测病马死亡的对率回归算法。 +注意事项: +- 在 function.py 中实现对率回归算法。 +- 可以自行导入其他库,需要在 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 +""" -def sigmoid(z): - """计算Sigmoid函数值""" - return 1 / (1 + np.exp(-z)) +id = "202210423213" +name = "熊浩燃" -def train_logreg(X, y, learning_rate=0.01, iterations=5000, reg_lambda=0.1): +# 对率回归训练函数 +def train_logreg(X, y, learning_rate=0.01, iterations=1000): """ - 对率回归训练函数,带正则化项。 - + 对率回归训练函数。 Args: - X (numpy array): 特征数据。 - y (numpy array): 标签数据。 - learning_rate (float): 学习率,默认为0.01。 - - iterations (int): 梯度下降迭代次数,默认为5000。 - - reg_lambda (float): L2正则化系数,默认为0.1。 - + - iterations (int): 迭代次数,默认为1000。 Returns: - numpy array: 训练得到的权重。 """ - # 数据标准化 - X = (X - X.mean(axis=0)) / X.std(axis=0) - # 初始化权重 weights = np.zeros(X.shape[1]) - - # 批量梯度下降 + for i in range(iterations): - predictions = sigmoid(np.dot(X, weights)) - errors = y - predictions - # 更新权重,带L2正则化 - weights += learning_rate * (np.dot(X.T, errors) - reg_lambda * weights) - + # 预测值:通过对率回归模型得到 + z = np.dot(X, weights) + predictions = 1 / (1 + np.exp(-z)) + + # 计算梯度并更新权重 + gradient = np.dot(X.T, (predictions - y)) / y.size + weights -= learning_rate * gradient + + # 可选:输出损失,帮助调试 + if i % 100 == 0: + loss = -np.mean(y * np.log(predictions) + (1 - y) * np.log(1 - predictions)) + print(f"迭代 {i},损失: {loss}") + return weights -def predict_logreg(inX, weights, threshold=0.3): +# 对率回归预测函数 +def predict_logreg(inX, weights): """ - 对率回归预测函数,包含自定义阈值。 - + 对率回归预测函数。 Args: - inX (numpy array): 输入待分类的样本。 - weights (numpy array): 训练得到的权重。 - - threshold (float): 分类阈值,默认为0.3。 - Returns: - int: 预测的分类标签。 """ - probability = sigmoid(np.dot(inX, weights)) - return 1 if probability >= threshold else 0 + probability = 1 / (1 + np.exp(-np.dot(inX, weights))) + return 1 if probability >= 0.5 else 0 +# 数据加载函数 def load_data(filepath): """ - 从文件中加载数据,并填充缺失值。 - + 从文件中加载数据。 Args: - filepath (str): 数据文件路径。 - Returns: - - np.array: 特征数据。 - - np.array: 标签数据。 + - numpy array: 特征数据。 + - numpy array: 标签数据。 """ - data = np.genfromtxt(filepath, delimiter=" ", dtype=float, missing_values="?", filling_values=np.nan) - - # 对每一列单独填充缺失值 - for i in range(data.shape[1] - 1): # 最后一列是标签列 - if np.isnan(data[:, i]).any(): - # 使用中位数填充数值型数据 - median = np.nanmedian(data[:, i]) - data[np.isnan(data[:, i]), i] = median - - # 标准化特征数据 - X = data[:, :-1] - y = data[:, -1] - X = (X - X.mean(axis=0)) / X.std(axis=0) - - return X, y + data = [] + labels = [] + with open(filepath, 'r') as file: + for line in file: + # 去除无效行,并将数据转换为float格式 + fields = line.strip().split() + if '?' not in fields: + # 以最后一列作为标签,其余列作为特征 + features = [float(x) for x in fields[:-1]] + label = float(fields[-1]) + data.append(features) + labels.append(label) + + return np.array(data), np.array(labels) if __name__ == "__main__": # 加载训练集 @@ -87,8 +95,8 @@ if __name__ == "__main__": X_test, y_test = load_data("./data/horse-colic.test") # 训练对率回归模型 - weights = train_logreg(X_train, y_train, learning_rate=0.01, iterations=5000, reg_lambda=0.1) + weights = train_logreg(X_train, y_train, learning_rate=0.01, iterations=1000) - # 使用自定义阈值测试单个数据 - y_pred = predict_logreg(X_test[11], weights, threshold=0.3) + # 测试单个数据 + y_pred = predict_logreg(X_test[11], weights) print(f"预测结果: {y_pred}, 实际结果: {y_test[11]}")