From 058b43f0eccb52be071a26bfcdefbe1045e80c67 Mon Sep 17 00:00:00 2001 From: Xionghaoran <719929980@qq.com> Date: Thu, 31 Oct 2024 16:46:05 +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 | 93 +++++++++++++++-------------------------------------- 1 file changed, 26 insertions(+), 67 deletions(-) diff --git a/function.py b/function.py index 9408735..5031f05 100644 --- a/function.py +++ b/function.py @@ -7,33 +7,17 @@ name = "熊浩燃" # 对率回归训练函数,包含加权损失、正则化、学习率调度和提前停止 def train_logreg(X, y, learning_rate=0.01, iterations=1000, regularization=0.01, early_stopping_rounds=100, class_weights={0: 1, 1: 1}): - """ - 对率回归训练函数,带有加权损失和正则化。 - Args: - - X (numpy array): 特征数据。 - - y (numpy array): 标签数据。 - - learning_rate (float): 初始学习率。 - - iterations (int): 最大迭代次数。 - - regularization (float): 正则化参数。 - - early_stopping_rounds (int): 提前停止轮数。 - - class_weights (dict): 类别权重字典,控制类别不平衡。 - 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)) - # 加权损失 loss = -np.mean(class_weights[1] * y * np.log(predictions) + class_weights[0] * (1 - y) * np.log(1 - predictions)) + regularization * np.sum(weights**2) - # 提前停止判断 if loss < min_loss: min_loss = loss stopping_step = 0 @@ -43,11 +27,9 @@ def train_logreg(X, y, learning_rate=0.01, iterations=1000, regularization=0.01, 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}") @@ -56,99 +38,76 @@ def train_logreg(X, y, learning_rate=0.01, iterations=1000, regularization=0.01, # 对率回归预测函数,带有自定义阈值 def predict_logreg(inX, weights, threshold=0.6): - """ - 对率回归预测函数。 - Args: - - inX (numpy array): 输入待分类的样本。 - - weights (numpy array): 训练得到的权重。 - - threshold (float): 分类决策阈值。 - Returns: - - int: 预测的分类标签。 - """ probability = 1 / (1 + np.exp(-np.dot(inX, weights))) return 1 if probability >= threshold else 0 # 数据加载函数,包含缺失值填充 def load_data(filepath): - """ - 从文件中加载数据,并填充缺失值。 - Args: - - filepath (str): 数据文件路径。 - Returns: - - numpy array: 填充后的特征数据。 - - numpy array: 标签数据。 - """ data = [] labels = [] with open(filepath, 'r') as file: for line in file: - # 去除无效行,并将数据转换为float格式 fields = line.strip().split() - - # 将 '?' 替换为 None features = [float(x) if x != '?' else None for x in fields[:-1]] label = float(fields[-1]) data.append(features) labels.append(label) - # 转换为numpy数组并填充缺失值 data = np.array(data, dtype=float) labels = np.array(labels, dtype=float) - # 处理缺失值,使用平均值填充 col_means = np.nanmean(data, axis=0) indices = np.where(np.isnan(data)) data[indices] = np.take(col_means, indices[1]) return data, labels -# 网格搜索函数 -def grid_search(X, y, learning_rates, iterations_list, regularizations, class_weights_list): - """ - 网格搜索来优化对率回归模型。 - Args: - - X (numpy array): 特征数据。 - - y (numpy array): 标签数据。 - - learning_rates (list of float): 学习率列表。 - - iterations_list (list of int): 迭代次数列表。 - - regularizations (list of float): 正则化参数列表。 - - class_weights_list (list of dict): 类别权重列表。 - Returns: - - dict: 包含最佳超参数及其对应的权重。 - """ +# 暴力搜索函数 +def brute_force_search(X, y, X_test, y_test, learning_rates, iterations_list, regularizations, class_weights_list, thresholds): best_params = {} best_weights = None - best_loss = float('inf') + best_accuracy = 0 for lr in learning_rates: for iters in iterations_list: for reg in regularizations: for cw in class_weights_list: - print(f"尝试参数: 学习率={lr}, 迭代次数={iters}, 正则化={reg}, 类别权重={cw}") - weights = train_logreg(X, y, learning_rate=lr, iterations=iters, regularization=reg, class_weights=cw) - z = np.dot(X, weights) - predictions = 1 / (1 + np.exp(-z)) - loss = -np.mean(cw[1] * y * np.log(predictions) + cw[0] * (1 - y) * np.log(1 - predictions)) - print(f"损失: {loss}") + for threshold in thresholds: + print(f"参数组合: 学习率={lr}, 迭代次数={iters}, 正则化={reg}, 类别权重={cw}, 阈值={threshold}") + weights = train_logreg(X, y, learning_rate=lr, iterations=iters, regularization=reg, class_weights=cw) + y_pred = [predict_logreg(x, weights, threshold=threshold) for x in X_test] + accuracy = np.mean(y_pred == y_test) + print(f"当前组合的测试集准确率: {accuracy}") - if loss < best_loss: - best_loss = loss - best_weights = weights - best_params = {'learning_rate': lr, 'iterations': iters, 'regularization': reg, 'class_weights': cw} + if accuracy > best_accuracy: + best_accuracy = accuracy + best_weights = weights + best_params = {'learning_rate': lr, 'iterations': iters, 'regularization': reg, 'class_weights': cw, 'threshold': threshold} - print("最佳参数:", best_params) + print("最佳参数组合:", best_params) + print("最佳准确率:", best_accuracy) return best_weights, best_params if __name__ == "__main__": # 加载训练集 X_train, y_train = load_data("./data/horse-colic.data") + X_test, y_test = load_data("./data/horse-colic.test") - # 超参数列表 + # 超参数组合列表 learning_rates = [0.001, 0.01, 0.1] iterations_list = [1000, 2000, 3000] regularizations = [0.01, 0.1, 1.0] class_weights_list = [{0: 1, 1: 1}, {0: 1, 1: 2}, {0: 1, 1: 3}] + thresholds = [0.5, 0.55, 0.6, 0.65] + # 进行暴力搜索找到最佳参数组合 + best_weights, best_params = brute_force_search(X_train, y_train, X_test, y_test, learning_rates, iterations_list, regularizations, class_weights_list, thresholds) + print("最佳权重:", best_weights) + + # 使用最佳权重和阈值在测试集上评估 + y_pred = [predict_logreg(x, best_weights, threshold=best_params['threshold']) for x in X_test] + accuracy = np.mean(y_pred == y_test) + print(f"最终测试集准确率: {accuracy}") # 进行网格搜索以找到最佳超参数组合 best_weights, best_params = grid_search(X_train, y_train, learning_rates, iterations_list, regularizations, class_weights_list) print("最佳权重:", best_weights)