什么是线性回归?
线性回归是一种用于预测数值型结果的统计方法,它通过建立一个或多个自变量(输入特征)与因变量(输出目标)之间的线性关系模型来工作。在最简单的形式中,即简单线性回归,仅涉及一个自变量和一个因变量,而多变量线性回归则考虑了多个自变量。
数学表达
在线性回归中,假设自变量 x x x 和因变量 y y y 之间存在线性关系,可以表示为:
y = θ 0 + θ 1 x + ϵ y = \theta_0 + \theta_1 x + \epsilon y=θ0+θ1x+ϵ
其中, θ 0 \theta_0 θ0 是截距项, θ 1 \theta_1 θ1 是斜率参数,描述了 x x x 对 y y y 的影响程度,而 ϵ \epsilon ϵ 表示误差项,代表了未被模型捕捉到的变异性。
损失函数
为了找到最佳拟合直线,我们定义了一个损失函数,通常采用均方误差(Mean Squared Error, MSE)的形式:
J ( θ ) = 1 2 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) 2 J(\theta) = \frac{1}{2m} \sum_{i=1}^{m} (h_\theta(x^{(i)}) - y^{(i)})^2 J(θ)=2m1i=1∑m(hθ(x(i))−y(i))2
这里, h θ ( x ) h_\theta(x) hθ(x)是模型的预测值, y ( i ) y^{(i)} y(i) 是实际值, m m m 是样本数量。
参数估计
为了最小化损失函数 J ( θ ) J(\theta) J(θ),我们使用梯度下降法或正规方程等方法来更新参数 θ \theta θ。这些方法旨在寻找一组参数值,使得模型对训练数据的预测尽可能准确。
梯度下降法
梯度下降是一种迭代优化算法,它通过沿着损失函数的负梯度方向调整参数来逐步减少损失。更新规则如下:
θ j : = θ j − α ∂ ∂ θ j J ( θ ) \theta_j := \theta_j - \alpha \frac{\partial}{\partial \theta_j} J(\theta) θj:=θj−α∂θj∂J(θ)
其中, α \alpha α 是学习率,控制每次更新的步长大小。线性回归利用梯度下降法进行参数更新的公式推导如下:
- 定义损失函数:首先,定义线性回归的损失函数(通常为均方误差,Mean Squared Error, MSE):
J ( θ ) = 1 2 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) 2 J(\theta) = \frac{1}{2m} \sum_{i=1}^{m} (h_\theta(x^{(i)}) - y^{(i)})^2 J(θ)=2m1i=1∑m(hθ(x(i))−y(i))2
其中:
- h θ ( x ( i ) ) = θ T x ( i ) h_\theta(x^{(i)}) = \theta^T x^{(i)} hθ(x(i))=θTx(i) 是模型的预测值。
- y ( i ) y^{(i)} y(i) 是实际值。
- m m m 是训练样本的数量。
-
求导:为了最小化损失函数 J ( θ ) J(\theta) J(θ),我们需要对参数 θ \theta θ 求导,并令导数等于0。具体来说,我们对每个参数 θ j \theta_j θj 偏导数:
∂ ∂ θ j J ( θ ) = ∂ ∂ θ j ( 1 2 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) 2 ) \frac{\partial}{\partial \theta_j} J(\theta) = \frac{\partial}{\partial \theta_j} \left( \frac{1}{2m} \sum_{i=1}^{m} (h_\theta(x^{(i)}) - y^{(i)})^2 \right) ∂θj∂J(θ)=∂θj∂(2m1i=1∑m(hθ(x(i))−y(i))2) -
计算偏导数:计算上述表达式的偏导数 ∂ ∂ θ j J ( θ ) = 1 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) ⋅ ∂ ∂ θ j h θ ( x ( i ) ) \frac{\partial}{\partial \theta_j} J(\theta) = \frac{1}{m} \sum_{i=1}^{m} (h_\theta(x^{(i)}) - y^{(i)}) \cdot \frac{\partial}{\partial \theta_j} h_\theta(x^{(i)}) ∂θj∂J(θ)=m1i=1∑m(hθ(x(i))−y(i))⋅∂θj∂hθ(x(i))
由于 h θ ( x ( i ) ) = θ T x ( i ) h_\theta(x^{(i)}) = \theta^T x^{(i)} hθ(x(i))=θTx(i),所以: ∂ ∂ θ j h θ ( x ( i ) ) = x j ( i ) \frac{\partial}{\partial \theta_j} h_\theta(x^{(i)}) = x_j^{(i)} ∂θj∂hθ(x(i))=xj(i)
因此: ∂ ∂ θ j J ( θ ) = 1 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) x j ( i ) \frac{\partial}{\partial \theta_j} J(\theta) = \frac{1}{m} \sum_{i=1}^{m} (h_\theta(x^{(i)}) - y^{(i)}) x_j^{(i)} ∂θj∂J(θ)=m1i=1∑m(hθ(x(i))−y(i))xj(i)
-
更新规则:为了最小化损失函数,我们沿着负梯度方向更新参数 θ j \theta_j θj:
θ j : = θ j − α ∂ ∂ θ j J ( θ ) \theta_j := \theta_j - \alpha \frac{\partial}{\partial \theta_j} J(\theta) θj:=θj−α∂θj∂J(θ)代入上面的偏导数结果: θ j : = θ j − α 1 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) x j ( i ) \theta_j := \theta_j - \alpha \frac{1}{m} \sum_{i=1}^{m} (h_\theta(x^{(i)}) - y^{(i)}) x_j^{(i)} θj:=θj−αm1i=1∑m(hθ(x(i))−y(i))xj(i)
-
最终更新公式
整理得到最终的参数更新公式:
θ j : = θ j − α 1 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) x j ( i ) \theta_j := \theta_j - \alpha \frac{1}{m} \sum_{i=1}^{m} (h_\theta(x^{(i)}) - y^{(i)}) x_j^{(i)} θj:=θj−αm1i=1∑m(hθ(x(i))−y(i))xj(i)
这就是线性回归中使用梯度下降法进行参数更新的公式。
python
import numpy as np
def linear_regression_gradient_descent(X: np.ndarray, y: np.ndarray, alpha: float, iterations: int) -> np.ndarray:
m, n = X.shape
theta = np.zeros((n, 1))
for _ in range(iterations):
predictions = X @ theta
errors = predictions - y.reshape(-1, 1)
updates = X.T @ errors / m
theta -= alpha * updates
return np.round(theta.flatten(), 4)
正规方程
对于某些问题,可以直接求解最优参数,无需迭代过程。这可以通过解下面的正规方程完成:
θ = ( X T X ) − 1 X T y \theta = (X^T X)^{-1} X^T y θ=(XTX)−1XTy
这种方法适用于当特征数量不多且矩阵可逆时的情况。具体推导过程如下:
线性回归参数更新公式的推导如下:
-
目标函数:线性回归的目标是找到一组参数 θ \theta θ,使得预测值 h θ ( x ) h_\theta(x) hθ(x) 与实际值 y y y 之间的误差最小。通常使用均方误差(Mean Squared Error, MSE)作为损失函数:
J ( θ ) = 1 2 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) 2 J(\theta) = \frac{1}{2m} \sum_{i=1}^{m} (h_\theta(x^{(i)}) - y^{(i)})^2 J(θ)=2m1i=1∑m(hθ(x(i))−y(i))2其中, h θ ( x ) = θ T x h_\theta(x) = \theta^T x hθ(x)=θTx 是预测值, x ( i ) x^{(i)} x(i) 和 y ( i ) y^{(i)} y(i) 分别是第 i i i 个训练样本的特征向量和目标值。
-
损失函数的矩阵形式:将上述公式转换为矩阵形式,设 X X X 是特征矩阵(每一行是一个训练样本,每一列是一个特征), y y y 是目标值向量,则损失函数可以写为:
J ( θ ) = 1 2 m ( X θ − y ) T ( X θ − y ) J(\theta) = \frac{1}{2m} (X\theta - y)^T (X\theta - y) J(θ)=2m1(Xθ−y)T(Xθ−y) -
求导:为了找到使损失函数最小化的 θ \theta θ,需要对 θ \theta θ 导,并令导数等于0。首先计算损失函数关于 θ \theta θ 的导数:
∇ θ J ( θ ) = 1 m X T ( X θ − y ) \nabla_\theta J(\theta) = \frac{1}{m} X^T (X\theta - y) ∇θJ(θ)=m1XT(Xθ−y) -
设置导数为0:令导数等于0,得到:
1 m X T ( X θ − y ) = 0 \frac{1}{m} X^T (X\theta - y) = 0 m1XT(Xθ−y)=0化简得:
X T X θ = X T y X^T X \theta = X^T y XTXθ=XTy -
解方程:假设 X T X X^T X XTX 是非奇异的(即可逆),则可以通过两边同时左乘 ( X T X ) − 1 (X^T X)^{-1} (XTX)−1 得到:
θ = ( X T X ) − 1 X T y \theta = (X^T X)^{-1} X^T y θ=(XTX)−1XTy
这就是线性回归中使用正规方程(Normal Equation)来求解参数 θ \theta θ 的过程。
python
import numpy as np
def linear_regression_normal_equation(X: list[list[float]], y: list[float]) -> list[float]:
# Your code here, make sure to round
X = np.array(X)
y = np.array(y).reshape(-1, 1)
X_T = X.T
theta = np.linalg.inv(X_T @ X) @ X_T @ y
theta = np.round(theta, 4).flatten().tolist()
return theta
实际应用
当然线性回归也是可以捕捉到数据中的非线性关系的,只需要在数据中进行预处理即可。比如,当利用变量 ( x 1 , x 2 ) (x_1, x_2) (x1,x2)预测房价 y y y,我们可以手动添加特征 x 1 2 , x 1 x 2 x_1^{2},x_1x_2 x12,x1x2之类经过非线性变换后的变量,这样就可以让线性回归学习到非线性关系了!更细致的线性回归讲解可以参考Google Crash Courese 线性回归