楼主: 奠老板
220 0

[其他] 第4篇:线性回归——找一条最合适的直线 [推广有奖]

  • 0关注
  • 0粉丝

等待验证会员

学前班

40%

还不是VIP/贵宾

-

威望
0
论坛币
0 个
通用积分
0
学术水平
0 点
热心指数
0 点
信用等级
0 点
经验
20 点
帖子
1
精华
0
在线时间
0 小时
注册时间
2018-11-18
最后登录
2018-11-18

楼主
奠老板 发表于 2025-12-2 16:04:34 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币

什么是线性回归?

假设你正在尝试预测房屋的价格。通常情况下,房子的面积越大,价格也越高;房间数量越多,价格往往也随之上升。但仅仅依靠“大概更贵”这样的判断是不够的——你需要一个可以量化、能给出具体数值的预测方法。

线性回归正是为此而生:它通过寻找一条最优直线,利用这条直线对未知数据进行连续数值的预测。

生活中的线性关系示例

学习时间与考试成绩的关系

即使不学习,也能获得50分的基础分数。每增加1小时的学习时间,成绩平均提升10分。例如,学习5小时后的预计得分为:

50 + 10 × 5 = 100 分

成绩 = 50 + 10 × 学习时间

工作年限与薪资水平的关系

刚毕业时起薪为3000元,之后每多工作一年,工资上涨500元。这种稳定的增长趋势可以用一条直线来近似描述。

工资 = 3000 + 500 × 工作年限

核心思想:寻找最佳拟合直线

在现实世界中,数据点通常不会完美地落在同一直线上。线性回归的目标是找到这样一条直线——使得所有实际数据点到该直线的垂直距离的平方和最小。

这条使误差最小化的直线就是我们建立的预测模型。

房价(万)
  ↑
  |    ●
  |  ●
  |●     ●
  |      ●
  |        ●
  +------------------→ 面积(㎡)

数学表达形式

线性回归的基本方程如下所示:

y = wx + b
  • y:需要预测的目标值(如房价)
  • x:输入特征变量(如房屋面积)
  • w:权重或斜率,表示x每增加一个单位时y的变化量(例如面积每增加1㎡,房价上涨w万元)
  • b:偏置项或截距,代表当x为0时的基础输出值(即无面积房屋的理论基础价)

使用Python实现线性回归

方法一:手动实现以理解原理

通过编写基础代码来手动计算参数w和b,有助于深入掌握算法内部机制。

import numpy as np
import matplotlib.pyplot as plt

class SimpleLinearRegression:
    def __init__(self):
        self.w = 0  # 权重
        self.b = 0  # 偏置
    
    def fit(self, X, y):
        """
        训练模型:找到最佳的w和b
        使用最小二乘法
        """
        # 将数据转换为numpy数组
        X = np.array(X)
        y = np.array(y)
        
        # 最小二乘法公式:
        # w = Σ[(xi - x?)(yi - ?)] / Σ[(xi - x?)?]
        # b = ? - w*x?
        
        x_mean = np.mean(X)
        y_mean = np.mean(y)
        
        numerator = np.sum((X - x_mean) * (y - y_mean))
        denominator = np.sum((X - x_mean) ** 2)
        
        self.w = numerator / denominator
        self.b = y_mean - self.w * x_mean
        
        print(f"训练完成!")
        print(f"直线方程: y = {self.w:.2f}x + {self.b:.2f}")
    
    def predict(self, X):
        """预测"""
        return self.w * np.array(X) + self.b
    
    def score(self, X, y):
        """计算R?决定系数(衡量拟合好坏)"""
        X = np.array(X)
        y = np.array(y)
        predictions = self.predict(X)
        
        # 总平方和
        ss_tot = np.sum((y - np.mean(y)) ** 2)
        # 残差平方和
        ss_res = np.sum((y - predictions) ** 2)
        
        r_squared = 1 - (ss_res / ss_tot)
        return r_squared

# 准备房价数据:面积(㎡) -> 价格(万)
areas = [50, 80, 100, 120, 150, 180, 200, 220, 250, 280]
prices = [80, 120, 150, 180, 220, 260, 290, 320, 360, 400]

# 创建并训练模型
model = SimpleLinearRegression()
model.fit(areas, prices)

# 预测
test_areas = [60, 130, 200, 300]
predicted_prices = model.predict(test_areas)

print(f"\n预测结果:")
for area, price in zip(test_areas, predicted_prices):
    print(f"面积{area}㎡ -> 预测价格{price:.1f}万")

# 评估模型
r2 = model.score(areas, prices)
print(f"\n模型表现:R? = {r2:.3f} (越接近1越好)")

运行后得到的结果如下:

训练完成!
直线方程: y = 1.43x + 8.57

预测结果:
面积60㎡ -> 预测价格94.5万
面积130㎡ -> 预测价格194.1万
面积200㎡ -> 预测价格295.0万
面积300㎡ -> 预测价格437.9万

模型表现:R? = 0.992 (越接近1越好)

方法二:使用sklearn库进行实战应用

在实际项目中,推荐使用成熟的机器学习库scikit-learn来快速构建模型,提高开发效率。

from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
import matplotlib.pyplot as plt

# 准备数据(注意:sklearn要求二维数组)
X = np.array(areas).reshape(-1, 1)  # 转换成n×1的矩阵
y = np.array(prices)

# 创建模型
sk_model = LinearRegression()

# 训练模型
sk_model.fit(X, y)

# 查看学到的参数
print(f"sklearn训练结果:")
print(f"权重w: {sk_model.coef_[0]:.2f}")
print(f"偏置b: {sk_model.intercept_:.2f}")
print(f"方程: y = {sk_model.coef_[0]:.2f}x + {sk_model.intercept_:.2f}")

# 预测
test_X = np.array(test_areas).reshape(-1, 1)
sk_predictions = sk_model.predict(test_X)

# 评估
sk_r2 = r2_score(y, sk_model.predict(X))
sk_mse = mean_squared_error(y, sk_model.predict(X))

print(f"\nsklearn模型表现:")
print(f"R? = {sk_r2:.3f}")
print(f"均方误差 = {sk_mse:.2f}")

# 可视化
plt.figure(figsize=(10, 6))
plt.scatter(areas, prices, color='blue', label='实际数据')
plt.plot(areas, sk_model.predict(X), color='red', linewidth=2, label='拟合直线')
plt.xlabel('面积(㎡)')
plt.ylabel('价格(万)')
plt.title('房价与面积的关系')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()

深入解析:损失函数的作用

为了评估模型预测结果的好坏,我们需要一个衡量标准——这就是损失函数。

在线性回归中,最常用的损失函数是均方误差(MSE),其定义如下:

MSE = (1/n) × Σ(yi - ?i)?
  • yi:第i个样本的真实值
  • i:第i个样本的预测值
  • n:样本总数

MSE越小,说明模型的预测结果越接近真实值。

优化方法:梯度下降法

当问题变得复杂,无法直接求解闭式解时,我们可以采用迭代优化方法——梯度下降。

该方法通过不断调整参数w和b,沿着损失函数下降最快的方向逐步逼近最优解。

class GradientDescentLinearRegression:
    def __init__(self, learning_rate=0.01, n_iterations=1000):
        self.learning_rate = learning_rate
        self.n_iterations = n_iterations
        self.w = 0
        self.b = 0
        self.loss_history = []
    
    def compute_loss(self, X, y):
        """计算均方误差"""
        predictions = self.w * X + self.b
        return np.mean((y - predictions) ** 2)
    
    def fit(self, X, y):
        """使用梯度下降训练"""
        X = np.array(X)
        y = np.array(y)
        
        n = len(X)
        
        for i in range(self.n_iterations):
            # 计算预测值
            predictions = self.w * X + self.b
            
            # 计算梯度
            dw = (-2/n) * np.sum(X * (y - predictions))  # w的梯度
            db = (-2/n) * np.sum(y - predictions)        # b的梯度
            
            # 更新参数
            self.w -= self.learning_rate * dw
            self.b -= self.learning_rate * db
            
            # 记录损失
            loss = self.compute_loss(X, y)
            self.loss_history.append(loss)
            
            # 每100次迭代打印进度
            if i % 100 == 0:
                print(f"迭代{i}: 损失 = {loss:.2f}, w = {self.w:.2f}, b = {self.b:.2f}")
    
    def predict(self, X):
        return self.w * np.array(X) + self.b

# 使用梯度下降版本
gd_model = GradientDescentLinearRegression(learning_rate=0.001, n_iterations=1000)
gd_model.fit(areas, prices)

print(f"\n梯度下降结果:")
print(f"方程: y = {gd_model.w:.2f}x + {gd_model.b:.2f}")

# 绘制损失下降过程
plt.figure(figsize=(10, 4))
plt.plot(gd_model.loss_history)
plt.xlabel('迭代次数')
plt.ylabel('损失值')
plt.title('梯度下降优化过程')
plt.grid(True, alpha=0.3)
plt.show()

多变量线性回归

在真实场景中,影响结果的因素往往是多个的。比如在房价预测中,除了面积和房间数,还可能包括楼层、朝向、地段等因素。

此时,模型扩展为多变量形式:

房价 = w?×面积 + w?×房间数 + w?×地段评分 + b

对应的向量表达式为:

# 多变量数据:面积、房间数、地段评分 -> 房价
X_multi = np.array([
    [120, 3, 8],    # 房子1
    [80,  2, 6],    # 房子2  
    [150, 4, 9],    # 房子3
    [90,  2, 7],    # 房子4
    [110, 3, 7],    # 房子5
    [200, 5, 9]     # 房子6
])

y_multi = np.array([300, 180, 450, 220, 280, 520])  # 对应房价

# 使用sklearn的多变量线性回归
multi_model = LinearRegression()
multi_model.fit(X_multi, y_multi)

print("多变量线性回归结果:")
print(f"权重 (面积, 房间数, 地段): {multi_model.coef_}")
print(f"偏置: {multi_model.intercept_:.2f}")
print(f"方程: 房价 = {multi_model.coef_[0]:.2f}×面积 + {multi_model.coef_[1]:.2f}×房间数 + {multi_model.coef_[2]:.2f}×地段 + {multi_model.intercept_:.2f}")

# 预测新房子
new_house = np.array([[100, 2, 7]])  # 100㎡, 2室, 地段7分
predicted_price = multi_model.predict(new_house)[0]
print(f"\n预测新房子价格: {predicted_price:.1f}万")

线性回归的局限性

  1. 仅适用于线性关系
    如果变量之间的关系是非线性的(如曲线关系),线性模型将难以准确拟合。
  2. # 非线性数据示例
    np.random.seed(42)
    X_nonlinear = np.linspace(0, 10, 100)
    y_nonlinear = 2 * X_nonlinear + 3 * X_nonlinear**2 + np.random.normal(0, 10, 100)
    
    # 用线性回归拟合非线性数据
    linear_model = LinearRegression()
    linear_model.fit(X_nonlinear.reshape(-1, 1), y_nonlinear)
    
    # 可视化对比
    plt.figure(figsize=(12, 4))
    
    plt.subplot(1, 2, 1)
    plt.scatter(X_nonlinear, y_nonlinear, alpha=0.6, label='真实数据')
    plt.plot(X_nonlinear, linear_model.predict(X_nonlinear.reshape(-1, 1)), 
             color='red', label='线性拟合')
    plt.legend()
    plt.title('线性回归拟合非线性数据(效果差)')
    
    # 多项式回归效果更好
    from sklearn.preprocessing import PolynomialFeatures
    from sklearn.pipeline import Pipeline
    
    poly_model = Pipeline([
        ('poly', PolynomialFeatures(degree=2)),
        ('linear', LinearRegression())
    ])
    poly_model.fit(X_nonlinear.reshape(-1, 1), y_nonlinear)
    
    plt.subplot(1, 2, 2)
    plt.scatter(X_nonlinear, y_nonlinear, alpha=0.6, label='真实数据')
    plt.plot(X_nonlinear, poly_model.predict(X_nonlinear.reshape(-1, 1)), 
             color='green', label='多项式拟合')
    plt.legend()
    plt.title('多项式回归拟合非线性数据(效果好)')
    
    plt.tight_layout()
    plt.show()
  3. 对异常值敏感
    个别偏离较大的数据点可能会显著影响拟合直线的位置,导致模型偏差增大。
  4. # 加入异常值的影响
    normal_areas = [50, 80, 100, 120, 150, 180, 200]
    normal_prices = [80, 120, 150, 180, 220, 260, 290]
    
    # 加入一个异常值:面积很小但价格极高
    outlier_areas = normal_areas + [60]  # 多加一个点
    outlier_prices = normal_prices + [1000]  # 这个房子60㎡却卖1000万!
    
    # 分别训练模型
    normal_model = LinearRegression().fit(
        np.array(normal_areas).reshape(-1, 1), normal_prices)
    outlier_model = LinearRegression().fit(
        np.array(outlier_areas).reshape(-1, 1), outlier_prices)
    
    # 可视化对比
    test_x = np.linspace(40, 220, 100).reshape(-1, 1)
    
    plt.figure(figsize=(10, 6))
    plt.scatter(normal_areas, normal_prices, color='blue', s=50, label='正常数据')
    plt.scatter([60], [1000], color='red', s=100, marker='x', label='异常值')
    plt.plot(test_x, normal_model.predict(test_x), 'b-', label='正常数据拟合')
    plt.plot(test_x, outlier_model.predict(test_x), 'r--', label='含异常值拟合')
    plt.xlabel('面积(㎡)')
    plt.ylabel('价格(万)')
    plt.legend()
    plt.title('异常值对线性回归的影响')
    plt.grid(True, alpha=0.3)
    plt.show()
    
    print("正常数据模型的斜率:", normal_model.coef_[0])
    print("含异常值模型的斜率:", outlier_model.coef_[0])

为何线性回归是机器学习的重要基石?

  • 简单高效
    模型结构清晰,易于理解和实现,计算开销小,在小规模数据上表现良好。
  • 理论基础扎实
    具备明确的统计性质,支持参数显著性检验,为后续复杂模型提供理论支撑。
  • 可解释性强
    每个特征的权重都有明确含义,便于分析各因素对结果的影响程度。
# 解释模型结果
print("=== 模型解释 ===")
print(f"面积每增加1㎡,房价平均增加{multi_model.coef_[0]:.1f}万")
print(f"房间数每增加1间,房价平均增加{multi_model.coef_[1]:.1f}万") 
print(f"地段评分每增加1分,房价平均增加{multi_model.coef_[2]:.1f}万")
print(f"即使什么都没有(面积=0),基础房价是{multi_model.intercept_:.1f}万")

本篇总结

  • 线性回归的本质:通过构建形如 y = wx + b 的直线来进行数值预测。
  • 最小二乘法:目标是最小化所有数据点到直线的垂直距离的平方和。
  • 梯度下降:用于在无法直接求解时,迭代优化模型参数。
  • 多变量扩展:允许同时考虑多个输入特征对输出的影响。
  • 局限性:只能处理线性关系,且容易受到异常值干扰。
  • 重要地位:作为入门级模型,它是理解更高级机器学习算法的基础。

练习建议

  • 手工计算练习:给定三组数据点 (1,2), (2,3), (3,5),尝试用手动方式推导出线性回归的参数w和b。
  • 实际数据分析:选取你感兴趣的一组数据(例如学习时长与考试得分),应用线性回归分析其相关性。
  • 模型改进实验:尝试在房价预测模型中加入“装修程度”这一新特征,观察是否提升了预测精度。
  • 异常值处理思考:探讨如何识别并合理处理数据集中的异常点,以增强模型的鲁棒性。

下期内容预告

第5篇:逻辑回归——不只是预测数值,还能做分类决策

线性回归擅长预测连续值,但在许多现实问题中,我们需要的是分类判断:

  • 这封邮件属于垃圾邮件还是正常邮件?
  • 这张图片显示的是猫还是狗?
  • 这位用户是否会购买某个产品?

逻辑回归正是解决这类分类任务的强大工具。我们将带你了解如何让机器学会“做选择题”,开启分类模型的学习之旅。

二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:线性回归 scikit-learn Predictions regression Prediction

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
加好友,备注cda
拉您进交流群
GMT+8, 2026-2-5 06:40