基本概念与数学形式

线性回归是一种监督学习算法,用于找出输入特征目标变量之间的线性关系
它的数学表达式是:

y^=w1x1+w2x2++wnxn+b\hat y = w_1 x_1 + w_2 x_2 + \dots + w_n x_n + b

含义

  • y^\hat y:预测值。
  • xix_i:第 ii 个输入特征
  • wiw_i:特征权重(回归系数,表示该特征对预测的影响)
  • bb:偏置(截距项,整体向上或向下平移预测结果)

分类与层次


各类型详细解释

一元线性回归

  • 特点:只有一个自变量(一个特征)
  • 公式

y^=wx+b\hat y = w x + b

  • 用途:预测单一因素影响的结果
    例如:用房屋面积预测价格。

多元线性回归

  • 特点:有多个自变量(多个特征)
  • 公式

y^=w1x1+w2x2++wnxn+b\hat y = w_1x_1 + w_2x_2 + \dots + w_nx_n + b

  • 用途:同时考虑多个因素的影响
    例如:用面积、位置、房龄等预测房价。

最小二乘法(OLS)

最小二乘法是一种参数估计方法,用于找到使误差平方和最小的模型参数。

它的核心思想是:在已知输入xx与输出yy的数据下,选择模型参数,使预测值与真实值之间的差的平方和最小。

符号介绍

推导过程

一元线性回归

假设我们有以下数据集D={(x(i),y(i))}i=1m\mathcal{D}=\{(x^{(i)}, y^{(i)})\}_{i=1}^m

接下来在图中画一条f(x)=xf(x)=x直线。

再将每个点向函数f(x)f(x)做垂线段,长度即是f(x)y|f(x) - y|,又可以称为真实点坐标yy的值与预测f(x)f(x)的误差,故然可以改为(f(x)y)2(f(x) - y)^2。且由于f(x)f(x)是预测的,可以随意变化为f(x)=2x+1f(x) = 2x + 1f(x)=x+1f(x) = x + 1等。

接下来我们将每个点坐标的误差值相加(f(x(i))y)2\sum (f(x^{(i)})-y)^2后求关于ww的偏导与关于bb的偏导:

S=(f(x(i))y(i))2{Sw=2(f(x(i))y(i))x(i)=0Sb=2(f(x(i))y(i))=0S = \sum (f(x^{(i)}) - y^{(i)})^2\\ \begin{cases} \frac{\partial S}{\partial w} = 2\sum(f(x^{(i)}) - y^{(i)})x^{(i)} = 0 \\ \frac{\partial S}{\partial b} = 2\sum(f(x^{(i)}) - y^{(i)})= 0 \end{cases}

整理后可得:

w=(x(i)xˉ)(y(i)yˉ)(x(i)xˉ)2,b=yˉwxˉw = \frac{\sum(x^{(i)} - \bar x)(y^{(i)} - \bar y)}{\sum(x^{(i)} - \bar x)^2}, b = \bar y - w\bar x

多元线性回归

假设模型为:

y=Xw+ϵ\mathbf{y} = \mathbf{X}\boldsymbol{w} + \boldsymbol{\epsilon}

其中:

  • yRn\mathbf{y} \in \mathbb{R}^n:输出向量
  • XRn×p\mathbf{X} \in \mathbb{R}^{n \times p}:输入矩阵(第一列为1表示截距)
  • wRp\boldsymbol{w} \in \mathbb{R}^p:参数向量
  • ϵ\boldsymbol{\epsilon}:误差向量

最小化:

S(w)=Xwy2S(\boldsymbol{w})=\parallel\mathbf{X}\boldsymbol{w}-\mathbf{y}\parallel^2

展开:

S(w)=(Xwy)T(Xwy)S(\boldsymbol{w})=(\mathbf{X}\boldsymbol{w}-\mathbf{y})^T(\mathbf{X}\boldsymbol{w}-\mathbf{y})

w\boldsymbol{w}求导:

Sw=2XT(Xwy)\frac{\partial S}{\partial \boldsymbol{w}} = 2\mathbf{X}^T(\mathbf{X}\boldsymbol{w}-\mathbf{y})

令导数为0:

XT(Xwy)=0\mathbf{X}^T(\mathbf{X}\boldsymbol{w}-\mathbf{y}) = 0

最终整理得:

w=(XTX)1XTy\boldsymbol{w} = (\mathbf{X}^T\mathbf{X})^{-1}\mathbf{X}^T\mathbf{y}

Python实现

一元最小二乘

import numpy as np

x = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
y = np.array([5.9, 8.1, 10.4, 12.3, 15.0, 17.2, 20.1, 22.0, 25.4, 28.1])

x_mean = np.mean(x)
y_mean = np.mean(y)

w = np.sum((x - x_mean) * (y - y_mean)) / np.sum((x - x_mean)**2)

b = y_mean - w * x_mean

print(f"b = {b:.3f}, w = {w:.3f}")

多元最小二乘

import numpy as np

X = np.array([[1, 1],
[1, 2],
[1, 3],
[1, 4]])
y = np.array([2.1, 4.0, 5.9, 8.1])

w = np.linalg.inv(X.T @ X) @ X.T @ y

print("参数 w:", w)

使用scikit-learn

from sklearn.linear_model import LinearRegression
import numpy as np

X = np.array([[1], [2], [3], [4], [5], [6], [7], [8], [9], [10]])
y = np.array([5.9, 8.1, 10.4, 12.3, 15.0, 17.2, 20.1, 22.0, 25.4, 28.1])

model = LinearRegression()
model.fit(X, y)

print("斜率 w:", model.coef_)
print("截距 b:", model.intercept_)

最终图像

根据以上内容,最终画图后可得到:

梯度下降法(Gradient Descent)

梯度下降是一种优化算法,主要用于找到函数的最小值。在机器学习中,我们用它来最小化损失函数,让模型预测更接近真实值。

直观理解
想象你在一座山谷里,眼睛被蒙住了,想找到山谷的最低点(最小值)。你感觉脚下的坡度,然后沿着坡度下降,每一步走一点,最终慢慢到达谷底。

  • 山谷 → 损失函数(Loss Function)
  • 最低点 → 最优参数
  • 坡度 → 函数的导数/梯度

我们的目标是让损失函数最小,接下来我们将多种损失函数任意一种表述为L(w,b)\mathcal{L}(w,b)

接下来是min L(w,b)min\ \mathcal{L}(w,b)的过程:

一元函数的泰勒展开

对于函数f(x)f(x)x0x_0附近的泰勒展开:

f(x)=f(x0)+f(x0)1!(xx0)+f(x0)2!(xx0)2+f(x0)3!(xx0)3+f(x)=f(x_0)+\frac{f^{\prime}(x_0)}{1!}(x−x_0)+\frac{f^{\prime}{\prime}(x_0)}{2!}(x−x_0)^2+\frac{f^{\prime}{\prime}{\prime}(x_0)}{3!}(x−x0)^3+…

忽略二阶及以上项,得到:

f(x)f(x0)+f(x0)(xx0)f(x) \approx f(x_0) + f{\prime}(x_0)(x-x_0)

为什么能忽略二阶及以上项?

解释一:梯度下降的特点

  • 每次迭代步长很小xx0=ηf(x0)x-x_0 = -\eta f^{\prime}(x_0)
  • 学习率η\eta通常很小(例如:0.01,0.001)
  • 负号不改变步长大小,只改变方向。
  • 所以xx0|x-x_0|很小。

且高阶项的量级随着步长的幂次增长迅速减小:

  • 二阶项:f(x0)2!(xx0)2\frac{f^{\prime}{\prime}(x_0)}{2!}(x-x_0)^2
  • 三阶项:f(x0)3!(xx0)3\frac{f^{\prime}{\prime}{\prime}(x_0)}{3!}(x-x_0)^3
  • (xx0)2(xx0)(x - x_0)^2 \ll (x - x_0)
  • (xx0)3(xx0)2(xx0)(x - x_0)^3 \ll (x - x_0)^2 \ll (x - x_0)

小步长的平方、立方远小于步长本身,故可以忽略其贡献。

解释二:拉格朗日余项(Lagrange remainder)

由于学习率η\eta通常很小且由xx0=ηf(x0)x-x_0 = -\eta f^{\prime}(x_0)显然看出xx01x-x_0 \ll 1
且一元函数一阶泰勒展开的拉格朗日余项为:

R1=f(ξ)2!(xx0)2R_1 = \frac{f{\prime}{\prime}(\xi)}{2!} (x-x_0)^2

其中 ξ[x0,x]\xi \in [x_0, x]。当 xx00|x-x_0| \to 0 时,R10R_1 \to 0,所以一阶近似越来越精确,可舍弃二阶及以上。

解释三:数值计算

假设(xx0)=0.01(x - x_0)=0.01

  • 一阶项:(xx0)0.01(x-x_0)\sim 0.01
  • 二阶项:(xx0)20.0001(x-x_0)^2\sim 0.0001
  • 三阶项:(xx0)30.000001(x-x_0)^3\sim 0.000001

梯度下降条件

为了使得函数值减小:

f(x)<f(x0)    f(x0)(xx0)<0f(x) < f(x_0) \implies f{\prime}(x_0)(x-x_0) < 0

选择沿负梯度方向:

xx0=ηf(x0)x - x_0 = - \eta f{\prime}(x_0)

梯度下降条件为什么使得梯度下降?

从一元函数的一阶泰勒展开看:假设当前位置是xx,下一步更新到x0x_0

f(x0)f(x)+f(x)(x0x)f(x_0)\approx f(x)+f{\prime}(x)(x_0-x)

我们希望新高度比当前低:

f(x0)<f(x)f(x_0)<f(x)

代入一元函数的一阶泰勒展开:

f(x)+f(x)(x0x)<f(x)f(x)+f{\prime}(x)(x_0-x) < f(x)

两边减去f(x)f(x)

f(x)(x0x)<0f{\prime}(x)(x_0-x) < 0

进行分析
f(x)>0f{\prime}(x) > 0(上坡)x0x<0\to x_0 - x < 0 \to 往左走。
f(x)<0f{\prime}(x) < 0(下坡)x0x>0\to x_0 - x > 0 \to 往右走。

梯度下降更新公式与梯度下降怎么沿着梯度相反方向行走?

梯度下降条件为什么使得梯度下降得:

f(x)(x0x)<0f{\prime}(x)(x_0-x) < 0

移项得:

x0x<f(x)x_0-x < -f{\prime}(x)

接下来为了控制每步走多远而引入正数η>0\eta > 0(学习率)即将不等式告诉我们的方向明确告诉我们走多远的移动量x0xx_0-x(用等号定义具体步长,是为了算法可操作):

x0x=ηf(x)x_0-x = -{\eta}f{\prime}(x)

  • -号确保梯度反方向
  • η\eta 控制步长大小

由于η>0\eta > 0(f(x))20(f{\prime}(x))^2 \geq 0不等式成立而最终推导且满足下降条件:

f(x)(x0x)=f(x)(ηf(xt))=η(f(xt))2<0f{\prime}(x)(x_0-x) = f{\prime}(x)(-\eta f{\prime}(x_t)) = -\eta(f{\prime}(x_t))^2 < 0

由上最终得到梯度下降更新公式

x0=xηf(x)x_0 = x - {\eta}f{\prime}(x)

多元梯度下降

假设参数向量wt=[w1,w2,...,wn]T\mathbf{w}_t=[w_1,w_2,...,w_n]^T
梯度定义:

wf(wt)=[fw1fw2fwn]\nabla_\mathbf{w} f(\mathbf{w}_t) = \begin{bmatrix} \frac{\partial f}{\partial w_1} \\ \frac{\partial f}{\partial w_2} \\ \vdots \\ \frac{\partial f}{\partial w_n} \end{bmatrix}

更新公式:

wt+1=wtηwf(wt)\mathbf{w}_{t+1} = w_t - {\eta}{\nabla_\mathbf{w}}f(\mathbf{w_t})

在一元线性回归中的应用

模型:

f(x(i))=wx(i)+bf(x^{(i)}) = w x^{(i)} + b

损失函数(均方误差):

L(w,b)=12mi=1m[wx(i)+by(i)]2\mathcal{L}(w, b) = \frac{1}{2m} \sum_{i=1}^m \left[ w x^{(i)} + b - y^{(i)} \right]^2

ww 求偏导:

Lw=1mi=1m[wx(i)+by(i)]x(i)\frac{\partial \mathcal{L}}{\partial w} = \frac{1}{m} \sum_{i=1}^m \left[ w x^{(i)} + b - y^{(i)} \right] x^{(i)}

bb 求偏导:

Lb=1mi=1m[wx(i)+by(i)]\frac{\partial \mathcal{L}}{\partial b} = \frac{1}{m} \sum_{i=1}^m \left[ w x^{(i)} + b - y^{(i)} \right]

梯度下降更新公式:

wwη1mi=1m[wx(i)+by(i)]x(i)w \gets w - \eta \cdot \frac{1}{m} \sum_{i=1}^m \left[ w x^{(i)} + b - y^{(i)} \right] x^{(i)}

bbη1mi=1m[wx(i)+by(i)]b \gets b - \eta \cdot \frac{1}{m} \sum_{i=1}^m \left[ w x^{(i)} + b - y^{(i)} \right]

Python实现

import numpy as np

#数据集
data = np.array([
[1, 5.9], [2, 8.1], [3, 10.4], [4, 12.3], [5, 15.0],
[6, 17.2], [7, 20.1], [8, 22.0], [9, 25.4], [10, 28.1]
])

X = data[:, 0].reshape(-1, 1) # x^(i)
y = data[:, 1].reshape(-1, 1) # y^(i)
m = X.shape[0] # 样本数

w = np.random.randn(1, 1)
b = 0.0
eta = 0.01
iterations = 4500

print(f"{'迭代':>5} | {'w':>8} | {'b':>8} | {'dw':>10} | {'db':>10} | {'损失值 L':>12}")
print("-"*70)

for t in range(1, iterations + 1):
y_hat = X.dot(w) + b

# 均方误差
L = (1/(2*m)) * np.sum((y_hat - y)**2)

dw = (1/m) * np.sum((y_hat - y) * X) # ∂L/∂w
db = (1/m) * np.sum(y_hat - y) # ∂L/∂b

# 更新参数
w -= eta * dw
b -= eta * db

print(f"{t:5d} | {w[0][0]:8.4f} | {b:8.4f} | {dw:10.4f} | {db:10.4f} | {L:12.6f}")

print("\n训练完成后的参数:")
print(f"权重 w: {w[0][0]:.4f}")
print(f"偏置 b: {b:.4f}")


X_test = np.array([[0], [1], [5], [10]])
y_test_hat = X_test.dot(w) + b
print("\n预测值 ŷ^(i) :", y_test_hat.ravel())

可视化过程

迭代次数: 0

为节约网页性能,仅显示1~19次梯度下降过程,20次为最终收敛结果。