温馨提示:
本文内容较为详尽,建议您分段阅读,以便逐步掌握。多动手实践,通过代码示例亲自操作,能够有效加深对线性回归的理解。祝您学习愉快!😊
一、引言:人工智能与机器学习的魅力
什么是人工智能(AI
)?
人工智能(AI
)是计算机科学的一个分支,致力于开发能够执行通常需要人类智能的任务的系统。AI
系统具备感知、推理、学习和决策的能力,广泛应用于语音识别、图像处理、自动驾驶和推荐系统等领域。例如,当你与智能助手(如Siri
、Alexa
)对话时,你就是在与AI互动。
什么是机器学习(ML
)?
机器学习是人工智能的一个子领域,旨在通过数据和经验让计算机自动改进其任务执行能力。与传统编程不同,程序员不需要手动编写规则,而是让计算机从数据中学习和发现解决问题的方法。这在数据量庞大或问题复杂时尤为有效。
机器学习的核心思想
机器学习的核心在于通过数据训练模型,识别数据中的模式,从而进行预测或分类。根据学习方式的不同,机器学习通常分为三大类:
- 监督学习:使用已标注的数据训练模型,学习输入与输出之间的关系。
- 无监督学习:处理未标注的数据,发现数据的内部结构或模式。
- 强化学习:通过与环境的互动和反馈,优化决策策略。
二、深入了解线性回归:简单但强大的算法
什么是线性回归?
线性回归(Linear Regression
)是一种基础的机器学习算法,用于描述一个目标变量(y
)与一个或多个自变量(X
)之间的线性关系,并基于此关系进行预测。理解线性回归对于掌握更复杂的模型至关重要。
线性回归是一种线性模型,即假设输入变量(x
)与单一输出变量(y
)之间存在线性关系。更具体地说,y
可以通过输入变量(x
)的线性组合来计算。
- 简单线性回归 :当只有一个输入变量(
x
)时,称为简单线性回归。 - 多元线性回归:当有多个输入变量时,称为多元线性回归。
线性回归的数学原理并不复杂,但它是许多机器学习和数据科学模型的基础。我们将从最简单的一元线性回归开始讲解。
一元线性回归试图找到一条最适合数据的直线,公式如下:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> y = β 0 + β 1 ⋅ X y=β0+β1⋅X </math>y=β0+β1⋅X
y
:目标变量,需预测的值。X
:输入特征,自变量。β0
:截距,直线与y
轴的交点。β1
:斜率,表示X
对y
的影响程度。
代码示例:一元线性回归
python
import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
# 生成示例数据
np.random.seed(42)
X = 2 * np.random.rand(100, 1)
y = 4 + 3 * X + np.random.randn(100, 1)
# 创建线性回归模型
model = LinearRegression()
model.fit(X, y)
y_pred = model.predict(X)
# 绘制数据点和回归直线
plt.figure(figsize=(8, 6))
plt.scatter(X, y, color='blue', label='数据点')
plt.plot(X, y_pred, color='red', label='回归直线')
plt.title('一元线性回归示例')
plt.xlabel('X')
plt.ylabel('y')
plt.legend()
plt.show()
# 模型评估
mse = mean_squared_error(y, y_pred)
r2 = r2_score(y, y_pred)
print(f"均方误差 (MSE): {mse:.2f}") # 均方误差 (MSE): 0.81
print(f"R²: {r2:.2f}") # R²: 0.77
运行结果:
多元线性回归则扩展为:
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> y = β 0 + β 1 X 1 + β 2 X 2 + ⋯ + β p X p y = \beta_0 + \beta_1 X_1 + \beta_2 X_2 + \dots + \beta_p X_p </math>y=β0+β1X1+β2X2+⋯+βpXp
X1,X2,...,Xp
:多个输入特征。β1,β2,...,βp
:各特征的权重。
python
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
# 生成示例数据
np.random.seed(42)
X_multi = 2 * np.random.rand(100, 2)
y_multi = 4 + 3 * X_multi[:, 0] + 5 * X_multi[:, 1] + np.random.randn(100)
# 创建并训练模型
model = LinearRegression()
model.fit(X_multi, y_multi)
y_pred_multi = model.predict(X_multi)
# 模型评估
mse_multi = mean_squared_error(y_multi, y_pred_multi)
r2_multi = r2_score(y_multi, y_pred_multi)
print(f"多元回归均方误差 (MSE): {mse_multi:.2f}")
print(f"多元回归 R²: {r2_multi:.2f}")
# 输出参数
print(f"截距 (β0): {model.intercept_:.2f}")
print(f"权重 (β1, β2): {model.coef_}")
输出:
python
多元回归均方误差 (MSE): 0.98
多元回归 R²: 0.92
截距 (β0): 3.77
权重 (β1, β2): [3.16933339 5.17747302]
为了从数据中准备或训练线性回归方程,常用的方法是最小二乘法(Ordinary Least Squares
, OLS
) 。因此,使用这种方法训练的模型通常称为最小二乘线性回归 或简称最小二乘回归。
线性回归的基本步骤
-
定义模型:选择适当的输入特征和目标变量,确定模型形式(简单或多元线性回归)。
-
选择损失函数 :通常使用均方误差(
MSE
) 来衡量预测值与实际值之间的差距:<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> M S E = 1 n ∑ i = 1 n ( y i − ( β 0 + β 1 X i ) ) 2 MSE = \frac{1}{n} \sum_{i=1}^{n} (y_i - (\beta_0 + \beta_1 X_i))^2 </math>MSE=n1i=1∑n(yi−(β0+β1Xi))2
其中:
n
:样本数量。yi
:第i个数据点的实际值。- **
β0+β1Xi
:模型预测值。
代码示例:计算
MSE
pythonimport numpy as np def calculate_mse(y_true, y_pred): mse = np.mean((y_true - y_pred) ** 2) return mse # 示例 y_true = np.array([3, -0.5, 2, 7]) y_pred = np.array([2.5, 0.0, 2, 8]) print("均方误差 (MSE):", calculate_mse(y_true, y_pred))
输出:
python均方误差 (MSE): 0.375
-
优化模型参数 :使用梯度下降法 等优化算法,通过最小化损失函数来找到最优的参数
β0
和β1
:梯度下降法是一种优化算法,类似于在山坡上寻找最低点。通过计算损失函数对模型参数的梯度(即坡度),并沿着坡度下降的方向(梯度的反方向)调整参数,从而逐步减小预测误差。
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> β 0 : = β 0 − η ∂ M S E ∂ β 0 \beta_0 := \beta_0 - \eta \frac{\partial MSE}{\partial \beta_0} </math>β0:=β0−η∂β0∂MSE
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> β 1 : = β 1 − η ∂ M S E ∂ β 1 \beta_1 := \beta_1 - \eta \frac{\partial MSE}{\partial \beta_1} </math>β1:=β1−η∂β1∂MSE其中,
-
η
是学习率,控制每次更新的步长。 -
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> ∂ M S E ∂ β 0 和 ∂ M S E ∂ β 1 是 M S E 对参数 β 0 和 β 1 的偏导数。 \frac{\partial MSE}{\partial \beta_0} 和\frac{\partial MSE}{\partial \beta_1} 是 MSE 对参数 β0 和 β1 的偏导数。 </math>∂β0∂MSE和∂β1∂MSE是MSE对参数β0和β1的偏导数。
代码示例:梯度下降法实现一元线性回归
pythonimport numpy as np import matplotlib.pyplot as plt # 生成示例数据 np.random.seed(42) X = 2 * np.random.rand(100, 1) y = 4 + 3 * X + np.random.randn(100, 1) # 初始化参数 beta_0 = 0 beta_1 = 0 eta = 0.1 epochs = 1000 n = len(X) # 梯度下降 for epoch in range(epochs): y_pred = beta_0 + beta_1 * X error = y_pred - y beta_0 -= eta * (2/n) * np.sum(error) beta_1 -= eta * (2/n) * np.sum(error * X) print(f"截距 (β0): {beta_0:.2f}") # 截距 (β0): 4.22 print(f"斜率 (β1): {beta_1:.2f}") # 斜率 (β1): 2.77 # 绘制结果 plt.figure(figsize=(8, 6)) plt.scatter(X, y, color='blue', label='数据点') plt.plot(X, beta_0 + beta_1 * X, color='red', label='回归直线') plt.title('梯度下降法拟合的一元线性回归') plt.xlabel('X') plt.ylabel('y') plt.legend() plt.show()
运行结果:
-
-
评估模型 :使用指标如均方误差(
MSE
) 和决定系数(R^2
) 来评估模型的性能。
三、数据集简介
数据集来源
我们将使用 加利福尼亚房价数据集。这个数据集包含了加利福尼亚州各个区域的房价信息,以及一系列与房价相关的特征(如收入中位数、房屋年龄等)。这些数据来源于 1990 年的美国人口普查,通常用于回归问题的练习。
特征介绍
以下是数据集中的一些主要特征:
MedInc
: 区域的收入中位数(单位:万美元)HouseAge
: 区域房屋的中位年龄(单位:年)AveRooms
: 每户家庭的平均房间数AveBedrms
: 每户家庭的平均卧室数Population
: 区域人口数量AveOccup
: 每户家庭的平均人数Latitude
: 区域的纬度Longitude
: 区域的经度HouseValue
: 区域房屋的中位价(目标变量,单位:$100,000)
目标是预测 HouseValue
,即加利福尼亚各区域的房屋中位价格。
四、加载和探索数据
数据加载
首先,我们使用 scikit-learn
提供的 fetch_california_housing
函数加载数据,并转化为 Pandas
DataFrame
格式,以便进行数据分析。
python
from sklearn.datasets import fetch_california_housing
import pandas as pd
# 加载数据集
california_housing = fetch_california_housing()
# 将数据转化为 DataFrame
data = pd.DataFrame(california_housing.data, columns=california_housing.feature_names)
# 添加目标变量
data['HouseValue'] = california_housing.target
data.head()
输出:
通过数据的前几行,我们可以看到:
- 每一行代表一个区域的数据,包括收入中位数、房屋年龄、人口等信息。
- 目标变量
HouseValue
是我们要预测的房价。它表示该地区的房屋中位价格。即该地区房屋价格的中位数,反映了该地区的住房市场价值。
五、数据探索与可视化
特征与目标变量的关系
我们选择四个特征:MedInc
(收入中位数)、 HouseAge
(房屋年龄)AveRooms
(平均房间数)和 AveOccup
(平均入住人数),与目标变量 HouseValue
(房价)之间的关系进行可视化。
收入中位数与房价的关系
python
import matplotlib.pyplot as plt
from sklearn.datasets import fetch_california_housing
import pandas as pd
# 加载加利福尼亚房价数据集
california = fetch_california_housing()
# 转换为 DataFrame,便于查看
df = pd.DataFrame(california.data, columns=california.feature_names)
# 添加目标变量(房价)
df['HouseValue'] = california.target
# 从数据集中随机选择200个样本
df_sample = df.sample(n=200, random_state=42)
# 绘制收入中位数与房价的关系
plt.figure(figsize=(8, 6))
plt.scatter(df_sample['MedInc'], df_sample['HouseValue'], alpha=0.5)
plt.title("收入中位数与房价的关系")
plt.xlabel("收入中位数 (MedInc)")
plt.ylabel("房价 (单位:$100k)")
# 显示图表
plt.show()
运行结果:
房屋年龄与房价的关系
python
# 绘制房屋年龄与房价的关系
plt.figure(figsize=(8, 6))
plt.scatter(df_sample['HouseAge'], df_sample['HouseValue'], alpha=0.5)
plt.title("房屋年龄与房价的关系")
plt.xlabel("房屋年龄 (HouseAge)")
plt.ylabel("房价 (单位:$100k)")
运行结果:
平均房间数与平均入住人数对房价的关系
python
# 平均房间数与平均入住人数对房价的关系
import seaborn as sns
# 设置绘图的行数和列数(2个特征)
rows = 1
cols = 2
# 创建一个绘图对象
plt.figure(figsize=(14, 6))
# 绘制每个特征和房价之间的散点图
features = ['AveRooms', 'AveOccup']
for i, feature in enumerate(features):
plt.subplot(rows, cols, i + 1) # 设置子图位置
sns.scatterplot(x=df_sample[feature], y=df_sample['HouseValue'])
plt.title(f'{feature} 与 房价的关系')
plt.xlabel(feature)
plt.ylabel('房价 (单位:$100k)')
# 调整布局,避免重叠
plt.tight_layout()
运行结果:
六、构建线性回归模型
一元线性回归示例
收入中位数与房价的关系(线性回归)
python
# 创建线性回归模型
model = LinearRegression()
# 选择收入中位数(MedInc)与房价(HouseValue)进行线性回归分析
X_feature = df_sample[['MedInc']].values # 将MedInc转换为二维数组
y_target = df_sample['HouseValue'].values # 房价作为目标变量
# 拟合线性回归模型
model.fit(X_feature, y_target)
y_pred = model.predict(X_feature)
# 绘制收入中位数与房价的散点图及回归直线
plt.figure(figsize=(8, 6))
plt.scatter(df_sample['MedInc'], df_sample['HouseValue'], alpha=0.5, label='数据点')
plt.plot(df_sample['MedInc'], y_pred, color='red', label='回归直线')
plt.title('收入中位数与房价的关系(线性回归)')
plt.xlabel('收入中位数 (MedInc)')
plt.ylabel('房价 (单位:$100k)')
plt.legend()
# 显示图表
plt.tight_layout()
plt.show()
# 输出回归模型的评估指标
mse = mean_squared_error(y_target, y_pred)
r2 = r2_score(y_target, y_pred)
print(f"均方误差 (MSE): {mse:.2f}") # 均方误差 (MSE): 0.70
print(f"R²: {r2:.2f}") # R²: 0.43
运行结果:
为了增强图表的可读性并展示每个数据点与回归线之间的距离,可以使用 残差 来表示数据点与回归线的偏差。残差是实际值与预测值之间的差距,标记这些残差能够帮助我们理解模型的拟合效果。
收入中位数与房价的关系(带残差的线性回归)
python
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score
from sklearn.datasets import fetch_california_housing
import pandas as pd
import numpy as np
# 加载加利福尼亚房价数据集
california = fetch_california_housing()
# 转换为 DataFrame,便于查看
df = pd.DataFrame(california.data, columns=california.feature_names)
# 添加目标变量(房价)
df['HouseValue'] = california.target
# 从数据集中随机选择200个样本
df_sample = df.sample(n=200, random_state=42)
# 创建线性回归模型
model = LinearRegression()
# 选择收入中位数(MedInc)与房价(HouseValue)进行线性回归分析
X_feature = df_sample[['MedInc']].values # 将MedInc转换为二维数组
y_target = df_sample['HouseValue'].values # 房价作为目标变量
# 拟合线性回归模型
model.fit(X_feature, y_target)
y_pred = model.predict(X_feature)
# 计算残差(数据点与回归线的垂直距离)
residuals = y_target - y_pred
# 绘制收入中位数与房价的散点图及回归直线
plt.figure(figsize=(10, 8))
plt.scatter(df_sample['MedInc'], df_sample['HouseValue'], alpha=0.5, label='数据点')
# 绘制回归直线
plt.plot(df_sample['MedInc'], y_pred, color='red', label='回归直线')
# 绘制每个点到回归线的距离(残差)
for i in range(len(df_sample)):
plt.plot([df_sample['MedInc'].iloc[i], df_sample['MedInc'].iloc[i]],
[df_sample['HouseValue'].iloc[i], y_pred[i]], color='gray', linestyle='--', alpha=0.7)
plt.title('收入中位数与房价的关系(带残差的线性回归)')
plt.xlabel('收入中位数 (MedInc)')
plt.ylabel('房价 (单位:$100k)')
plt.legend()
# 显示图表
plt.tight_layout()
plt.show()
运行结果:
多元线性回归示例
静态多元线性回归模型
我们使用 Plotly
库创建一个交互式的三维图表,展示收入中位数(MedInc
)、房屋年龄(HouseAge
)和房间数(AveRooms
)对房价的影响。
python
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from sklearn.linear_model import LinearRegression
# 选择三个特征来进行回归建模
features = ['MedInc', 'HouseAge', 'AveRooms']
# 从数据集中选择200个样本(可以是之前已经处理好的 df_sample)
df_sample = df.sample(n=200, random_state=42)
# 提取特征和目标变量
X = df_sample[features].values # 特征
y = df_sample['HouseValue'].values # 房价(目标变量)
# 创建三维回归模型
model = LinearRegression()
model.fit(X, y) # 拟合线性回归模型
# 获取回归系数
intercept = model.intercept_
coefficients = model.coef_
# 创建三维散点图
fig = plt.figure(figsize=(12, 8))
ax = fig.add_subplot(111, projection='3d')
# 绘制数据点
ax.scatter(df_sample['MedInc'], df_sample['HouseAge'], df_sample['AveRooms'], c=y, cmap='viridis', s=30, label='数据点')
# 绘制回归平面
xx, yy = np.meshgrid(np.linspace(df_sample['MedInc'].min(), df_sample['MedInc'].max(), 10),
np.linspace(df_sample['HouseAge'].min(), df_sample['HouseAge'].max(), 10))
zz = intercept + coefficients[0] * xx + coefficients[1] * yy # 计算平面上的z值,即预测的房价
# 绘制平面
ax.plot_surface(xx, yy, zz, color='r', alpha=0.5)
# 设置标签
ax.set_xlabel('收入中位数 (MedInc)')
ax.set_ylabel('房屋年龄 (HouseAge)')
ax.set_zlabel('房价 (HouseValue)')
ax.set_title('收入中位数, 房屋年龄, 平均房间数 与 房价的关系(三维线性回归模型)')
# 设置3D图形的长宽比例
ax.set_box_aspect([1, 1, 1]) # 可以调整长、宽和高度的比例
# 调整边距,确保标签不被裁剪
plt.subplots_adjust(left=0, right=1, bottom=0, top=1)
plt.show()
运行结果:
动态多元线性回归模型
python
import plotly.graph_objects as go
import pandas as pd
import numpy as np
from sklearn.datasets import fetch_california_housing
from sklearn.linear_model import LinearRegression
# 从sklearn加载加利福尼亚房价数据集
california_housing = fetch_california_housing()
X = california_housing.data # 特征数据
y = california_housing.target # 目标数据(房价)
# 只选择前500个样本进行分析
X = X[:500, :]
y = y[:500]
# 创建DataFrame
df_sample = pd.DataFrame(X, columns=california_housing.feature_names)
df_sample['HouseValue'] = y # 将目标房价加入数据中
# 选择需要的特征进行线性回归
features = ['MedInc', 'HouseAge', 'AveRooms']
# 提取特征和目标变量
X = df_sample[features].values # 特征
y = df_sample['HouseValue'].values # 房价(目标变量)
# 创建线性回归模型
model = LinearRegression()
model.fit(X, y) # 拟合线性回归模型
# 获取回归系数
intercept = model.intercept_
coefficients = model.coef_
# 创建三维散点图
fig = go.Figure()
# 绘制数据点
fig.add_trace(go.Scatter3d(
x=df_sample['MedInc'],
y=df_sample['HouseAge'],
z=df_sample['AveRooms'],
mode='markers',
marker=dict(
size=5,
color=y, # 房价
colorscale='Viridis', # 颜色映射
colorbar=dict(title="房价 (单位:$100k)", tickvals=[0, 1, 2, 3, 4, 5], ticktext=["$0", "$100k", "$200k", "$300k", "$400k", "$500k"], len=0.9, yanchor="top", y=0.99), # 优化颜色条
opacity=0.8
),
name='数据点', # 可以去掉 name 来进一步隐藏图例
showlegend=False # 隐藏数据点的图例项
))
# 绘制回归平面:通过固定 `AveRooms` 来获得多个平面
x_grid = np.linspace(df_sample['MedInc'].min(), df_sample['MedInc'].max(), 20)
y_grid = np.linspace(df_sample['HouseAge'].min(), df_sample['HouseAge'].max(), 20)
x_grid, y_grid = np.meshgrid(x_grid, y_grid)
# 使用 AveRooms 的一个固定值来计算平面上的 z 值(这里选择 AveRooms 的中位数作为固定值)
AveRooms_fixed = df_sample['AveRooms'].median()
z_grid = intercept + coefficients[0] * x_grid + coefficients[1] * y_grid + coefficients[2] * AveRooms_fixed
# 绘制回归平面
fig.add_trace(go.Surface(
x=x_grid,
y=y_grid,
z=z_grid,
opacity=0.5,
colorscale='Reds', # 使用红色调来表示回归平面
showscale=False # 不显示平面颜色条
))
# 设置布局,增加图表大小和优化显示
fig.update_layout(
scene=dict(
xaxis_title='MedInc (收入中位数)',
yaxis_title='HouseAge (房屋年龄)',
zaxis_title='AveRooms (每户平均房间数)',
xaxis=dict(
tickangle=45, # 旋转x轴标签,避免重叠
tickfont=dict(size=10) # 调整字体大小
),
yaxis=dict(
tickangle=45, # 旋转y轴标签,避免重叠
tickfont=dict(size=10) # 调整字体大小
),
zaxis=dict(
tickfont=dict(size=10) # 调整z轴字体大小
)
),
title='加利福尼亚房价数据 - 线性回归三维图',
autosize=False, # 禁用自动调整大小
width=1200, # 增加图表宽度
height=900, # 增加图表高度
showlegend=True
)
# 显示图表
fig.show()
运行结果:
七、结论
线性回归作为机器学习中的基础算法,虽简单却功能强大。通过本文的介绍,您已经了解了一元和多元线性回归的基本原理、实现方法以及其在数据分析和预测中的应用。掌握线性回归不仅为学习更复杂的模型奠定了坚实的基础,也使其成为数据科学中不可或缺的工具。
希望这篇入门文章能帮助您运用线性回归 解决实际问题,并掌握回归模型的使用技巧。若您对模型优化感兴趣,可以进一步探索正则化方法,如岭回归和 Lasso
回归,以提升模型性能并减少过拟合现象。
同系列文章推荐
如果你觉得本文对你有所帮助,不妨看看以下同系列文章,深入学习 AI
开发的各个环节:
- 从零开始:如何用Python训练一个AI模型(超详细教程)
- 图像描述自动生成:如何让AI"看图说话"?
- AI与数据集:从零基础到全面应用的深度解析(超详细教程)
- 让计算机"听懂"人类语言:自然语言处理详细指南
- 💻TensorFlow 与 PyTorch 对比:哪个更适合初学者?🔍
欢迎点击链接阅读,让你的 AI
学习之旅更加全面丰富! 🚀