本文参考了周志华老师的《机器学习》(俗称“西瓜书”)。这里是 第三章“线性模型” 的阅读笔记。本文专注于线性回归这一块,并且记录了我的思考,希望对你有所帮助🎉


一、线性模型基本概念

线性模型是机器学习的基础模型之一,假设目标值 (y) 与输入特征 (x) 之间的关系是一个线性组合。

线性回归图片


二、线性回归公式推导

为了推导出最优的 (w) 和 (b),我们需要最小化损失函数 (L(w, b))。以下是完整推导过程:

线性回归推导


三、从零实现线性回归

使用 Python 完全从零实现线性回归,包括数据生成、解析解计算和模型预测。

import numpy as np

# 1. 生成模拟数据
np.random.seed(42)
m = 100  # 样本数量
n = 1    # 特征数量

X = 2 * np.random.rand(m, n)  # 输入特征矩阵
true_w = np.array([[3]])      # 真实权重
true_b = 5                   # 真实偏置

y = X.dot(true_w) + true_b    # 真实目标值
y += np.random.randn(m, 1)    # 添加高斯噪声

# 2. 实现线性回归解析解
def linear_regression(X, y):
    """实现线性回归解析解"""
    m = len(X)
    X_b = np.c_[X, np.ones((m, 1))]  # 添加偏置项 (X_b = [X, 1])
    theta = np.linalg.inv(X_b.T.dot(X_b)).dot(X_b.T).dot(y)  # 解析解公式
    return theta

# 3. 计算权重和偏置
theta = linear_regression(X, y)
w_hat = theta[:-1]  # 权重
b_hat = theta[-1]   # 偏置

print(f"真实权重: {true_w.flatten()}, 预测权重: {w_hat.flatten()}")
print(f"真实偏置: {true_b}, 预测偏置: {b_hat}")

# 4. 预测函数
def predict(X, w, b):
    return X.dot(w) + b

# 5. 可视化结果
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['SimHei']  # 使用黑体
plt.rcParams['axes.unicode_minus'] = False   # 解决负号显示问题


plt.scatter(X, y, color="blue", label="真实数据")
y_pred = predict(X, w_hat, b_hat)
plt.plot(X, y_pred, color="red", label="拟合直线")
plt.xlabel("特征 X")
plt.ylabel("目标 y")
plt.legend()
plt.title("线性回归:从零实现")
plt.show()

四、结果分析

  1. 输出
 真实权重: [3], 预测权重: [2.77011339]
真实偏置: 5, 预测偏置: [5.21509616]
  1. 图像解释
    线性回归python图

    • 蓝点表示真实数据(包含噪声)。
    • 红线表示我们用解析解拟合出的线性回归模型。

五、头脑风暴

1.手写版公式推导过程

2.可以加入梯度下降来优化线性回归

简单解释
梯度下降是一种迭代优化算法,用于通过不断调整参数)来最小化损失函数。相比解析解(直接计算),梯度下降更加适合大规模数据集,因为它避免了矩阵求逆的高计算成本。

主要过程

优点


3.正则化(L1/L2)处理过拟合

简单解释

正则化通过在损失函数中增加一个惩罚项,限制模型参数的大小,从而防止过拟合。主要有两种形式:

正则化的意义


4.更简单的代码显示

4.1. 使用 PyTorch 实现线性回归

代码实现

import torch
import torch.nn as nn
import matplotlib.pyplot as plt
import numpy as np

# 1. 生成数据
np.random.seed(42)
X = 2 * np.random.rand(100, 1).astype(np.float32)
y = 3 * X + 5 + np.random.randn(100, 1).astype(np.float32)  # y = 3X + 5 + 噪声

# 转换为 PyTorch 张量
X_tensor = torch.from_numpy(X)
y_tensor = torch.from_numpy(y)

# 2. 定义模型
class LinearRegressionModel(nn.Module):
    def __init__(self):
        super(LinearRegressionModel, self).__init__()
        self.linear = nn.Linear(1, 1)  # 输入维度 1,输出维度 1

    def forward(self, x):
        return self.linear(x)

# 创建模型实例
model = LinearRegressionModel()

# 3. 定义损失函数和优化器
criterion = nn.MSELoss()  # 均方误差损失
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)  # 随机梯度下降

# 4. 训练模型
epochs = 1000
losses = []

for epoch in range(epochs):
    # 前向传播
    y_pred = model(X_tensor)
    loss = criterion(y_pred, y_tensor)

    # 反向传播和优化
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()

    # 记录损失
    losses.append(loss.item())
    if epoch % 100 == 0:
        print(f"Epoch {epoch}, Loss: {loss.item():.4f}")

# 5. 获取权重和偏置
w, b = model.linear.weight.item(), model.linear.bias.item()
print(f"预测权重: {w:.2f}, 预测偏置: {b:.2f}")

# 6. 结果
y_pred = model(X_tensor).detach().numpy()  # 获取预测值

4.2. 使用 Scikit-learn 实现线性回归(带正则化)

a. 普通线性回归

from sklearn.linear_model import LinearRegression

# 1. 创建模型并训练
model = LinearRegression()
model.fit(X, y)

# 2. 获取权重和偏置
w_hat = model.coef_[0][0]
b_hat = model.intercept_[0]
print(f"预测权重: {w_hat:.2f}, 预测偏置: {b_hat:.2f}")

# 3. 结果
y_pred = model.predict(X)

b. 带正则化的线性回归(Ridge 和 Lasso)

Ridge 回归(L2 正则化)

from sklearn.linear_model import Ridge

# 1. 创建 Ridge 模型
ridge_model = Ridge(alpha=1.0)  # alpha 控制正则化强度
ridge_model.fit(X, y)

# 2. 获取权重和偏置
w_hat = ridge_model.coef_[0][0]
b_hat = ridge_model.intercept_[0]
print(f"Ridge 回归预测权重: {w_hat:.2f}, 预测偏置: {b_hat:.2f}")

# 3. 可结果
y_pred_ridge = ridge_model.predict(X)

Lasso 回归(L1 正则化)

from sklearn.linear_model import Lasso

# 1. 创建 Lasso 模型
lasso_model = Lasso(alpha=0.1)  # alpha 控制正则化强度
lasso_model.fit(X, y)

# 2. 获取权重和偏置
w_hat = lasso_model.coef_[0]
b_hat = lasso_model.intercept_
print(f"Lasso 回归预测权重: {w_hat:.2f}, 预测偏置: {b_hat:.2f}")

# 3. 结果
y_pred_lasso = lasso_model.predict(X)

总结

模型 工具 正则化类型 特点
普通线性回归 Scikit-learn 不限制参数,适合无噪声或低维数据场景。
Ridge 回归 Scikit-learn L2 正则化 限制权重大小,使模型更平滑,适合高维场景。
Lasso 回归 Scikit-learn L1 正则化 特征选择效果好,可使部分特征权重为 0。
自定义线性回归 PyTorch 支持梯度下降 灵活性高,可扩展到复杂深度学习任务。

文章参考