1.引言
最近打比赛又一次使用到了XGBoost算法来写baseline,想起了我博士论文里使用该模型处理问题的方法,所以写下此博客,分享我对博士毕业论文中河流溶解硅影响因素这一问题的处理方法和模型,希望各位自然科学学科的小伙伴们在处理自己的数据时也可以用XGB这一实用模型来分析影响数据的各因子权重,并且可以根据模型对缺失数据进行补齐。
我的研究方向是河流水环境,通过采样、测试得到了一系列河流溶解态Si数据,此类数据具有连续、样本量大、变化明显的特性,需要选用一种更为精确的方法来研究Si与各环境指标和物化指标间的关系。机器学习算法可以通过计算机从数据集中自动分析并获得其内在规律,利用这些规律对于未知数据作出预测的算法,可以有效帮助我们模拟时间序列上的Si浓度在不同因素影响下的变化,并分辨出各影响因素对溶解Si浓度影响的程度。
2. XGBoost模型概述
本次研究中使用了XGBoost模型作为研究手段。该模型全称为eXtreme Gradient Boosting,是华盛顿大学开发出来的一项开源性机器学习项目(Chen and Guestrin, 2016)。XGBoost进行了算法和工程上的许多改进,被广泛应用在许多机器学习竞赛中,它是一个基于决策树集合的模型,主要思想是将一系列准确率不高的决策树集合起来,以构建一个性能更好的预测模型(Chen et al., 2019)。重要的是,XGBoost在传统的决策树集合的模型基础上,结合使用了提升算法和梯度算法,这两种算法的结合使得其性能大大提升,可以减少监督学习中的偏差(Bentéjac et al., 2019; Milad et al., 2021)。如图1,在XGBoost模型中,通过向模型输入训练数据,然后决策树集合中的决策树在损失函数梯度的指引下依次传递信息,最终完成了模型的训练。
图1 XGBoost模型训练流程图
图2展示了XGBoost模型应用流程的概念图。在该学习过程中,首先向计算机提供了目标水化学数据集,并建立一个预测模型分析河水Si浓度与各参数间的相关性。该问题适合运用机器学习中的监督学习方法解决,算法会在具有已知输出值(即已给定的Si浓度)的输入值-输出值进行训练和测试,然后再使用具有未知输出值的输入数据进行预测。在此分析中,已知的输入-输出对是流域内的水化学参数和测试所得的Si浓度。在完成预测后,先通过验证模型预测结果是否准确,来判断机器学习模型的适用性,然后再比较各个特征参数的特征权重(Feature importance),来讨论各特征参数与目标变量河流溶解Si的相关性。
图2 XGBoost模型应用流程图,修改自Chen et al.(2019)
3. 模型建立与应用
机器学习模型中使用的数据集为我所研究的流域内六个站点的高频时间序列数据。使用目标因变量为溶解Si浓度,特征参数包含流量、水温、pH、水化学参数(Cl-、SO42-、Na+、K+、Mg2+、Ca2+)。
为验证机器学习预测结果的准确性,我采用了对时间序列数据集设置训练集与预测集的方式,来完成验证。以站1为例,该站点共有226组数据,我首先将训练集设置为90%(200组),测试集设置为10%(26组),根据训练集机器学习的结果对Si浓度进行了预测,并将所得预测值和实测值进行对比。为了避免单站点的数据集学习带来的偶然性,对站点2的数据集(231组)也进行了评估,训练集设置为90%(205组),测试集设置为10%(26组)。在10%预测集的情况下,站点1的Si浓度预测值误差范围为0.1-7.86%,误差平均值为2.80%。站点2的Si浓度预测值误差范围是0.02-6.47%,误差平均值为1.51%。整个XGBoost算法的Si浓度预测值平均误差是2.15%。
因此,XGBoost算法基于水化学参数对溶解Si浓度的预测结果十分准确,可以根据其它水化学参数,通过机器学习对它们内在逻辑的分析,来对溶解Si浓度值进行预测。同时,通过分析模型中各特征参数的重要性,来分析影响河流溶解Si的主次要因素。此外,该模型提供了一种在水化学数据缺失并无法实测的情况下,通过机器学习方法,对缺失数据进行预测并补充的手段,如无法在部分时间点采样或部分采样数据或历史数据缺失的情况下,可以通过已有数据集,建立预测模型,对缺失数据进行预测并补充。
4.代码实现
#导入 xgboost、csv、numpy这三个需要使用的扩展式程序包
import xgboost as xgb
import csv
import numpy as np
#输入第一列为Si浓度,其余列为其他影响因子的csv文件
file='input_files.csv'
#对csv文件进行处理
with open(file, 'r') as f:
lines=csv.reader(f)
header=next(lines)
data=[]
for line in lines:
d=[]
for l in line:
try:
d.append(float(l))
except:
print(line)
data.append(d)
#将文件中的缺失值标记为nan,并对数据进行随机打乱
data=np.array(data)
data[data==99999]=np.nan
np.random.shuffle(data)
#取打乱后的最后26条数据为测试集,其余数据为训练集
X_train=data[:-26,1:]
y_train=data[:-26,0]
X_test=data[-26:,1:]
y_test=data[-26:,0]
#对数据进行XGBoost回归模型的训练
xg_reg=xgb.XGBRegressor()
xg_reg.fit(X_train,y_train)
#计算训练后模型的特征重要性
fi=xg_reg.feature_importances_
#打印模型预测的测试集结果,并与测试集实际数据进行比较
print(xg_reg.predict(X_test), y_test)
#保存训练好的模型
xg_reg.save_model("new.model")
5.小结
在我接触机器学习前,我和身边很多小伙伴一样,执着于增加数据,多测一些样,多得到几个时间点的数据,通过扩充数据来使成果更好看。但一想到数据处理,就是Excel、Origin,画关系图,最多用SPSS做个成分分析。但其实机器学习模型提供了一个更好的处理问题的方法,不仅可以帮我们找到数据间相关性,还能对各影响因子的权重作分析,还可以在部分数据缺失(如样品丢失无法补齐数据)的情况下,利用其它特征对数据进行预测补齐。
此外,对时间序列的数据其实还可以用时间序列模型做一个未来预测,但我这里由于数据量不是特别足,建立的时间序列不是特别好,如果小伙伴们有更详细的数据集(例如多年降水数据集、或者能拿到水文站很详尽的水文数据列),也可以做时间序列的模型。
References
Bentéjac C, Csörgő A, Martínez-Muñoz G. A Comparative Analysis of XGBoost[J]. arXiv e-prints, 2019: arXiv:1911.01914.
Chen T, Guestrin C. XGBoost: A Scalable Tree Boosting System[J]. arXiv e-prints, 2016: arXiv:1603.02754.
Chen M, Liu Q, Chen S, et al. XGBoost-Based Algorithm Interpretation and Application on Post-Fault Transient Stability Status Prediction of Power System[J]. IEEE Access, 2019, 7: 13149-13158.
Milad A, Hussein S H, Khekan A R, et al. Development of ensemble machine learning approaches for designing fiber-reinforced polymer composite strain prediction model[J]. Engineering with Computers, 2021.