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

如何用Python基于损失函数实现线性回归的w与b求解及模型构建

线性回归模型构建学习笔记与问题解答

我的目标

创建一个ipynb文件,学习线性回归模型(Linear Regression Model)的构建方法。

技术疑问

  1. 线性回归模型的初始w和b应如何设置?是否需要随机初始化?
  2. 迭代过程中何时调整w或b?
  3. 每次迭代时w或b的更新幅度应为多少?

预期实现效果

  1. 构建一个包含__init__和fit方法的Model类;
  2. fit方法需在每次迭代中对w或b进行增减调整。

已完成的工作

1. 数据可视化图表绘制

plt.xlim(-2, 11)
plt.ylim(-2, 11)

x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
y = [-1, 2, 1, 4, 3, 6, 5, 8, 7, 10, 9]
plt.plot(x, y, 'ro')

# y = x
x = [0,10]
y = [0,10]
plt.plot(x, y)

# fill_between
x = [0, 10]
y1 = [-1, 9]
y2 = [1, 11]
plt.fill_between(x, y1, y2, alpha=0.2)

del x, y

2. 损失函数实现

# Dots
x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
y = [-1, 2, 1, 4, 3, 6, 5, 8, 7, 10, 9]

# calculated from y = 1x + 0
ŷ = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# 线性回归的损失函数为(ŷ - y)²,也叫残差平方
def calculate_linear_regression_loss_function(ŷ: list[int], y: list[int]) -> list[int]:
  # 转换为numpy数组简化计算
  np_ŷ = np.array(ŷ)
  np_y = np.array(y)
  # 计算预测值与真实值的差值
  distances = np_ŷ - np_y
  # 差值平方
  squares = distances ** 2
  # 返回平方和
  return squares.sum()

print(calculate_linear_regression_loss_function(ŷ, y))

del x, ŷ, y

3. 训练数据生成及拆分函数实现

生成训练数据

def generate_training_data(n: int) -> list[list[int]]:
    training_data: list[list[int]] = []

    for _ in range(n):
        x = randrange(0, 1000) / 100
        y = randrange(0, 1000) / 100
        training_data.append([x, y])

    return training_data

generate_training_data(n=10)

拆分训练数据为x和y

def separate_training_data_into_x_y(training_data: list[list[int]]) -> tuple[list[int], list[int]]:
    array = np.array(training_data)
    return array[:,0], array[:, 1]

training_data = generate_training_data(n=10)
print("training_data", training_data)

x_training, y_training = separate_training_data_into_x_y(training_data=training_data)
print("x_training", x_training)

可视化生成的训练数据

training_data = generate_training_data(10)
x_training, y_training = separate_training_data_into_x_y(training_data=training_data)

plt.plot(x_training, y_training, 'ro')

示例疑问:如何估算下图中线性回归模型的初始w和b

线性回归数据分布图


待完善代码

目前Model类尚未完成,需先理解线性回归核心逻辑再完善:

# 深度学习的目标是最小化损失函数的值
# 以线性回归y = w*x + b为例,权重w和偏置b会在训练过程中调整
# 损失函数为(ŷ - y)²,其中ŷ是预测值,y是真实值

from typing import Callable

class Model:
    x_train: list[list[int]]
    loss_function: Callable[[int, int], int]

    def __init__(self,
                 loss_function: Callable[[int, int], int]):
        self.loss_function = loss_function
        
    def fit(self, x_training: list[list[int]], y_training: list[int]):
        self.x_training = x_training
        self.y_training = y_training
        print(self.loss_function(3,1))

loss_function: Callable[[int, int], int] = lambda ŷ, y: (ŷ - y)**2
model = Model(loss_function)
model.fit([[1], [1]], [1])

技术疑问解答

1. 初始w和b的设置方式

线性回归的参数初始化分两种场景:

  • 若使用批量梯度下降(BGD)或最小二乘法解析解:无需随机初始化,直接设为0即可,因为线性回归的损失函数是凸函数,不会陷入局部最优;
  • 若使用随机/小批量梯度下降(SGD/MBGD):可以从[-0.1, 0.1]的均匀分布随机采样初始化,也可以直接设为0,随机初始化仅在极少数情况下能加快收敛。
    针对你提供的数据分布图,也可以通过可视化粗略估算:比如数据整体斜率接近1,截距接近0,用这个值作为初始参数能大幅加快收敛速度。

2. 迭代过程中何时调整w或b

每次计算完损失函数的梯度后,就需要调整w和b。梯度代表当前参数下损失函数增大的方向,我们要朝着梯度的反方向更新参数,才能让损失函数持续减小:

  • 批量梯度下降:遍历完所有训练数据,计算一次全局梯度,更新一次参数;
  • 随机梯度下降:每遍历一个样本,计算一次梯度并更新参数;
  • 小批量梯度下降:每遍历一小批样本,计算梯度并更新参数。

3. w和b的更新幅度

更新幅度由学习率(learning rate)和梯度值共同决定,公式为:

w = w - learning_rate * dL/dw
b = b - learning_rate * dL/db

其中dL/dw是损失函数对w的偏导数,dL/db是对b的偏导数:

  • 学习率是手动调整的超参数:太小会导致收敛过慢,太大可能导致损失函数震荡甚至发散,通常从0.001、0.01、0.1这类值开始尝试;
  • 梯度值反映参数对损失的影响程度:梯度越大,说明参数对损失的影响越强,更新幅度也会越大。

完善后的线性回归Model类

结合上述逻辑,完善后的Model类包含参数初始化、梯度计算、迭代更新逻辑:

import numpy as np
from typing import Callable

class LinearRegressionModel:
    def __init__(self, loss_function: Callable[[np.ndarray, np.ndarray], float], learning_rate: float = 0.01):
        self.loss_function = loss_function
        self.learning_rate = learning_rate
        self.w = None  # 权重参数
        self.b = None  # 偏置参数

    def _predict(self, x: np.ndarray) -> np.ndarray:
        # 线性回归预测公式:ŷ = w*x + b
        return self.w * x + self.b

    def _compute_gradients(self, x: np.ndarray, y: np.ndarray) -> tuple[float, float]:
        # 计算损失函数对w和b的梯度(基于均方误差损失)
        ŷ = self._predict(x)
        error = ŷ - y
        dw = (2 / len(x)) * np.sum(error * x)
        db = (2 / len(x)) * np.sum(error)
        return dw, db

    def fit(self, x_training: np.ndarray, y_training: np.ndarray, epochs: int = 1000):
        # 初始化参数:这里设为0,也可以随机初始化
        self.w = 0.0
        self.b = 0.0
        # 转换为numpy数组方便计算
        x_train = np.array(x_training)
        y_train = np.array(y_training)

        for epoch in range(epochs):
            # 计算梯度
            dw, db = self._compute_gradients(x_train, y_train)
            # 更新参数
            self.w -= self.learning_rate * dw
            self.b -= self.learning_rate * db
            # 每100轮打印一次损失,监控训练过程
            if epoch % 100 == 0:
                ŷ = self._predict(x_train)
                loss = self.loss_function(ŷ, y_train)
                print(f"Epoch {epoch}: Loss = {loss:.4f}, w = {self.w:.4f}, b = {self.b:.4f}")

# 定义均方误差损失函数
def mean_squared_error(ŷ: np.ndarray, y: np.ndarray) -> float:
    return np.mean((ŷ - y)**2)

# 测试模型
if __name__ == "__main__":
    # 示例数据
    x = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
    y = np.array([-1, 2, 1, 4, 3, 6, 5, 8, 7, 10, 9])
    # 创建模型
    model = LinearRegressionModel(loss_function=mean_squared_error, learning_rate=0.01)
    # 训练模型
    model.fit(x, y, epochs=2000)
    # 测试预测
    print(f"\n预测x=11的值:{model._predict(11):.4f}")

内容的提问来源于stack exchange,提问作者Jason Rich Darmawan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 01:19:55