文章目录
- 项目四:回归分析
- 实践目的
- 实践平台
- 实践内容
- 预测帕金森病病情的严重程度作业
- (一)数据读入及理解
- (二)数据准备
- (三)模型建立
- (四)模型预测
- (五)模型评价及优化
项目四:回归分析
实践目的
- 熟悉并掌握线性回归模型及其使用方法;
- 理解回归分析算法并能使用回归模型分析数据集;
- 熟悉模型性能评估的方法;
实践平台
- 操作系统:Windows 7 及以上
- Python 版本:3.8.x 及以上
- 开发环境:PyCharm 或 Anoconda 集成环境
实践内容
数据集:“parkinsons_updrs.data”,专注于通过远程监测设备记录帕金森病患者的语音信号来预测病情严重程度。
主要属性
subject#
:受试者编号;age
:受试者年龄;sex
:受试者性别;test_time
:从招募日期开始的时间间隔;motor_UPDRS
:运动症状帕金森病评分量表分数;total_UPDRS
:总体帕金森病评分量表分数;Jitter(%)
:声音信号频率抖动的百分比;Jitter(Abs)
:声音信号频率抖动的绝对值;Jitter:RAP
:声音信号频率抖动的相对平均扰动;Jitter:PPQ5
:与五个周期相关的频率抖动特征;Jitter:DDP
:与差分相关的频率抖动特征;Shimmer
:声音信号振幅的抖动;Shimmer(dB)
:以分贝为单位的振幅抖动;Shimmer:APQ3
:与三个周期相关的振幅抖动特征;Shimmer:APQ5
:与五个周期相关的振幅抖动特征;Shimmer:APQ11
:与十一个周期相关的振幅抖动特征;Shimmer:DDA
:与差分相关的振幅抖动特征;NHR
:噪声谐波比;HNR
:谐波噪声比;RPDE
:循环周期密度熵;DFA
:趋势波动分析;PPE
: 基频变化的非线性测量。
步骤
-
数据读入及理解
- 导入所需Python包;
- 将数据读入DataFrame格式,查看前5行数据;
- 使用
describe()
、info()
方法和shape
属性进行探索性分析;
-
数据准备
- 数据清洗:处理缺失值、重复值、异常值;
- 标准化处理;
- 使用Seaborn.pairplot()可视化展示“Jitter:RAP”、“Jitter:DDP”、“Shimmer:DDA”与“motor_UPDRS”、“total_UPDRS”的相关性;
- 准备特征矩阵(X)和目标向量(y);
-
模型建立
- 使用
train_test_split()
方法划分训练集和测试集(random_state=1,25%测试,75%训练); - 使用
LinearRegression
进行线性回归,并通过score()
方法输出模型准确率;
- 使用
-
模型预测
- 输出预测值(y_pred);
- 对比y_pred与y_test;
-
模型评价及优化
- 使用
sklearn.metrics
模块中的MSE、RMSE、R²对模型进行评价; - 建立岭回归或Lasso回归模型,进行训练和预测;
- 对岭回归或Lasso回归模型进行评价;
- 对比两种模型预测结果。
- 使用
预测帕金森病病情的严重程度作业
(一)数据读入及理解
# 1. 导入本案例所需的 Python 包
import json
import os
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt
# 显示中文
plt.rcParams['font.sans-serif'] = ['SimHei']
# 显示负号
plt.rcParams['axes.unicode_minus'] = False
# 2. 将数据读入并存为 DataFrame 格式,查看前 5 行数据
data = pd.read_csv('input/parkinsons_updrs.data')
print(data.head())
# 3. 通过 describe()、info()方法和 shape 属性等方法对读入的数据对象进行探索性分析
# 显示数据的基本统计信息
print(data.describe())
# 显示数据的信息
print(data.info())
# 显示数据的形状
print(f"数据形状: {data.shape}")
(二)数据准备
# 1. 对数据集从缺失值、重复值、异常值等方面进行数据清洗;
# 检查缺失值
print('缺失值情况:', data.isnull().sum())
# 处理缺失值(假设用均值填充)
# data.fillna(data.mean(), inplace=True)
# 检查重复值
print("\n重复值数量:", data.duplicated().sum())
# 删除重复值
# data.drop_duplicates(inplace=True)
# 异常值处理(假设使用 IQR 方法)
Q1 = data.quantile(0.25, axis=0)
Q3 = data.quantile(0.75, axis=0)
IQR = Q3 - Q1
# 定义异常值范围
outliers = ((data < (Q1 - 1.5 * IQR)) | (data > (Q3 + 1.5 * IQR)))
# 替换异常值(例如用中位数)
for column in data.columns:
if column in outliers.columns:
data.loc[outliers[column], column] = data[column].median()
# 查看异常值处理后的数据
print("异常值处理后的数据:\n", data.head())
# 2.对数据进行标准化处理;
from sklearn.preprocessing import StandardScaler
scaler = StandardScaler()
# 选定需要标准化的特征(排除非数值类型特征)
features = ["Jitter:RAP", "Jitter:DDP", "Shimmer:DDA"]
data[features] = scaler.fit_transform(data[features])
print("标准化后的数据:\n", data.head())
# 3. 通过 Seaborn.pairplot()可视化展示"Jitter:RAP","Jitter:DDP","Shimmer:DDA"与"motor_UPDRS","total_UPDRS"的相关性;
selected_columns = ['Jitter:RAP', 'Jitter:DDP', 'Shimmer:DDA', 'motor_UPDRS', 'total_UPDRS']
# 绘制 pairplot
sns.pairplot(data[selected_columns])
plt.show()
# 4. 进行回归分析前,准备好模型所需的特征矩阵(X)和目标向量(y)。
# # 特征矩阵
# X = data[["Jitter:RAP", "Jitter:DDP", "Shimmer:DDA","total_UPDRS"]]
#
# # 目标变量
# y_motor = data["motor_UPDRS"]
# 准备特征矩阵(X)和目标向量(y)
X = data[["Jitter:RAP", "Jitter:DDP", "Shimmer:DDA","total_UPDRS"]]
y_motor = data['motor_UPDRS']
y_total = data['total_UPDRS']
# 查看特征矩阵和目标向量的形状
print("特征矩阵 X 的形状:", X.shape)
print("目标向量 y_motor 的形状:", y_motor.shape[0])
print("目标向量 y_total 的形状:", y_total.shape[0])
特征矩阵 X 的形状: (5875, 4)
目标向量 y_motor 的形状: 5875
目标向量 y_total 的形状: 5875
(三)模型建立
# 1 调用 sklearn.model_selection 中的 train_test_split() 方法进行训练集和测试集的拆分
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score
# X 和 y_motor 已经定义
# X = data.drop(['motor_UPDRS', 'total_UPDRS'], axis=1)
# y_motor = data['motor_UPDRS']
# 拆分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y_motor, test_size=0.25, random_state=1)
# 查看训练数据和测试数据的数量
print("训练数据数量:", len(X_train))
print("测试数据数量:", len(X_test))
训练数据数量: 4406
测试数据数量: 1469
# 2. 调用 sklearn.linear_model 中的 LinearRegression 对训练集进行线性回归,并通过 score()方法输出模型的准确率;
# 创建线性回归模型
linear_reg = LinearRegression()
# 训练模型
linear_reg.fit(X_train, y_train)
# 输出模型的准确率(R^2 分数)
train_score = linear_reg.score(X_train, y_train)
test_score = linear_reg.score(X_test, y_test)
print("训练集准确率 (R^2):", train_score)
print("测试集准确率 (R^2):", test_score)
训练集准确率 (R^2): 0.8968939783000226
测试集准确率 (R^2): 0.8984946250185042
(四)模型预测
# 1. 输出预测值(y_pred);
# 使用训练好的模型进行预测
y_pred = linear_reg.predict(X_test)
# 输出预测值
print("预测值 (y_pred):", y_pred)
# 2. 通过可视化图表对 y_pred 和 y_test 进行对比;
import matplotlib.pyplot as plt
# 设置显示中文字体
plt.rcParams['font.sans-serif'] = ['SimHei'] # 指定默认字体
# 设置正常显示符号
plt.rcParams['axes.unicode_minus'] = False
# 创建一个图形
plt.figure(figsize=(10, 6))
# 绘制实际值和预测值
plt.scatter(y_test, y_pred, color='blue', label='预测值')
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], color='red', linewidth=2, label='实际值')
# 添加标签和标题
plt.xlabel('实际值 (y_test)')
plt.ylabel('预测值 (y_pred)')
plt.title('实际值 vs 预测值')
plt.legend()
# 显示图形
plt.show()
(五)模型评价及优化
# 1. 调用 sklearn.metrics 模块,通过均方误差(MSE)“mean_squared_error”、均方根误差(RMSE)以及决定系数(R2) “r2_score” 对模型进行评价;
from sklearn.metrics import mean_squared_error, r2_score
import numpy as np
# 计算均方误差(MSE)
mse = mean_squared_error(y_test, y_pred)
# 计算均方根误差(RMSE)
# rmse = mean_squared_error(y_test, y_pred, squared=False)
# FutureWarning: 'squared' is deprecated in version 1.4 and will be removed in 1.6. To calculate the root mean squared error, use the function'root_mean_squared_error'.
rmse = np.sqrt(mse)# 直接用 numpy 计算 RMSE
# 计算决定系数(R2)
r2 = r2_score(y_test, y_pred)
print("均方误差 (MSE):", mse)
print("均方根误差 (RMSE):", rmse)
print("决定系数 (R2_score):", r2)
# 2. 建立岭回归或 Lasso 回归模型,对数据集进行训练并预测;
from sklearn.linear_model import Ridge, Lasso
# 建立岭回归模型
ridge_reg = Ridge(alpha=1.0)
ridge_reg.fit(X_train, y_train)
y_pred_ridge = ridge_reg.predict(X_test)
# 建立 Lasso 回归模型
lasso_reg = Lasso(alpha=1.0)
lasso_reg.fit(X_train, y_train)
y_pred_lasso = lasso_reg.predict(X_test)
# 3 通过均方误差(MSE)、均方根误差(RMSE)以及决定系数(R2) 对岭回归或 Lasso 回归模型进行评价
# 评价岭回归模型
mse_ridge = mean_squared_error(y_test, y_pred_ridge)
rmse_ridge = np.sqrt(mse_ridge)
r2_ridge = r2_score(y_test, y_pred_ridge)
print("岭回归 均方误差 (MSE):", mse_ridge)
print("岭回归 均方根误差 (RMSE):", rmse_ridge)
print("岭回归 决定系数 (R2_SCORE):", r2_ridge)
# 评价 Lasso 回归模型
mse_lasso = mean_squared_error(y_test, y_pred_lasso)
rmse_lasso = np.sqrt(mse_lasso)
r2_lasso = r2_score(y_test, y_pred_lasso)
print("Lasso 回归 均方误差 (MSE):", mse_lasso)
print("Lasso 回归 均方根误差 (RMSE):", rmse_lasso)
print("Lasso 回归 决定系数 (R2_SCORE):", r2_lasso)
# 保存数据
results = {}
results['线性回归'] = {'均方误差': mse, '均方根误差': rmse, '决定系数': r2}
results['岭回归'] = {'均方误差': mse_ridge, '均方根误差': rmse_ridge, '决定系数': r2_ridge}
results['Lasso 回归'] = {'均方误差': mse_lasso, '均方根误差': rmse_lasso, '决定系数': r2_lasso}
# print(results)
# 保存数据
output_dir = 'output'
# 保存 JSON 文件
json_file_path = os.path.join(output_dir, '三种回归评价.json')
with open(json_file_path, 'w', encoding='utf-8') as f:
json.dump(results, f, ensure_ascii=False, indent=4)
print('已完成保存 JSON 文件')
{
"线性回归": {
"均方误差": 6.914145184671658,
"均方根误差": 2.6294762186929277,
"决定系数": 0.8984946250185042
},
"岭回归": {
"均方误差": 6.914213719729213,
"均方根误差": 2.629489250734677,
"决定系数": 0.8984936188671246
},
"Lasso 回归": {
"均方误差": 6.916797056785589,
"均方根误差": 2.6299804289738717,
"决定系数": 0.8984556933405978
}
}
# 4 通过可视化图表对比两种模型预测结果
# 创建一个图形
plt.figure(figsize=(15, 5))
# 绘制线性回归模型的预测结果
plt.subplot(1, 3, 1)
plt.scatter(y_test, y_pred, color='blue', label='预测值')
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], color='red', linewidth=2, label='实际值')
plt.xlabel('实际值 (y_test)')
plt.ylabel('预测值 (y_pred)')
plt.title('线性回归 实际值 vs 预测值')
plt.legend()
# 绘制岭回归模型的预测结果
plt.subplot(1, 3, 2)
plt.scatter(y_test, y_pred_ridge, color='green', label='预测值')
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], color='red', linewidth=2, label='实际值')
plt.xlabel('实际值 (y_test)')
plt.ylabel('预测值 (y_pred_ridge)')
plt.title('岭回归 实际值 vs 预测值')
plt.legend()
# 绘制 Lasso 回归模型的预测结果
plt.subplot(1, 3, 3)
plt.scatter(y_test, y_pred_lasso, color='orange', label='预测值')
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], color='red', linewidth=2, label='实际值')
plt.xlabel('实际值 (y_test)')
plt.ylabel('预测值 (y_pred_lasso)')
plt.title('Lasso 回归 实际值 vs 预测值')
plt.legend()
# 显示图形
plt.tight_layout()
plt.savefig('./output/三种回归预测结果.png')
plt.show()
# 保存图片
print('已完成保存图片')