线性回归(Linear regression)算法详解

一、线性回归基础概念

1.1 什么是线性回归

线性回归是一种通过回归方程来建模自变量(特征值)与因变量(目标值)之间线性关系的分析方法。简单来说,它试图找到一条直线(或超平面),能够最佳地拟合数据点,从而实现对新数据的预测。

一元线性回归(单变量)的数学表达式为:

y = k x + b y = kx + b y=kx+b

其中, x x x 是特征(如房屋面积), y y y 是目标值(如房屋价格), k k k 是斜率, b b b 是截距。

k = 1 k=1 k=1, b = 0 b=0 b=0时的 y = k x + b y = kx + b y=kx+b
在这里插入图片描述

多元线性回归(多变量)的表达式为:

y = w 1 x 1 + w 2 x 2 + . . . + w n x n + b y = w_1x_1 + w_2x_2 + ... + w_nx_n + b y=w1x1+w2x2+...+wnxn+b

其中, x 1 , x 2 , . . . , x n x_1, x_2, ..., x_n x1,x2,...,xn 是多个特征(如房屋面积、房间数、地理位置等), w 1 , w 2 , . . . , w n w_1, w_2, ..., w_n w1,w2,...,wn 是对应的权重, b b b 是截距。

两个特征(两个 x x x w 1 = 1 w_1=1 w1=1 w 2 = 1 w_2=1 w2=1 b = 0 b=0 b=0 时的 y = w 1 x 1 + w 2 x 2 + b y = w_1x_1 + w_2x_2+ b y=w1x1+w2x2+b 的图像:
在这里插入图片描述
绘图代码:

import numpy as np
# 导入 NumPy 库,它是 Python 中用于科学计算的基础库,提供了高效的多维数组对象和处理这些数组的工具。
import matplotlib.pyplot as plt
# 导入 Matplotlib 库中的 pyplot 模块,它是一个用于创建各种可视化图形的接口,可用于绘制折线图、散点图等。
from mpl_toolkits.mplot3d import Axes3D  # 用于3D绘图
# 从 mpl_toolkits.mplot3d 模块中导入 Axes3D 类,该类用于创建三维图形。

# 设置中文字体和负号显示
plt.rcParams["font.family"] = ["SimHei"]
# 设置 Matplotlib 的字体为黑体,以便在图形中正确显示中文。
plt.rcParams["axes.unicode_minus"] = False
# 设置允许在坐标轴上正确显示负号。

# 设置权重和偏置
w1, w2 = 1, 1  # 权重
# 定义多元线性模型中的两个权重 w1 和 w2,这里都设置为 1。
b = 0               # 截距
# 定义多元线性模型中的截距 b,这里设置为 0。

# 创建 x1 和 x2 的网格数据
x1 = np.linspace(-10, 10, 100)
# 使用 NumPy 的 linspace 函数生成从 -10 到 10 之间均匀分布的 100 个点,作为特征 x1 的取值。
x2 = np.linspace(-10, 10, 100)
# 同样使用 linspace 函数生成从 -10 到 10 之间均匀分布的 100 个点,作为特征 x2 的取值。
x1_mesh, x2_mesh = np.meshgrid(x1, x2)
# 使用 NumPy 的 meshgrid 函数将 x1 和 x2 转换为二维网格矩阵,方便后续计算。

# 计算 y 值
y = w1 * x1_mesh + w2 * x2_mesh + b
# 根据多元线性模型的公式 y = w1 * x1 + w2 * x2 + b,计算对应的目标值 y。

# 创建 3D 图像
fig = plt.figure(figsize=(10, 7))
# 使用 plt.figure 函数创建一个新的图形对象,设置图形的大小为宽 10 英寸,高 7 英寸。
ax = fig.add_subplot(111, projection='3d')
# 在图形中添加一个子图,111 表示将图形划分为 1 行 1 列,当前子图为第 1 个,projection='3d' 表示创建一个三维子图。

# 绘制曲面
surf = ax.plot_surface(x1_mesh, x2_mesh, y, cmap='viridis', alpha=0.8)
# 使用 plot_surface 方法在三维子图中绘制曲面,x1_mesh 和 x2_mesh 是网格数据,y 是对应的目标值,cmap='viridis' 设置颜色映射为 'viridis',alpha=0.8 设置曲面的透明度为 0.8。

# 添加坐标轴标签
ax.set_xlabel('$x_1$', fontsize=12)
# 设置 x 轴的标签为 '$x_1$',字体大小为 12。
ax.set_ylabel('$x_2$', fontsize=12)
# 设置 y 轴的标签为 '$x_2$',字体大小为 12。
ax.set_zlabel('$y$', fontsize=12)
# 设置 z 轴的标签为 '$y$',字体大小为 12。

# 添加标题
ax.set_title('多元线性模型示意图:$y = w_1x_1 + w_2x_2 + b$', fontsize=14)
# 设置子图的标题为 '多元线性模型示意图:$y = w_1x_1 + w_2x_2 + b$',字体大小为 14。

# 添加颜色条(表示 y 值高低)
fig.colorbar(surf, shrink=0.6, aspect=10)
# 在图形中添加颜色条,用于表示 y 值的高低,shrink=0.6 表示将颜色条缩小为原来的 0.6 倍,aspect=10 表示颜色条的宽高比为 10。

# 显示图像
plt.show()
# 显示最终绘制的图形。

1.2 线性回归小例子

假设我们有一个简单的数据集,包含房屋面积和房屋价格的信息。我们想要通过房屋面积来预测房屋价格,这就是一个典型的一元线性回归问题。

我们假设房屋价格 y y y 和房屋面积 x x x 之间存在线性关系,即 y = k x + b y = kx + b y=kx+b,其中 k k k 是斜率, b b b 是截距。

现在我们有以下数据集:

房屋面积 ( x x x)房屋价格 ( y y y)
50100
60120
70140
80160

我们的目标是找到最佳的 k k k b b b 值,使得预测值 y ^ = k x + b \hat{y} = kx + b y^=kx+b 与真实值 y y y 之间的误差最小。常用的误差衡量方法是均方误差(MSE,MSE介绍),即 M S E = 1 n ∑ i = 1 n ( y i − y ^ i ) 2 MSE = \frac{1}{n} \sum_{i=1}^{n} (y_i - \hat{y}_i)^2 MSE=n1i=1n(yiy^i)2,其中 n n n 是样本数量。

通过最小化 MSE,我们可以得到最佳的 k k k b b b 值。在这个简单的例子中,我们可以通过手动计算或者使用线性回归算法来找到 k = 2 k = 2 k=2 b = 0 b = 0 b=0,即 y = 2 x y = 2x y=2x ,此时回归曲线将会完全拟合样本,误差为 0。

假设此时输入一个样本,该样本 x = 75 x=75 x=75 ,真实值: y = 145 y=145 y=145 ,那么模型的预测值: y ^ = 150 \hat{y}=150 y^=150,根据 M S E MSE MSE 计算公式即可计算出误差为 25。这样做能测试模型对未知数据的预测能力,揭示模型的泛化局限性,并为模型优化提供依据。这正是机器学习中训练 - 测试 - 验证流程的基础逻辑。

在这里插入图片描述
绘图代码:

import numpy as np
import matplotlib.pyplot as plt

# 设置中文字体和负号显示
plt.rcParams["font.family"] = ["SimHei"]  # 指定中文字体为黑体
plt.rcParams["axes.unicode_minus"] = False  # 确保负号正确显示

# 数据集:房屋面积 x 和对应的价格 y
x = np.array([50, 60, 70, 80])  # 房屋面积(平方米)
y = np.array([100, 120, 140, 160])  # 房屋价格(万元)

# 线性回归模型参数(假设已知)
k = 2  # 斜率,表示每增加1平方米面积,价格增加2万元
b = 0  # 截距,表示面积为0时的基础价格

# 计算预测值
y_pred = k * x + b  # 根据模型 y = 2x + 0 计算预测的价格
# 计算均方误差(MSE)
mse = np.mean((y - y_pred) ** 2)  # 误差平方的均值,衡量模型拟合程度

# 新增一个测试点 (75, 145)
x_new = 75  # 新房屋面积
y_true_new = 145  # 新房屋真实价格
y_pred_new = k * x_new + b  # 根据模型预测的新房屋价格

# 创建绘图窗口
fig, ax = plt.subplots(figsize=(8, 6))  # 创建8×6英寸的图表
# 绘制原始数据点(散点图)
ax.scatter(x, y, color='red', label='真实数据点')  # 用红色圆点表示原始数据
# 绘制新增数据点
ax.scatter(x_new, y_true_new, color='green', label='新增数据点', zorder=5)  # 用绿色圆点表示新增数据

# 绘制拟合直线 y = 2x
x_line = np.linspace(40, 90, 100)  # 在40-90范围内生成100个均匀分布的点
y_line = k * x_line + b  # 计算拟合直线上的对应点
ax.plot(x_line, y_line, color='blue', label=rf'拟合直线: $y = {k}x + {b}$')  # 用蓝色线绘制拟合直线

# 添加误差线(真实值与预测值之间的垂直线)
for i in range(len(x)):
    ax.plot([x[i], x[i]], [y[i], y_pred[i]], 'k--', lw=1)  # 用黑色虚线连接每个点的真实值和预测值

# 添加新增点的误差线
ax.plot([x_new, x_new], [y_true_new, y_pred_new], 'g--', lw=1.5, label='误差线')  # 绿色虚线表示新增点的误差

# 设置图表标题和坐标轴标签
ax.set_title(r'一元线性回归示例:房屋面积 vs 房屋价格', fontsize=14)  # 设置标题
ax.set_xlabel('房屋面积 $x$', fontsize=12)  # 设置x轴标签
ax.set_ylabel('房屋价格 $y$', fontsize=12)  # 设置y轴标签

# 显示 MSE 值
ax.text(45, 170, f'MSE = {mse:.2f}', fontsize=12, bbox=dict(facecolor='white', alpha=0.6))  # 在图表上标注MSE

# 显示新增点的预测值和真实值
ax.text(x_new + 1, y_true_new, f'(x={x_new}, y={y_true_new})', fontsize=10, color='green')  # 标注新增点的真实坐标
ax.text(x_new + 1, y_pred_new, f'$\hat{{y}} = {y_pred_new}$', fontsize=10, color='blue')  # 标注新增点的预测值

# 图例和网格
ax.legend(fontsize=12)  # 显示图例
ax.grid(True, linestyle='--', alpha=0.7)  # 添加网格线,增强可读性

# 设置坐标轴范围
ax.set_xlim(40, 95)  # 设置x轴范围
ax.set_ylim(80, 180)  # 设置y轴范围

# 优化布局并显示图像
plt.tight_layout()  # 自动调整布局,防止内容重叠
plt.show()  # 显示图表

二、sklearn 中线性回归的 API 和参数

2.1 安装sklearn

sklearnscikit-learn,是 Python 中常用的机器学习库。以下为你介绍几种常见的下载安装方式:

使用 pip 安装

  1. 打开命令行工具

    • 在 Windows 系统中,可以通过按下 Win + R 组合键,输入 cmd 并回车,打开命令提示符。

    • 在 macOS 和 Linux 系统中,可以打开终端应用程序。

  2. 执行安装命令

在命令行中输入以下命令并回车:

pip install -U scikit-learn

这里的 -U 选项表示如果已经安装了 scikit-learn,则将其升级到最新版本。

  1. 验证安装
    安装完成后,你可以在 Python 环境中验证是否安装成功。在命令行中输入 python 进入 Python 交互式环境,然后输入以下代码:
import sklearn
print(sklearn.__version__)

如果没有报错并能输出版本号,则说明安装成功。

使用 conda 安装

如果你使用的是 Anaconda 或 Miniconda 环境,那么可以使用 conda 来安装 scikit-learn

  1. 打开 Anaconda Prompt 或终端
    • 在 Windows 系统中,找到并打开 Anaconda Prompt
    • 在 macOS 和 Linux 系统中,打开终端。
  2. 执行安装命令
    在命令行中输入以下命令并回车:
conda install scikit-learn
  1. 验证安装
    同样进入 Python 交互式环境,执行上述验证代码,确认是否安装成功。

2.2 LinearRegression

API 介绍LinearRegressionsklearn 中用于实现普通最小二乘(最小二乘介绍)线性回归的类,它使用正规方程法来求解线性回归的参数。

参数解释

  • fit_intercept:布尔值,默认为 True,表示是否计算截距。如果设置为 False,则不会计算截距。
  • normalize:布尔值,默认为 False,表示是否对输入数据进行归一化处理。
  • copy_X:布尔值,默认为 True,表示是否复制输入数据。
  • n_jobs:整数,默认为 None,表示用于计算的 CPU 核心数。

示例代码

from sklearn.linear_model import LinearRegression
import numpy as np

# 生成示例数据
X = np.array([[50], [60], [70], [80]])
y = np.array([100, 120, 140, 160])

# 创建线性回归模型
lin_reg = LinearRegression()

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

# 输出模型参数
print(f"斜率: {lin_reg.coef_[0]:.2f}, 截距: {lin_reg.intercept_:.2f}")

2.3 SGDRegresso

API 介绍SGDRegressorsklearn 中用于实现随机梯度下降(SGD,SGD介绍)回归的类,它通过迭代更新模型参数来最小化损失函数。

参数解释

  • loss:字符串,默认为 'squared_loss',表示损失函数的类型,常见的有 'squared_loss'(均方误差)、'huber'(Huber 损失)等。
  • penalty:字符串,默认为 'l2',表示正则化的类型,常见的有 'l2'(L2 正则化)、'l1'(L1 正则化)等。
  • alpha:浮点数,默认为 0.0001,表示正则化的强度。
  • learning_rate:字符串,默认为 'invscaling',表示学习率的更新策略,常见的有 'constant'(固定学习率)、'invscaling'(递减学习率)等。
  • eta0:浮点数,默认为 0.01,表示初始学习率。

示例代码

from sklearn.linear_model import SGDRegressor
import numpy as np

# 生成示例数据
X = np.array([[50], [60], [70], [80]])
y = np.array([100, 120, 140, 160])

# 创建随机梯度下降回归模型
sgd_reg = SGDRegressor(loss='squared_loss', learning_rate='constant', eta0=0.001)

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

# 输出模型参数
print(f"斜率: {sgd_reg.coef_[0]:.2f}, 截距: {sgd_reg.intercept_[0]:.2f}")

2.4 Lasso

API 介绍Lassosklearn 中用于实现 L1 正则化线性回归的类,它可以用于特征选择。

参数解释

  • alpha:浮点数,默认为 1.0,表示正则化的强度。
  • fit_intercept:布尔值,默认为 True,表示是否计算截距。
  • normalize:布尔值,默认为 False,表示是否对输入数据进行归一化处理。

示例代码

from sklearn.linear_model import Lasso
import numpy as np

# 生成示例数据
X = np.array([[50], [60], [70], [80]])
y = np.array([100, 120, 140, 160])

# 创建 Lasso 回归模型
lasso_reg = Lasso(alpha=0.1)

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

# 输出模型参数
print(f"斜率: {lasso_reg.coef_[0]:.2f}, 截距: {lasso_reg.intercept_:.2f}")

2.5 Ridge

API 介绍Ridgesklearn 中用于实现 L2 正则化线性回归的类,它可以用于防止过拟合。

参数解释

  • alpha:浮点数,默认为 1.0,表示正则化的强度。
  • fit_intercept:布尔值,默认为 True,表示是否计算截距。
  • normalize:布尔值,默认为 False,表示是否对输入数据进行归一化处理。

示例代码

from sklearn.linear_model import Ridge
import numpy as np

# 生成示例数据
X = np.array([[50], [60], [70], [80]])
y = np.array([100, 120, 140, 160])

# 创建 Ridge 回归模型
ridge_reg = Ridge(alpha=0.1)

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

# 输出模型参数
print(f"斜率: {ridge_reg.coef_[0]:.2f}, 截距: {ridge_reg.intercept_:.2f}")

2.6 各个API的对比

API名称适用场景优点缺点示例场景
LinearRegression数据规模较小且特征数量不多,数据噪声小,无明显多重共线性基于正规方程法,能直接得到精确最优解,计算效率高数据规模大时计算复杂度高,可能导致内存不足或计算时间过长;存在多重共线性时易过拟合预测学生考试成绩,特征为学习时长、预习次数等,样本少且特征间无明显相关性
SGDRegressor数据规模非常大,需要在线学习采用随机梯度下降算法,内存占用少,计算速度快,适合在线学习收敛速度可能较慢,结果可能受初始值和学习率影响较大电商平台预测用户购买金额,每天产生大量用户行为数据
Lasso需要进行特征选择,数据集中部分特征对目标变量影响较小能通过L1正则化使部分不重要特征系数变为零,实现自动特征筛选当特征之间存在较强相关性时,可能无法很好地保留所有重要特征基因数据分析,有成千上万个基因特征,只有少数与疾病相关
Ridge数据存在多重共线性,普通线性回归易过拟合L2正则化可将特征系数收缩到接近零但不为零的值,缓解多重共线性,提高泛化能力不能进行特征选择,所有特征都会保留一定的权重房地产价格预测,房屋面积、房间数量、使用年限等特征间有较强相关性

三、使用 sklearn 实现线性回归

3.1 程序概述

本程序演示了使用Python实现线性回归的完整流程,包括数据生成、模型训练和可视化展示。程序通过生成带噪声的模拟数据,使用scikit-learn库进行线性回归拟合,并通过matplotlib库可视化拟合结果,直观展示了线性回归模型的工作原理。

3.2 核心功能

  1. 数据生成模块

    • 基于真实线性关系 y = 2.5 x + 10 y = 2.5x + 10 y=2.5x+10 生成基础数据
    • 添加高斯噪声(均值0,标准差25)模拟真实观测误差
    • 使用固定随机种子确保结果可复现
  2. 模型训练模块

    • 使用scikit-learn的LinearRegression类实现最小二乘法拟合
    • 自动计算最优斜率和截距参数
    • 支持多维特征输入格式处理(reshape操作)
  3. 可视化模块

    • 绘制带噪声的原始数据点
    • 绘制真实线性关系(蓝色实线)
    • 绘制模型拟合的线性关系(绿色虚线)
    • 直观对比真实参数与拟合参数差异

3.3 关键技术细节

  1. 数据处理

    • 使用 np.linspace 生成均匀分布的特征数据
    • 通过 np.random.normal 添加符合高斯分布的随机噪声
    • 使用 reshape(-1, 1) 将一维数组转换为二维特征矩阵(sklearn要求)
  2. 模型参数

    • model.coef_:获取模型学习到的斜率参数
    • model.intercept_:获取模型学习到的截距参数
    • 拟合结果自动存储在模型实例中

3.4 程序运行结果

运行程序后,将生成一个包含以下元素的图表:

  • 红色散点:带噪声的观测数据点
  • 蓝色实线:真实的线性关系(无噪声)
  • 绿色虚线:模型拟合的线性关系
  • 图例中标注了真实参数与拟合参数

在这里插入图片描述

通过对比蓝色实线与绿色虚线,可以直观理解噪声对模型拟合的影响。在本示例中,即使数据包含噪声,线性回归模型仍能较好地逼近真实参数。

利用线性回归演示过拟合和正则化网页连接

3.5 代码结构

import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression

# 设置中文字体和负号显示
plt.rcParams["font.family"] = ["SimHei"]  # 指定中文字体为黑体
plt.rcParams["axes.unicode_minus"] = False  # 确保负号正确显示

# 1. 使用 NumPy 生成带噪声的数据
np.random.seed(44)  # 固定随机种子,确保结果可复现

# 真实参数(我们希望模型学习的理想参数)
k_true = 2.5  # 真实斜率
b_true = 10   # 真实截距

# 生成 x 数据(特征):在 0-50 范围内均匀生成 25 个点
x = np.linspace(0, 50, 25)

# 生成 y 数据(目标):基于真实线性关系 y = 2.5x + 10,并添加高斯噪声
# np.random.normal(0, 25, size=x.shape) 生成均值为 0、标准差为 25 的随机噪声
y = k_true * x + b_true + np.random.normal(0, 25, size=x.shape)

# 2. 使用 sklearn 进行线性回归拟合
model = LinearRegression()  # 创建线性回归模型实例
model.fit(x.reshape(-1, 1), y)  # 训练模型
# x.reshape(-1, 1) 将一维数组转换为二维数组(sklearn 要求输入为二维特征矩阵)

# 获取拟合参数
k_fit = model.coef_[0]  # 提取拟合的斜率
b_fit = model.intercept_  # 提取拟合的截距

# 生成拟合直线上的预测值
y_fit = model.predict(x.reshape(-1, 1))  # 使用模型预测训练数据

# 3. 可视化展示
fig, ax = plt.subplots(figsize=(10, 6))  # 创建 10×6 英寸的图表

# 绘制原始数据点(带噪声的样本)
ax.scatter(x, y, color='red', label='样本点', alpha=0.7)  # 使用半透明红色圆点表示数据点

# 绘制真实直线(无噪声的理想情况)
ax.plot(x, k_true * x + b_true, color='blue', label=r'真实关系 $y = %.1fx + %.1f$' % (k_true, b_true))

# 绘制拟合直线(模型学习到的关系)
ax.plot(x, y_fit, color='green', linestyle='--', linewidth=2,
        label=r'拟合直线 $\hat{y} = %.2fx + %.2f$' % (k_fit, b_fit))

# 添加标题和坐标轴标签
ax.set_title('线性回归拟合示例', fontsize=14)
ax.set_xlabel('x 特征值')
ax.set_ylabel('y 目标值')

# 添加图例与网格
ax.legend(fontsize=12)  # 显示图例,调整字体大小
ax.grid(True, linestyle='--', alpha=0.6)  # 添加半透明虚线网格

# 优化布局并显示图像
plt.tight_layout()  # 自动调整布局,防止内容重叠
plt.show()  # 显示图表
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值