目标:
分类任务: 开发一个神经网络,预测一氧化碳 (CO) 浓度是否超过某一阈值(CO(GT) 值的平均值)。这项任务涉及二元分类,即您的模型学会将实例分为两类:高于或低于阈值。阈值。要确定阈值,您必须首先计算CO(GT) 的平均值,其中不包括未知数据(缺失值)。然后,使用该阈值来预测网络预测的值是高于还是低于该阈值。但是您的网络应该能够处理缺失值。
原始表部分数据截图
数据处理
1. 根据原始表输出时间序列图,以日期为横坐标,value为纵坐标
可以看到当平均浓度=-200时,CO(GT), NMHC(GT), G6H5(GT)等多张图都表现为数值突增或突降,我们可以初步判断平均浓度=-200为异常值。接下来我们再生出数据分布图来进一步验证。
2. 数据分布图
我们可以进一步得出平均浓度=-200为异常值,同时我们还可以使用df.describe()
方法可以生成数据框架的描述性统计信息,从而帮助分析数据是否异常。
补充一下数据分布图的作用(来自伟大的G老师):
import pandas as pd import numpy as np import matplotlib.pyplot as plt import seaborn as sns # 生成示例数据 np.random.seed(0) data = np.random.normal(loc=0, scale=1, size=1000) df = pd.DataFrame(data, columns=['Value']) # 直方图 plt.figure(figsize=(10, 5)) plt.hist(df['Value'], bins=30, edgecolor='k', alpha=0.7) plt.title('Histogram') plt.xlabel('Value') plt.ylabel('Frequency') plt.show() # 密度图 plt.figure(figsize=(10, 5)) sns.kdeplot(df['Value'], shade=True) plt.title('Density Plot') plt.xlabel('Value') plt.ylabel('Density') plt.show() # 箱线图 plt.figure(figsize=(10, 5)) sns.boxplot(df['Value']) plt.title('Box Plot') plt.xlabel('Value') plt.show() # 小提琴图 plt.figure(figsize=(10, 5)) sns.violinplot(df['Value']) plt.title('Violin Plot') plt.xlabel('Value') plt.show()
3. 处理异常值
我们通过前面两步已经找到了异常值(气体浓度为-200),接下来我们进行处理,有几种常见的处理方法,比如直接删除,数据替换(使用中位数:中位数受异常值的影响较小,是一个稳健的统计量;插值:对于时间序列数据,可以使用前后相邻值的均值或插值法替换异常值),标记异常等。
本文使用的是插值,原因如上对于时间序列数据,可以使用前后相邻值的均值或插值法替换异常值。看一下处理异常值后的时间序列图:
df_linear_interpolation = df[columns_to_plot].interpolate(method='linear', inplace=False)
这里解释一下插值方法的选取: 首先本文选取的是线性插值的方法。如图可知,本次数据呈线性关系,并且缺失值附近有效值较多,因此采用线性的方式处理,简单效率高。那么如何分析选用哪种插值方法呢?
- 分析数据特性:
- 数据是线性(linear)的还是非线性的(spline)?
- 数据的变化趋势是平滑的还是有较大波动(nearest)?
- 数据是时间序列数据吗(time)?
- 尝试不同方法:
- 可以尝试多种插值方法,并比较其结果。
- 例如,使用
linear
、spline
、polynomial
等方法进行插值,并绘制插值前后的数据曲线。
- 评估插值效果:
- 检查插值后的数据是否符合预期:插值后的曲线看起来合理且平滑,且不会有明显的异常点或过拟合情况,说明插值结果符合预期。
- 计算插值前后的误差(如均方误差,RMSE)来评估插值方法的效果。
- 数据是否保持一致,如果是时间序列,检查插值后的时间点和值是否合理。
二分类任务
1. 计算阈值:题目里设定阈值为CO(GT) 的平均值,将数据分类为平均值以上及平均值以下
threshold = df_linear_interpolation['CO(GT)'].mean() df_linear_interpolation['CO_Target'] = (df_linear_interpolation['CO(GT)'] > threshold).astype(int)
2. 输出相关矩阵:用于表示数据集中各特征(变量)之间相关关系的矩阵
correlation_matrix = df_linear_interpolation[columns_to_plot].corr()
为什么要分析相关性:
首先相关矩阵展示了数据集中每一对特征之间的相关性。这对于理解特征之间的线性关系非常有用。相关系数的值在-1到1之间:
- 1:表示完全正相关
- 0:表示无相关性
- -1:表示完全负相关
- 特征选择
- 在进行特征选择时,相关矩阵可以帮助我们识别高度相关的特征。如果两个特征高度相关(相关系数接近1或-1),可能只需要保留一个特征,从而减少特征的冗余性。
- 检测多重共线性
- 多重共线性是指在多元回归模型中,一个特征可以被其他特征线性预测。高相关性的特征组合可能导致多重共线性问题,从而影响模型的稳定性和解释性。相关矩阵可以帮助识别这种问题。
3. 数据预处理
- 分析数据相关性:在数据预处理阶段,了解特征之间的相关性有助于做出数据转换、标准化、归一化等决策。
- 根据热图选取与CO(GT)表现相关性较高的气体,红色颜色越深相关性越高
- 对数据进行标准化处理
标准化特征是机器学习和数据分析中常用的预处理步骤。 标准化的作用是将不同特征缩放到相同的尺度上,通常是均值为0,标准差为1。我们可以看到上图为标准化之前,不同气体的数据差(比如2004-03-10,PT08.S1(CO)和C6H6(GT))还是很大的。而这种数据差异较大可能会造成模型更倾向于差异大的数据,导致训练结果准确度低,展开来讲就是以下几点:
- 模型收敛速度慢: 较大尺度的特征会主导梯度更新,导致在这些方向上步长过大,而在小尺度的特征方向上步长过小。这种不一致会使优化过程变得缓慢,模型需要更多的迭代才能收敛。
- 优化问题:未标准化的数据可能会导致损失函数的形状不对称,形成一个拉长的椭圆形等高线图。这种情况下,梯度下降法需要在较多方向上进行调整,增加了优化难度。
- 权重更新不平衡:神经网络的权重更新依赖于输入特征的值。如果特征的尺度差异较大,模型会倾向于更多地关注数值较大的特征,而忽视数值较小的特征,导致不平衡的权重更新和次优的模型性能。
- 模型稳定性问题:数据的尺度差异会导致模型输出的激活值范围差异过大,特别是在深度神经网络中,这会导致梯度消失或梯度爆炸问题,从而影响模型训练的稳定性。
- 特征贡献不平衡:当特征值差异较大时,特征的贡献会不均衡。较大数值的特征可能在模型中占据主导地位,而较小数值的特征则可能被忽视。 这会影响模型的整体表现,特别是当每个特征对预测结果都有重要贡献时。
4. 划分数据集,训练模型
划分训练集、验证集、测试集:需要注意测试集只有在最后预测的时候才用,模型训练阶段只用训练集和验证集。
本文将训练集、验证集、测试集按照7:2:1的比例划分,这个比例是比较常见的并不是硬性要求。我们可以根据数据集的大小来调整,比如数据集较大的时候,适量增加训练集比例,提高模型学习能力;数据集较小的时候,适量增加验证集,更好的评估模型的性能。
可以看我们本次训练的表现还是不错的,训练集和验证集的准确度重合较高。且根据混淆矩阵计算所得的准确度和精确度都较高。
总结
我从以下几点分析本次训练结果较好的原因:
- 对缺失或异常数据进行插值处理
- 选择相关性较高的数据进行训练(根据相关性矩阵画热图)
- 对数据进行标准化处理
- 使得模型收敛更快
- 减少大差异数据导致模型忽略小差异数据,使得消失或爆炸
- 提高模型的泛化能力
- 将数据集划分为训练集、验证集和测试集。验证集的作用:
- 调优模型超参数:验证集用于调整和选择模型的超参数(例如学习率、正则化参数、树的深度等)。通过在验证集上评估模型,可以找到最优的超参数组合,从而提升模型的性能和泛化能力。如果没有验证集,直接使用测试集进行超参数调优,会导致测试集的信息泄露,无法真正评估模型的泛化性能。
- 避免过拟合
- 模型评估:在训练集上,通过验证集评估
- 合适的训练周期(epoch),也是需要根据验证集的表现来反应
- 训练损失:通常会随着 epoch 数量的增加而减少。
- 验证损失:在一开始会随着 epoch 数量的增加而减少,但在过多的 epoch 后可能会开始增加,这表明模型开始过拟合。