第三次试验 BP神经网络¶
如何使用此PM2.5回归预测脚本¶
本脚本使用多层感知机 (MLP) 神经网络对空气质量数据中的 PM2.5 浓度进行回归预测。它会执行以下操作:
通过文件对话框加载用户选择的空气质量监测数据 CSV 文件。
对数据进行预处理,包括:
识别并选择 PM2.5 作为目标变量。
选择 ‘AQI’, ‘PM10’, ‘SO2’, ‘CO’, ‘NO2’, ‘O3’ 作为特征变量。
处理非数值数据和缺失值(使用均值填充特征列的缺失值,移除目标列为缺失值的行)。
对特征数据进行标准化。
将数据划分为训练集和测试集。
训练和评估三个不同的 MLPRegressor 模型:
模型1: ReLU 激活函数,一个包含100个节点的隐藏层。
模型2: Logistic 激活函数,一个包含100个节点的隐藏层。
模型3: ReLU 激活函数,两个隐藏层,分别包含100和50个节点。
对于每个模型,输出训练集和测试集的 R² 分数、测试集的平均绝对误差 (MAE) 和均方误差 (MSE)。
绘制每个模型的训练损失曲线。
对于模型1,绘制测试集上实际 PM2.5 值与预测 PM2.5 值的散点图。
比较模型1和模型2(具有相同单隐藏层结构但不同激活函数)的训练损失曲线。
步骤:¶
环境准备:
确保您已安装 Python (建议版本 3.7+)。
安装必要的库。您可以使用 pip 安装它们:
pip install pandas numpy scikit-learn matplotlib
tkinter
通常随 Python 标准库一起提供。如果未安装,您可能需要单独安装它(例如,在某些 Linux 发行版上使用sudo apt-get install python3-tk
)。
数据准备:
您的数据文件应该是
.csv
格式。脚本会尝试使用
utf-8
和gbk
编码读取文件。文件中应包含一个名为 ‘PM2.5’ (或其变体如 ‘PM25’, ‘pm2.5’, ‘pm25’) 的列作为目标变量。
文件中应包含尽可能多的以下特征列:‘AQI’, ‘PM10’, ‘SO2’, ‘CO’, ‘NO2’, ‘O3’。这些列应该是数值类型或可以转换为数值类型。
脚本会自动处理这些列中的缺失值和非数值数据。
运行脚本:
将上述 Python 代码保存为一个
.py
文件 (例如,pm25_regressor.py
)。打开终端或命令提示符,导航到保存文件的目录。
运行脚本:
python pm25_regressor.py
选择数据文件:
脚本运行时,会弹出一个文件对话框。
请浏览并选择包含您的空气质量监测数据的 CSV 文件。
查看结果:
控制台输出:
数据加载和预处理过程中的信息、警告和错误。
使用的特征列和目标列。
每个模型训练的配置信息。
每个模型的 R² 分数、MAE 和 MSE。
绘图窗口:
模型1的实际值 vs 预测值图: 显示模型1在测试集上的预测效果。
各个模型的训练损失曲线: 显示每个模型在训练过程中的损失下降情况。
ReLU vs Logistic 损失曲线对比图: 比较具有100个隐藏节点的 ReLU 和 Logistic 激活函数的模型损失。
关闭所有绘图窗口后,脚本将完成执行并在控制台打印最终消息。
实验报告素材(基于OCR内容和脚本)¶
以下是根据您提供的OCR图片和脚本,可以用于撰写实验报告的一些章节和要点:
1. 实验名称¶
基于人工神经网络的PM2.5浓度回归预测 (对应OCR P11, P12 "实验任务"中的回归部分)
2. 实验目的 (参考OCR P11, P12)¶
理解人工神经网络模型实现回归预测任务的基本原理。
掌握使用 Python 及 scikit-learn 库构建、训练和评估 MLPRegressor 模型的方法。
通过对空气质量监测数据进行PM2.5浓度预测,实践神经网络在解决实际回归问题中的应用。
比较不同激活函数(ReLU、Logistic)和不同网络结构(单隐藏层、双隐藏层)对模型性能的影响。
学习分析模型损失函数曲线和评估指标(R² Score, MAE, MSE)。
3. 实验环境与设备 (参考OCR P11)¶
硬件: 运行Python编译环境的计算机。
软件:
操作系统 (例如: Windows, macOS, Linux)
Python (例如: 3.7 或更高版本)
主要Python库:
pandas
: 用于数据读取和处理。numpy
: 用于数值计算。scikit-learn
: 用于构建神经网络模型 (MLPRegressor)、数据预处理 (StandardScaler)、模型评估 (metrics)。matplotlib
: 用于数据可视化(绘制损失曲线、预测结果图)。tkinter
: 用于创建文件选择对话框。
代码编辑器 (例如: VS Code, PyCharm, Sublime Text 3 (如OCR P11所述))
4. 实验原理简介¶
人工神经网络 (ANN): 简述ANN的基本概念,模拟人脑神经元结构,通过连接权重进行学习。
多层感知机 (MLP):
一种前馈ANN,包含输入层、一个或多个隐藏层和输出层。
MLPRegressor
: scikit-learn中用于回归任务的MLP实现。
回归任务: 预测连续值输出(如PM2.5浓度)。
激活函数 (Activation Functions) (参考OCR P7, P8):
作用:为神经元引入非线性,使网络能够学习复杂模式。
ReLU (Rectified Linear Unit): \(f(x) = \max(0, x)\)。优点:计算简单,收敛速度快,缓解梯度消失问题。
Logistic (Sigmoid): \(f(x) = \frac{1}{1 + e^{-x}}\)。输出在 (0,1) 之间,常用于二分类输出层,但在隐藏层中可能导致梯度消失。
隐藏层 (Hidden Layers) (参考OCR P6):
hidden_layer_sizes
: 定义隐藏层的数量以及每层神经元的数量。例如(100,)
表示一个包含100个神经元的隐藏层;(100, 50)
表示两个隐藏层,第一个100个神经元,第二个50个神经元。
优化器 (Solver) (参考OCR P7, P8):
adam
: 一种基于梯度的优化算法,通常在实践中表现良好,能自适应调整学习率。
损失函数 (Loss Function):
对于回归任务,
MLPRegressor
默认使用均方误差 (Mean Squared Error, MSE) 作为损失函数进行优化。损失曲线 (
loss_curve_
): 显示训练过程中损失函数值随迭代次数 (epochs) 的变化,用于判断模型是否收敛、是否过拟合或欠拟合。
评估指标 (Evaluation Metrics) (参考OCR P5):
R² Score (决定系数): \( R^2 = 1 - \frac{\sum{(y_{true} - y_{pred})^2}}{\sum{(y_{true} - \bar{y}_{true})^2}} \)。表示模型对因变量变异的解释程度,值越接近1越好。
MAE (Mean Absolute Error, 平均绝对误差): \( MAE = \frac{1}{n} \sum{|y_{true} - y_{pred}|} \)。预测值与真实值之间绝对误差的平均值,对异常值不敏感。
MSE (Mean Squared Error, 均方误差): \( MSE = \frac{1}{n} \sum{(y_{true} - y_{pred})^2} \)。预测值与真实值之间误差平方的平均值,对异常值敏感。
数据预处理:
特征选择: 选择与目标变量相关的输入特征。
缺失值处理: 例如使用均值、中位数填充,或删除含有缺失值的样本。
数据标准化 (Standardization): 使用
StandardScaler
将特征数据转换为均值为0,标准差为1的分布,有助于神经网络更快更好地收敛。
5. 实验数据描述¶
数据来源: 空气质量监测数据 (用户提供的CSV文件)。
目标变量: PM2.5 浓度 (数值型)。
特征变量: 脚本尝试使用 ‘AQI’, ‘PM10’, ‘SO2’, ‘CO’, ‘NO2’, ‘O3’ 等空气质量指标作为特征。
数据预处理步骤:
自动识别PM2.5列名。
筛选数值型特征列,对无法转换的列给出警告。
目标列转换为数值,无法转换的设为NaN。
移除目标列为NaN的行。
对特征列中的NaN值使用该列的均值填充。
使用
StandardScaler
对特征进行标准化。
6. 实验步骤 (对应脚本流程)¶
导入所需库:
pandas
,numpy
,sklearn.model_selection
,sklearn.neural_network.MLPRegressor
,sklearn.metrics
,sklearn.preprocessing.StandardScaler
,matplotlib.pyplot
,tkinter
。加载和预处理数据 (
load_and_preprocess_data
函数):使用
tkinter.filedialog.askopenfilename
允许用户选择CSV数据文件。读取CSV文件 (尝试UTF-8和GBK编码)。
识别PM2.5目标列和预定义的特征列。
进行数据清洗:类型转换、处理缺失值(目标列NaN行移除,特征列NaN均值填充)。
数据标准化:使用
StandardScaler
对特征数据进行标准化。返回处理后的特征
X
、目标y
、特征名称和缩放器。
划分数据集: 使用
train_test_split
将数据划分为训练集和测试集 (例如,测试集比例为25%,random_state=42
)。定义和训练模型 (
train_evaluate_plot_model
函数和main_regression_task
中的模型配置):模型1:
MLPRegressor(hidden_layer_sizes=(100,), activation='relu', solver='adam', early_stopping=True, ...)
模型2:
MLPRegressor(hidden_layer_sizes=(100,), activation='logistic', solver='adam', early_stopping=True, ...)
模型3:
MLPRegressor(hidden_layer_sizes=(100, 50), activation='relu', solver='adam', early_stopping=True, ...)
使用训练数据 (
X_train
,y_train
) 对每个模型进行训练 (mlp_model.fit()
)。
评估模型性能:
使用训练好的模型对训练集和测试集进行预测。
计算并打印 R² Score (训练集和测试集),以及测试集的 MAE 和 MSE。
结果可视化:
绘制每个模型的训练损失曲线 (
mlp_model.loss_curve_
)。对于模型1,绘制测试集上实际PM2.5值与预测PM2.5值的散点图。
比较模型1和模型2的训练损失曲线。
分析与讨论: 根据输出的评估指标和图表进行分析。
7. 实验结果与分析 (根据脚本运行后产生的图表和控制台输出填写)¶
数据概览: 简述加载数据的基本情况(例如,样本量,特征数,PM2.5的分布情况——如果做了探索性分析)。
模型性能对比:
表1: 不同模型在测试集上的性能指标
模型配置
激活函数
隐藏层结构
测试集 R² Score
测试集 MAE
测试集 MSE
Model 1 (ReLU, 100 nodes)
ReLU
(100,)
填入值
填入值
填入值
Model 2 (Logistic, 100 nodes)
Logistic
(100,)
填入值
填入值
填入值
Model 3 (ReLU, 100, 50 nodes)
ReLU
(100, 50)
填入值
填入值
填入值
图1: 模型1 (ReLU, 100 nodes) 在测试集上的实际值 vs. 预测值散点图 (截图并粘贴)
分析:预测点是否紧密围绕在 y=x 线周围?是否存在系统性偏差?
图2: 模型1 (ReLU, 100 nodes) 的训练损失曲线 (截图并粘贴)
分析:损失是否随迭代次数下降并趋于稳定?下降速度如何?
图3: 模型2 (Logistic, 100 nodes) 的训练损失曲线 (截图并粘贴)
分析:与模型1对比,损失下降情况有何不同?最终损失值如何?
图4: 模型3 (ReLU, 100, 50 nodes) 的训练损失曲线 (截图并粘贴)
分析:与模型1对比,增加网络深度对损失和收敛有何影响?
图5: ReLU 与 Logistic (100个隐藏节点) 训练损失曲线对比图 (截图并粘贴)
分析:哪种激活函数在该任务和网络结构下收敛更快?最终损失更低?
结果分析:
激活函数对比 (模型1 vs 模型2):
比较R² Score, MAE, MSE。哪种激活函数表现更好?
结合损失曲线分析收敛速度和稳定性。
网络结构对比 (模型1 vs 模型3):
比较R² Score, MAE, MSE。增加隐藏层和节点数是否提升了模型性能?
是否存在过拟合或欠拟合的迹象(例如,训练集R²远高于测试集R²,或者两者都很低)?
综合评价: 哪个模型在当前数据集和任务上表现最佳?为什么?
8. 结论与讨论¶
主要结论: 总结本次实验中不同神经网络配置(激活函数、隐藏层结构)对PM2.5回归预测性能的影响。哪个模型配置表现最好。
遇到的问题与解决方法 (可选): 例如数据质量问题、模型不收敛、调参经验等。
实验的局限性与未来工作展望 (可选):
数据集大小和代表性。
特征工程的进一步探索。
更复杂的网络结构或正则化方法。
尝试其他类型的回归模型进行比较。