diff --git a/function.py b/function.py index ee9d822..72cdde3 100644 --- a/function.py +++ b/function.py @@ -1,4 +1,3 @@ -# function.py import numpy as np """ @@ -8,44 +7,55 @@ import numpy as np - 在 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 """ -id = "202210423xxx" -name = "test_name" +id = "202210423213" +name = "熊浩燃" -# 对率回归训练函数 -def train_logreg(X, y, learning_rate=0.01, iterations=1000): +# 对率回归训练函数,包含调参和优化 +def train_logreg(X, y, learning_rate=0.01, iterations=1000, regularization=0.01, early_stopping_rounds=100): """ - 对率回归训练函数。 + 对率回归训练函数,带有学习率调度和正则化。 Args: - X (numpy array): 特征数据。 - y (numpy array): 标签数据。 - - learning_rate (float): 学习率,默认为0.01。 - - iterations (int): 迭代次数,默认为1000。 + - learning_rate (float): 初始学习率。 + - iterations (int): 最大迭代次数。 + - regularization (float): 正则化参数。 + - early_stopping_rounds (int): 提前停止轮数。 Returns: - numpy array: 训练得到的权重。 """ - # 初始化权重 weights = np.zeros(X.shape[1]) + min_loss = float('inf') + stopping_step = 0 for i in range(iterations): # 预测值:通过对率回归模型得到 z = np.dot(X, weights) predictions = 1 / (1 + np.exp(-z)) - # 计算梯度并更新权重 - gradient = np.dot(X.T, (predictions - y)) / y.size - weights -= learning_rate * gradient + # 计算损失(含正则化项) + loss = -np.mean(y * np.log(predictions) + (1 - y) * np.log(1 - predictions)) + regularization * np.sum(weights**2) - # 可选:输出损失,帮助调试 - if i % 100 == 0: - loss = -np.mean(y * np.log(predictions) + (1 - y) * np.log(1 - predictions)) - print(f"迭代 {i},损失: {loss}") + # 提前停止判断 + if loss < min_loss: + min_loss = loss + stopping_step = 0 + else: + stopping_step += 1 + if stopping_step >= early_stopping_rounds: + print("提前停止于迭代:", i) + break + + # 计算梯度并更新权重(含正则化项) + gradient = (np.dot(X.T, (predictions - y)) + regularization * weights) / y.size + weights -= learning_rate * gradient + + # 学习率调整策略 + if i % 100 == 0 and i != 0: + learning_rate *= 0.9 # 每100轮衰减学习率 + print(f"迭代 {i},损失: {loss},学习率: {learning_rate}") return weights @@ -96,17 +106,56 @@ def load_data(filepath): return data, labels +# 网格搜索函数 +def grid_search(X, y, learning_rates, iterations_list, regularizations): + """ + 网格搜索来优化对率回归模型。 + Args: + - X (numpy array): 特征数据。 + - y (numpy array): 标签数据。 + - learning_rates (list of float): 学习率列表。 + - iterations_list (list of int): 迭代次数列表。 + - regularizations (list of float): 正则化参数列表。 + Returns: + - dict: 包含最佳超参数及其对应的权重。 + """ + best_params = {} + best_weights = None + best_loss = float('inf') + + for lr in learning_rates: + for iters in iterations_list: + for reg in regularizations: + print(f"尝试参数: 学习率={lr}, 迭代次数={iters}, 正则化={reg}") + weights = train_logreg(X, y, learning_rate=lr, iterations=iters, regularization=reg) + z = np.dot(X, weights) + predictions = 1 / (1 + np.exp(-z)) + loss = -np.mean(y * np.log(predictions) + (1 - y) * np.log(1 - predictions)) + print(f"损失: {loss}") + + if loss < best_loss: + best_loss = loss + best_weights = weights + best_params = {'learning_rate': lr, 'iterations': iters, 'regularization': reg} + + print("最佳参数:", best_params) + return best_weights, best_params if __name__ == "__main__": # 加载训练集 X_train, y_train = load_data("./data/horse-colic.data") - # 加载测试集 + # 超参数列表 + learning_rates = [0.001, 0.01, 0.1] + iterations_list = [1000, 2000, 3000] + regularizations = [0.01, 0.1, 1.0] + + # 进行网格搜索以找到最佳超参数组合 + best_weights, best_params = grid_search(X_train, y_train, learning_rates, iterations_list, regularizations) + print("最佳权重:", best_weights) + + # 使用最佳权重进行预测 X_test, y_test = load_data("./data/horse-colic.test") - - # 训练对率回归模型 - 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]}") + y_pred = [predict_logreg(x, best_weights) for x in X_test] + accuracy = np.mean(y_pred == y_test) + print(f"测试集准确率: {accuracy}")