You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从零实现线性回归Theta参数趋于无穷的解决方法咨询

解决梯度下降中参数趋于无穷/NaN的问题

你遇到的参数发散到无穷、出现NaN的情况,在自定义梯度下降实现中很常见,尤其是处理多项式特征时,主要原因集中在特征未缩放、正则化实现有误以及学习率适配性这几个方面。下面一步步帮你解决:

1. 必须先做特征缩放(最关键)

多项式特征会让不同特征的数值范围变得极其悬殊——比如波士顿数据里rm大概在4-9之间,它的平方就是16-81;而lstat在1-37之间,平方是1-1369,交叉项rm*lstat也会有几十到几百的范围。这种数值范围的巨大差异会导致梯度更新时,不同参数的步长失衡,最终引发参数爆炸。

解决方法:

在生成多项式特征后,对所有特征做标准化(StandardScaler)或者归一化(MinMaxScaler),注意要用训练集的统计量去缩放测试集,避免数据泄露。

修改你的测试脚本:

from sklearn.preprocessing import PolynomialFeatures, StandardScaler

# ... 之前的代码 ...

poly_features = PolynomialFeatures(degree=2)
X_train_poly = poly_features.fit_transform(X_train)
X_test_poly = poly_features.transform(X_test)  # 这里不要用fit_transform,避免测试集重新拟合

# 特征标准化
scaler = StandardScaler()
X_train_poly_scaled = scaler.fit_transform(X_train_poly)
X_test_poly_scaled = scaler.transform(X_test_poly)

# 用缩放后的特征训练模型
mlr_poly = MultivariateLinearRegression(0.001, 'Gradient Descent', 5000, None)  # 可以适当调大学习率,因为缩放后梯度更稳定
mlr_poly.train(X_train_poly_scaled, Y_train)

2. 修复正则化的实现错误

你的正则化代码里,把偏置项(也就是theta的最后一个元素,对应你添加的全1列)也加入了正则化,这是错误的——偏置项不需要正则化,它只是调整预测值的整体偏移,不会导致过拟合。

修改_trainGradientDescent中的正则化部分:

if self._reg_rate != None:
    # 复制theta,避免修改原数组
    theta_without_bias = self._theta.copy()
    theta_without_bias[-1] = 0  # 偏置项不参与正则化
    reg_factor = (1 - (self._learning_rate * self._reg_rate) / self._training_sample)
    self._theta = np.subtract(reg_factor * theta_without_bias, gradient)
else:
    self._theta = np.subtract(self._theta, gradient)

另外,sklearn的Ridge默认会对特征做标准化(如果你没设normalize=False的话),而且它正确排除了偏置项的正则化,这也是它不会发散的原因。

3. 调整学习率和迭代次数

  • 特征缩放后,梯度的量级会更稳定,你可以尝试把学习率从0.0001调到0.001甚至0.01,加快收敛速度。
  • 迭代次数400可能太少,不足以让梯度下降收敛,建议调到5000以上,同时可以监控损失值的变化,当损失不再下降时提前停止(早停机制)。

4. 监控损失值的变化

你注释掉了损失计算的代码,建议恢复它,这样可以直观看到损失是否在下降,还是在震荡/上升:

# 在_trainGradientDescent的循环里恢复损失计算
hypothesis = X.dot(self._theta)
difference = np.subtract(hypothesis, Y)
# 计算MSE损失
cost_val = np.sum(difference ** 2) / (2 * self._training_sample)  # 除以2是为了求导后简化,不影响趋势
self._cost_vals.append(cost_val)

然后可以用matplotlib画出损失曲线,判断模型是否收敛:

plt.plot(range(len(mlr_poly._cost_vals)), mlr_poly._cost_vals)
plt.xlabel('Iterations')
plt.ylabel('MSE Loss')
plt.show()

按照以上步骤修改后,你的模型应该就能稳定收敛,不会出现参数无穷大的问题了。

内容的提问来源于stack exchange,提问作者H. Can

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 07:21:57