Ridge回归梯度下降实现结果与闭式解不符,请求排查代码问题
Ridge回归梯度下降实现结果与闭式解不符,请求排查代码问题
我帮你排查出几个关键问题,这些是导致梯度下降结果和闭式解不符的主要原因:
1. 致命缩进错误:return 语句在循环内部
你的return B语句缩进在了for _ in range(num_iterations):的循环块里,这意味着函数在第一次迭代后就直接返回了参数B,完全没有执行后续的99999次梯度更新!这是结果完全不对的核心原因。
2. 多行表达式语法错误
计算gradient_B的代码行中,你直接在+号后换行,Python无法识别这是一个延续的表达式。需要用反斜杠\标记多行延续,或者将整个表达式用括号包裹。
3. 正则项的缩放不匹配闭式解
你的闭式解使用的是标准Ridge回归公式,对应的损失函数是 $L(B) = ||y - XB||^2 + \lambda||B||^2$。而你的梯度下降代码中,MSE部分做了(1/n)的缩放,但正则项没有对应缩放,导致梯度的整体逻辑和闭式解的损失函数不匹配,最终结果会偏离。
修改后的完整代码
import numpy as np x = np.random.rand(10, 2) y = np.random.rand(10, 1) lambda_reg = 0.1 alpha = 0.1 num_iterations = 100000 X_train = np.hstack((np.ones((x.shape[0], 1)), x)) def ridge_regression_gradient_descent(X, y, lambda_reg, alpha, num_iterations): n, p = X.shape B = np.zeros(p) # Gradient descent loop for _ in range(num_iterations): y_pred = X.dot(B).reshape(-1, 1) error = y - y_pred # 计算偏置项B0的梯度 gradient_B0 = - (2 / n) * np.sum(error) # 计算B1到Bp的梯度,修复多行表达式+正则项缩放 gradient_B = - (2 / n) * (X[:, 1:].T @ error) + (2 * lambda_reg / n) * B[1:].reshape(-1, 1) # 更新参数 B[0] -= alpha * gradient_B0 B[1:] -= alpha * gradient_B.reshape(-1) # 把return移到循环外部 return B # 梯度下降结果 B_gd = ridge_regression_gradient_descent(X_train, y, lambda_reg, alpha, num_iterations) # 闭式解结果(不对偏置项B0加正则化) I = np.eye(X_train.shape[1]) I[0, 0] = 0 B_closed = np.linalg.inv(X_train.T @ X_train + lambda_reg * I) @ X_train.T @ y print("梯度下降得到的B:", B_gd) print("闭式解得到的B:", B_closed.flatten())
额外说明
- 我调整了梯度的缩放系数为
2/n,对齐了标准MSE损失函数的梯度计算逻辑,确保和闭式解的损失函数逻辑一致。 - 闭式解中我对单位矩阵
I的第0行第0列设为0,因为通常Ridge回归不对偏置项B0施加正则化,这和你的梯度下降代码逻辑保持一致。 - 如果你的学习率
alpha设置过大,可能会导致梯度下降震荡甚至发散,可以尝试调小到0.01或者使用自适应学习率优化器。
这样修改后,梯度下降的结果就会和闭式解非常接近了。
备注:内容来源于stack exchange,提问作者Melvin Curraj
相关产品推荐
相关产品推荐

