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

线性回归调优问题:学习率与方程精度异常(Python)

线性回归梯度下降不收敛问题排查与修复

我尝试用0.01的学习率调优线性回归模型,但拟合直线无法正常收敛,参数更新路径不符合预期,反而出现随机偏移。确认问题不在学习率,而是模型参数更新方程有误。

原实现代码

from sklearn.datasets import make_regression, make_classification, make_blobs
import matplotlib.pyplot as plt
import numpy as np
import random as rd

# 生成回归数据集
x, y = make_regression(
  n_samples=100,
  n_features=1,
  noise=30
)

# 划分训练集和测试集
train_x = x[:-20]
test_x = x[-20:]

train_y = y[:-20]
test_y = y[-20:]

# 绘图函数
def graph_linear_regression():
  # 绘制数据点
  plt.scatter(train_x, train_y, color='blue', label='Data')

  # 绘制回归直线(原错误:直接画y=x)
  plt.plot(train_x, train_x, color='red', label='Linear Regression')

  # 添加标签和标题
  plt.xlabel('x')
  plt.ylabel('y')
  plt.title('Linear Regression')

  # 显示图例和图像
  plt.legend()
  plt.show()

# 参数更新函数(原错误核心)
def calculate_update_error():
  global m
  global b
  learning_rate = 0.01
  # 原注释的公式也有误
  M = 1 / n * np.sum(f(train_x) - train_y)
  B = 1 / n * np.sum(np.sum(f(train_x) - train_y) * train_x)

  m = m - learning_rate * M
  b = b - learning_rate * B

# 初始化参数
m = rd.randint(1, 100)
b = rd.randint(1, 100)
n = len(train_x)
learning_rate = 0.01

print(f"n: {n}")
print(f"m: {m}")
print(f"b: {b}")
print(f"learning_rate: {learning_rate}")

# 线性回归预测函数
def f(x):
  return m * x + b

# 迭代更新参数(原错误:迭代次数不足)
for i in range(n):
  calculate_update_error()
  print()

graph_linear_regression()

当前问题表现

拟合直线与数据点严重偏离,无收敛趋势,参数更新出现随机偏移。
期望达到:最小二乘法的拟合效果(直线贴合数据点的整体分布趋势)


错误分析与修复方案

1. 梯度计算公式错误(核心问题)

线性回归用MSE作为损失函数,对参数m(斜率)和b(截距)的梯度推导如下:

  • 损失函数:$L = \frac{1}{2n}\sum_{i=1}^n (f(x_i)-y_i)^2$,其中$f(x_i)=m x_i + b$
  • 对m求导:$\frac{\partial L}{\partial m} = \frac{1}{n}\sum_{i=1}^n (f(x_i)-y_i) \cdot x_i$
  • 对b求导:$\frac{\partial L}{\partial b} = \frac{1}{n}\sum_{i=1}^n (f(x_i)-y_i)$

原代码的错误:

  • m的梯度少乘了x,导致更新方向错误
  • b的梯度多了一层sum且错误乘以x,导致梯度被错误放大

2. 绘图函数错误

原代码中plt.plot(train_x, train_x, ...)直接绘制了y=x的直线,完全没有使用训练得到的m和b,无法展示模型的拟合效果,应改为绘制f(train_x)。

3. 迭代次数不足

梯度下降需要足够多的迭代轮次才能让参数收敛,原代码只迭代了80次(训练集样本数),通常需要几百到几千次迭代。


修正后的完整代码

from sklearn.datasets import make_regression
import matplotlib.pyplot as plt
import numpy as np
import random as rd

# 生成回归数据集
x, y = make_regression(
  n_samples=100,
  n_features=1,
  noise=30,
  random_state=42  # 加随机种子保证可复现
)

# 划分训练集和测试集
train_x = x[:-20]
train_y = y[:-20]

# 绘图函数修复
def graph_linear_regression():
  plt.scatter(train_x, train_y, color='blue', label='Data')
  # 使用模型预测值绘制回归直线
  plt.plot(train_x, f(train_x), color='red', label='Linear Regression')
  plt.xlabel('x')
  plt.ylabel('y')
  plt.title('Linear Regression')
  plt.legend()
  plt.show()

# 参数更新函数修复
def calculate_update_error():
  global m
  global b
  learning_rate = 0.01
  # 计算预测值与真实值的误差
  error = f(train_x) - train_y
  # 正确计算梯度
  m_gradient = (1 / n) * np.sum(error * train_x)
  b_gradient = (1 / n) * np.sum(error)
  # 更新参数
  m -= learning_rate * m_gradient
  b -= learning_rate * b_gradient

# 初始化参数
m = rd.randint(1, 100)
b = rd.randint(1, 100)
n = len(train_x)
learning_rate = 0.01

print(f"初始参数 - n: {n}, m: {m}, b: {b}, learning_rate: {learning_rate}")

# 线性回归预测函数
def f(x):
  return m * x + b

# 增加迭代次数,比如1000轮
for i in range(1000):
  calculate_update_error()
  # 每100轮打印一次参数变化
  if i % 100 == 0:
    print(f"迭代第{i}轮 - m: {round(m,2)}, b: {round(b,2)}")

graph_linear_regression()

修复效果

修正后模型会逐步收敛,最终拟合直线会贴合数据点的整体趋势,达到接近最小二乘法的效果。

内容的提问来源于stack exchange,提问作者Tincho

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 12:15:26