线性回归实战:从梯度下降到完整实现(附避坑指南)

1次阅读
没有评论

共计 2082 个字符,预计需要花费 6 分钟才能阅读完成。

image.webp

背景痛点:新手常踩的 3 个坑

刚接触线性回归时,我遇到了不少问题,后来发现很多新手都会犯类似的错误。这里总结三个最常见的坑:

线性回归实战:从梯度下降到完整实现(附避坑指南)

  1. 梯度下降不收敛:学习率设得太大导致震荡,或者太小导致收敛过慢
  2. 特征处理不当:没做归一化导致某些特征权重过大,或者忽略了线性对数转换
  3. 代码实现混乱:把数据预处理、模型训练和评估的代码混在一起,难以调试

技术实现:分步拆解线性回归

1. 数据预处理

首先我们需要准备数据。假设我们有一组房价数据,特征是面积,目标是价格。

  • 加载数据并分割为特征 X 和目标 y
  • 对特征做标准化:(X – mean)/std
  • 添加偏置项(全 1 列)
  • 如果数据有指数分布特征,可以尝试对数转换
import numpy as np

# 加载数据
X = np.array([...])  # 特征
Y = np.array([...])  # 目标

# 标准化
X = (X - np.mean(X)) / np.std(X)

# 添加偏置项
X = np.c_[np.ones(X.shape[0]), X]

2. 损失函数计算

线性回归使用均方误差 (MSE) 作为损失函数:

def compute_cost(X, y, theta):
    m = len(y)
    predictions = X.dot(theta)
    cost = (1/(2*m)) * np.sum(np.square(predictions - y))
    return cost

3. 梯度下降实现

这是最核心的部分,注意学习率的选择:

def gradient_descent(X, y, theta, learning_rate, iterations):
    m = len(y)
    cost_history = []

    for _ in range(iterations):
        predictions = X.dot(theta)
        errors = predictions - y
        gradient = (1/m) * X.T.dot(errors)
        theta -= learning_rate * gradient
        cost_history.append(compute_cost(X, y, theta))

    return theta, cost_history

4. 模型评估

训练完成后,我们需要评估模型效果:

  • 计算 R 平方值
  • 绘制学习曲线
  • 检查残差分布
from sklearn.metrics import r2_score

# 预测
y_pred = X.dot(theta)

# R 平方
r2 = r2_score(y, y_pred)
print(f'R-squared: {r2:.3f}')

完整代码示例

import numpy as np
from sklearn.metrics import r2_score

class LinearRegression:
    def __init__(self, learning_rate=0.01, iterations=1000):
        self.learning_rate = learning_rate
        self.iterations = iterations
        self.theta = None
        self.cost_history = []

    def fit(self, X, y):
        # 添加偏置项
        X = np.c_[np.ones(X.shape[0]), X]

        # 初始化参数
        self.theta = np.zeros(X.shape[1])

        # 梯度下降
        m = len(y)
        for _ in range(self.iterations):
            predictions = X.dot(self.theta)
            errors = predictions - y
            gradient = (1/m) * X.T.dot(errors)
            self.theta -= self.learning_rate * gradient
            self.cost_history.append(self._compute_cost(X, y))

        return self

    def _compute_cost(self, X, y):
        m = len(y)
        predictions = X.dot(self.theta)
        return (1/(2*m)) * np.sum(np.square(predictions - y))

    def predict(self, X):
        X = np.c_[np.ones(X.shape[0]), X]
        return X.dot(self.theta)

    def score(self, X, y):
        y_pred = self.predict(X)
        return r2_score(y, y_pred)

避坑指南

  1. 学习率选择:先用 0.01 试运行,观察 cost 变化,太大就减小,太小就增大
  2. 特征缩放:务必将特征标准化,否则梯度下降会很慢
  3. 迭代次数:绘制 cost 曲线,当曲线变平时就可以停止了

性能考量

  • 批量大小 :小批量(32-256) 通常效果不错
  • 迭代次数:一般 1000-5000 次足够
  • 学习率衰减:可以尝试随着迭代逐步减小学习率

思考题

  1. 如果特征和目标之间是非线性关系(比如二次方),该如何处理?
  2. 当特征数量很多时,如何防止过拟合?(提示:正则化)

总结

实现线性回归模型看似简单,但要注意很多细节。通过本文的步骤,你应该已经掌握了从数据预处理到模型评估的全流程。建议动手实现一遍代码,遇到问题时再回来看各个注意事项。记住,实践出真知!

正文完
 0
评论(没有评论)