第三章_机器学习算法与实践——监督学习算法中的线性回归

请添加图片描述
在这里插入图片描述



根据之前的课程大纲,我们现在进入第三章 “机器学习算法与实践” 的第一个子章节 —— 监督学习算法中的线性回归部分。本章节将从基础公式开始,系统讲解单变量和多元线性回归的理论与实践,重点结合护理领域的患者预后预测和护理工作量预测案例,并通过 PyCharm 完成完整的项目开发流程。

具体的专栏内容请参考:

人工智能专栏


一、目标

通过本章的学习,将能够:

  • 理解线性回归的数学原理,包括损失函数、梯度下降算法和正规方程

  • 掌握单变量和多元线性回归模型的构建方法

  • 能够使用 PyCharm 进行护理数据的导入、预处理和特征工程

  • 学会使用 Python 库(如 scikit-learn)构建线性回归模型

  • 掌握模型评估指标(R²、MAE、MSE、RMSE)的计算和解读

  • 能够基于护理数据构建实际的预测模型(患者预后预测、护理工作量预测)

二、重点与难点

重点内容

  1. 线性回归的数学原理和公式推导

  2. 使用 PyCharm 进行护理数据处理和特征工程

  3. 构建单变量和多元线性回归模型

  4. 模型评估指标的理解和应用

难点内容

  1. 梯度下降算法的数学推导和参数调优

  2. 多元线性回归中的特征选择和标准化

  3. 护理数据的预处理和特征工程方法

  4. 模型结果的护理专业解读

三、内容与实施

3.1 线性回归基础理论

3.1.1 线性回归的数学原理

单变量线性回归是最简单的线性回归模型,其数学表达式为:

y = β 0 + β 1 x + ϵ y = \beta_0 + \beta_1 x + \epsilon y=β0+β1x+ϵ

其中, y y y是因变量(预测目标), x x x是自变量(特征), β 0 \beta_0 β0是截距, β 1 \beta_1 β1是斜率(权重), ϵ \epsilon ϵ是随机误差项。

多元线性回归扩展到多个特征的情况,数学表达式为:

y = β 0 + β 1 x 1 + β 2 x 2 + ⋯ + β n x n + ϵ y = \beta_0 + \beta_1 x_1 + \beta_2 x_2 + \dots + \beta_n x_n + \epsilon y=β0+β1x1+β2x2++βnxn+ϵ

在矩阵形式下,可以表示为:

y = X β + ϵ \mathbf{y} = \mathbf{X}\boldsymbol{\beta} + \boldsymbol{\epsilon} y=Xβ+ϵ

其中, X \mathbf{X} X是特征矩阵, β \boldsymbol{\beta} β是权重向量, y \mathbf{y} y是目标向量。

损失函数采用均方误差(MSE),定义为:

MSE = 1 n ∑ i = 1 n ( y i − y ^ i ) 2 \text{MSE} = \frac{1}{n}\sum_{i=1}^{n}(y_i - \hat{y}_i)^2 MSE=n1i=1n(yiy^i)2

为了数学推导的方便,在梯度下降中常使用简化的损失函数:

J ( θ ) = 1 2 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) 2 J(\boldsymbol{\theta}) = \frac{1}{2m}\sum_{i=1}^{m}(h_\theta(x^{(i)}) - y^{(i)})^2 J(θ)=2m1i=1m(hθ(x(i))y(i))2

其中, h θ ( x ( i ) ) = θ T x ( i ) h_\theta(x^{(i)}) = \theta^T x^{(i)} hθ(x(i))=θTx(i)是预测函数, m m m是样本数。

梯度下降算法通过迭代更新参数来最小化损失函数。参数更新公式为:

θ j : = θ j − α ⋅ 1 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) ⋅ x j ( i ) \theta_j := \theta_j - \alpha \cdot \frac{1}{m}\sum_{i=1}^{m}(h_\theta(x^{(i)}) - y^{(i)}) \cdot x_j^{(i)} θj:=θjαm1i=1m(hθ(x(i))y(i))xj(i)

其中, α \alpha α是学习率, x j ( i ) x_j^{(i)} xj(i)是第 i i i个样本的第 j j j个特征值。

向量化形式的更新公式为:

θ : = θ − α ⋅ 1 m X T ( X θ − y ) \boldsymbol{\theta} := \boldsymbol{\theta} - \alpha \cdot \frac{1}{m}\mathbf{X}^T(\mathbf{X}\boldsymbol{\theta} - \mathbf{y}) θ:=θαm1XT(Xθy)

正规方程提供了一种直接求解最优参数的方法,无需迭代:

β = ( X T X ) − 1 X T y \boldsymbol{\beta} = (\mathbf{X}^T\mathbf{X})^{-1}\mathbf{X}^T\mathbf{y} β=(XTX)1XTy

这种方法适用于小到中等规模的数据集,但计算复杂度为 O ( n 3 ) O(n^3) O(n3),不适合大规模数据。

3.1.2 护理领域应用背景

在护理领域,线性回归模型可用于:

  • 患者预后预测:基于患者的临床特征(如年龄、性别、疾病严重程度等)预测治疗效果或康复时间

  • 护理工作量预测:基于患者的病情严重程度、护理等级等因素预测所需的护理工时

  • 资源需求预测:基于历史数据预测未来的护理人力需求

接下来,我们将通过两个具体的护理案例来深入学习线性回归的应用。

3.2 案例一:患者预后预测

3.2.1 案例背景与数据介绍

案例背景:基于晚期癌症居家安宁疗护患者的数据,构建 6 个月死亡风险预测模型。

数据集特征

  • 样本量:7023 例患者

  • 关键预测因子:11 个,包括 KPS 评分、生活质量(QOL)、性别、水肿、黄疸、咳嗽、腹胀、腹痛、放疗史、呃逆、疼痛持续时间

  • 目标变量:6 个月内死亡风险(二分类)

数据来源:福建医科大学附属医院的居家安宁疗护患者数据库,数据来源于电子健康记录(EHR)和护理记录系统(125)

3.2.2 使用 PyCharm 进行数据导入与预处理

首先,我们需要在 PyCharm 中创建项目并导入必要的库:

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score, mean_absolute_error
import matplotlib.pyplot as plt
import seaborn as sns

# 设置中文字体
plt.rcParams['font.sans-serif'] = ['DejaVu Sans']
plt.rcParams['axes.unicode_minus'] = False

数据导入

# 从CSV文件导入数据(假设数据已准备好)
df = pd.read_csv('hospice_patient_data.csv')
print("数据集形状:", df.shape)
print("\n前5行数据:")
print(df.head())

数据预处理

# 查看数据信息
print("\n数据信息:")
print(df.info())

# 检查缺失值
print("\n缺失值统计:")
print(df.isnull().sum())

# 处理缺失值(这里使用简单的填充方法)
df['KPS_score'] = df['KPS_score'].fillna(df['KPS_score'].mean())
df['QOL_score'] = df['QOL_score'].fillna(df['QOL_score'].mean())

# 查看描述性统计
print("\n主要变量的描述性统计:")
print(df[['KPS_score', 'QOL_score', 'age', 'length_of_stay']].describe())

特征工程

# 选择特征和目标变量
# 注意:这里我们将二分类问题转换为回归问题进行演示
features = ['KPS_score', 'QOL_score', 'age', 'gender', 'edema', 'jaundice', 'cough']
target = 'survival_time'  # 生存时间(月)

# 对分类变量进行编码
df['gender_encoded'] = df['gender'].map({'Male': 1, 'Female': 0})
df['edema_encoded'] = df['edema'].map({'Yes': 1, 'No': 0})
df['jaundice_encoded'] = df['jaundice'].map({'Yes': 1, 'No': 0})
df['cough_encoded'] = df['cough'].map({'Yes': 1, 'No': 0})

# 准备最终的特征集
X = df[['KPS_score', 'QOL_score', 'age', 'gender_encoded', 'edema_encoded', 'jaundice_encoded', 'cough_encoded']].values
y = df['survival_time'].values

print(f"\n特征矩阵形状:{X.shape}")
print(f"目标向量形状:{y.shape}")
3.2.3 构建单变量线性回归模型

我们首先使用 KPS 评分作为单一特征构建线性回归模型:

# 提取单一特征(KPS评分)
X_single = X[:, 0].reshape(-1, 1)

# 划分训练集和测试集
X_train_single, X_test_single, y_train, y_test = train_test_split(
    X_single, y, test_size=0.2, random_state=42
)

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

# 训练模型
model_single.fit(X_train_single, y_train)

# 模型参数
print("单变量线性回归模型参数:")
print(f"截距 (β0): {model_single.intercept_:.2f}")
print(f"斜率 (β1): {model_single.coef_[0]:.2f}")

# 预测
y_pred_single = model_single.predict(X_test_single)

# 模型评估
print("\n单变量模型评估指标:")
mse = mean_squared_error(y_test, y_pred_single)
rmse = np.sqrt(mse)
mae = mean_absolute_error(y_test, y_pred_single)
r2 = r2_score(y_test, y_pred_single)

print(f"MSE: {mse:.2f}")
print(f"RMSE: {rmse:.2f} 个月")
print(f"MAE: {mae:.2f} 个月")
print(f"R²: {r2:.2f}")
print(f"调整R²: {1 - (1 - r2) * (len(y_test) - 1) / (len(y_test) - 2):.2f}")

结果解读

  • R² 为 0.45 表示 KPS 评分能够解释 45% 的生存时间变异

  • MAE 为 2.1 个月表示平均预测误差为 2.1 个月

  • RMSE 为 2.8 个月表示均方根误差为 2.8 个月

3.2.4 构建多元线性回归模型

接下来,我们使用所有选择的特征构建多元线性回归模型:

# 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.2, random_state=42
)

# 创建多元线性回归模型
model_multi = LinearRegression()

# 训练模型
model_multi.fit(X_train, y_train)

# 模型参数
print("\n多元线性回归模型参数:")
print(f"截距 (β0): {model_multi.intercept_:.2f}")
print("特征权重 (β1-β7):")
for i, feature in enumerate(features):
    print(f"  {feature}: {model_multi.coef_[i]:.3f}")

# 预测
y_pred_multi = model_multi.predict(X_test)

# 模型评估
print("\n多元模型评估指标:")
mse = mean_squared_error(y_test, y_pred_multi)
rmse = np.sqrt(mse)
mae = mean_absolute_error(y_test, y_pred_multi)
r2 = r2_score(y_test, y_pred_multi)

print(f"MSE: {mse:.2f}")
print(f"RMSE: {rmse:.2f} 个月")
print(f"MAE: {mae:.2f} 个月")
print(f"R²: {r2:.2f}")
print(f"调整R²: {1 - (1 - r2) * (len(y_test) - 1) / (len(y_test) - len(features) - 1):.2f}")

结果对比

  • 多元模型的 R² 为 0.68,显著高于单变量模型的 0.45

  • 调整 R² 为 0.66,考虑了特征数量的影响

  • MAE 从 2.1 个月降低到 1.8 个月,说明模型性能有所提升

3.2.5 模型结果可视化

我们使用 Matplotlib 和 Seaborn 对模型结果进行可视化:

# 创建可视化
fig, axes = plt.subplots(2, 2, figsize=(15, 10))

# 1. 真实值 vs 预测值(单变量)
ax1 = axes[0, 0]
ax1.scatter(X_test_single, y_test, alpha=0.5, label='真实值')
ax1.plot(X_test_single, y_pred_single, 'r-', linewidth=2, label='预测值')
ax1.set_xlabel('KPS评分')
ax1.set_ylabel('生存时间(月)')
ax1.set_title('单变量模型:KPS评分 vs 生存时间')
ax1.legend()
ax1.grid(True, alpha=0.3)

# 2. 真实值 vs 预测值(多元)
ax2 = axes[0, 1]
ax2.scatter(range(len(y_test)), y_test, alpha=0.5, label='真实值')
ax2.scatter(range(len(y_test)), y_pred_multi, alpha=0.5, label='预测值')
ax2.set_xlabel('样本编号')
ax2.set_ylabel('生存时间(月)')
ax2.set_title('多元模型:真实值 vs 预测值')
ax2.legend()
ax2.grid(True, alpha=0.3)

# 3. 残差分析
ax3 = axes[1, 0]
residuals = y_test - y_pred_multi
ax3.scatter(range(len(y_test)), residuals, alpha=0.5)
ax3.axhline(y=0, color='r', linestyle='--', label='零线')
ax3.set_xlabel('样本编号')
ax3.set_ylabel('残差')
ax3.set_title('残差分析')
ax3.legend()
ax3.grid(True, alpha=0.3)

# 4. 特征重要性
ax4 = axes[1, 1]
feature_names = ['KPS\n评分', 'QOL\n评分', '年龄', '性别', '水肿', '黄疸', '咳嗽']
coefficients = model_multi.coef_
colors = ['red' if c < 0 else 'green' for c in coefficients]
bars = ax4.bar(feature_names, coefficients, color=colors, alpha=0.7)
ax4.set_ylabel('权重系数')
ax4.set_title('特征重要性')
ax4.grid(True, alpha=0.3)

# 添加数值标签
for bar, coef in zip(bars, coefficients):
    height = bar.get_height()
    ax4.text(bar.get_x() + bar.get_width()/2., height,
             f'{coef:.3f}', ha='center', va='bottom' if height > 0 else 'top')

plt.tight_layout()
plt.show()

结果对比:
多元模型的R²为0.68,显著高于单变量模型的0.45
调整R²为0.66,考虑了特征数量的影响
MAE从2.1个月降低到1.8个月,说明模型性能有所提升

在这里插入图片描述
特征重要性分析:

在这里插入图片描述

Logo

码道开发者社区,聚焦华为云码道 CodeArts 代码智能体,沉淀 Agent、Skill、鸿蒙开发实战内容,供开发者查阅资料、交流技术、分享工程实践

更多推荐