文章目录
一、线性回归基础概念
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) |
---|---|
50 | 100 |
60 | 120 |
70 | 140 |
80 | 160 |
我们的目标是找到最佳的 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=n1∑i=1n(yi−y^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
sklearn
即 scikit-learn
,是 Python 中常用的机器学习库。以下为你介绍几种常见的下载安装方式:
使用 pip 安装
-
打开命令行工具:
-
在 Windows 系统中,可以通过按下
Win + R
组合键,输入cmd
并回车,打开命令提示符。 -
在 macOS 和 Linux 系统中,可以打开终端应用程序。
-
-
执行安装命令:
在命令行中输入以下命令并回车:
pip install -U scikit-learn
这里的 -U
选项表示如果已经安装了 scikit-learn
,则将其升级到最新版本。
- 验证安装:
安装完成后,你可以在 Python 环境中验证是否安装成功。在命令行中输入python
进入 Python 交互式环境,然后输入以下代码:
import sklearn
print(sklearn.__version__)
如果没有报错并能输出版本号,则说明安装成功。
使用 conda 安装
如果你使用的是 Anaconda 或 Miniconda 环境,那么可以使用 conda
来安装 scikit-learn
。
- 打开 Anaconda Prompt 或终端:
- 在 Windows 系统中,找到并打开
Anaconda Prompt
。 - 在 macOS 和 Linux 系统中,打开终端。
- 在 Windows 系统中,找到并打开
- 执行安装命令:
在命令行中输入以下命令并回车:
conda install scikit-learn
- 验证安装:
同样进入 Python 交互式环境,执行上述验证代码,确认是否安装成功。
2.2 LinearRegression
API 介绍:LinearRegression
是 sklearn
中用于实现普通最小二乘(最小二乘介绍)线性回归的类,它使用正规方程法来求解线性回归的参数。
参数解释:
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 介绍:SGDRegressor
是 sklearn
中用于实现随机梯度下降(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 介绍:Lasso
是 sklearn
中用于实现 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 介绍:Ridge
是 sklearn
中用于实现 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 核心功能
-
数据生成模块
- 基于真实线性关系 y = 2.5 x + 10 y = 2.5x + 10 y=2.5x+10 生成基础数据
- 添加高斯噪声(均值0,标准差25)模拟真实观测误差
- 使用固定随机种子确保结果可复现
-
模型训练模块
- 使用scikit-learn的LinearRegression类实现最小二乘法拟合
- 自动计算最优斜率和截距参数
- 支持多维特征输入格式处理(reshape操作)
-
可视化模块
- 绘制带噪声的原始数据点
- 绘制真实线性关系(蓝色实线)
- 绘制模型拟合的线性关系(绿色虚线)
- 直观对比真实参数与拟合参数差异
3.3 关键技术细节
-
数据处理
- 使用
np.linspace
生成均匀分布的特征数据 - 通过
np.random.normal
添加符合高斯分布的随机噪声 - 使用
reshape(-1, 1)
将一维数组转换为二维特征矩阵(sklearn要求)
- 使用
-
模型参数
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() # 显示图表