在上一篇Datawhale AI 夏令营学习笔记(1)-CSDN博客,我们简单粗暴地使用了部分训练集数据的target均值进行预测,效果并不好。在本篇,我们将尝试使用特征工程、GBDT算法和LGBM模型进行优化。
1 特征工程
从上一篇中我们阅读题目是已知题目给出的数据中存在d——时间序列。对于时间序列,我们尝试使用常用的历史平移特征技术与窗口统计特征技术。
首先,我们预处理好数据。
# 使用 read_csv() 函数从文件中读取训练集数据,文件名为 'train.csv'
train = pd.read_csv('./data/train.csv')
# 使用 read_csv() 函数从文件中读取测试集数据,文件名为 'train.csv'
test = pd.read_csv('./data/test.csv')
# 合并训练数据和测试数据,并进行排序
data = pd.concat([test, train], axis=0, ignore_index=True)
data = data.sort_values(['id', 'dt'], ascending=False).reset_index(drop=True)
1.1 历史平移特征
历史平移特征是指将时间序列数据按一定的时间间隔进行平移,以生成新的特征。这种特征有助于模型捕捉时间序列中的时间依赖性和趋势。
第一段代码通过循环生成多个不同步数的历史平移特征,用于捕捉时间序列中的时间依赖性。
# 历史平移
for i in range(10, 30):
data[f'last{i}_target'] = data.groupby(['id'])['target'].shift(i)
代码分析:
- 循环遍历:对从10到29的整数进行循环。
- 按组处理:
data.groupby(['id'])
根据id
列对数据进行分组。用于处理具有多个实体的数据,让每个实体的时间序列独立。 - 生成历史平移特征:
['target'].shift(i)
对target
列进行平移操作。shift(i)
将当前组中的数据向下平移i
个位置。 - 新列命名:
data[f'last{i}_target']
为每个平移生成的新列命名。 - 将新列添加到数据集中:将生成的历史平移特征添加到数据集中。
结果:
代码执行后,数据集
data
中会多出20个新的列(从
last10_target
到
last29_target
),每列表示
target
列向下平移不同步数后的值。
1.2 窗口统计特征
窗口统计特征是通过在时间序列上定义一个滚动窗口,然后在这个窗口内计算统计量(如均值、标准差、最小值、最大值等)来生成特征。滚动窗口有助于捕捉数据的局部统计特征,从而提高模型的预测能力。
第二段代码通过对特定的历史平移特征计算均值,生成一个窗口统计特征,用于捕捉局部统计特性。
# 窗口统计
data[f'win3_mean_target'] = (data['last10_target'] + data['last11_target'] + data['last12_target']) / 3
代码分析:
- 选择特定的历史平移特征:
data['last10_target']
、data['last11_target']
和data['last12_target']
是之前生成的历史平移特征,分别表示target
列向下平移10、11和12个位置的值。 - 计算窗口均值:将这三个平移特征相加,然后除以3,计算这三个值的平均值。
- 新列命名:
data[f'win3_mean_target']
为计算出的窗口均值新列命名,命名为win3_mean_target
。 - 将新列添加到数据集中:将计算出的窗口均值特征添加到数据集中。
结果:
代码执行后,数据集
data
中会多出一个新的列
win3_mean_target
,表示从第10个到第12个历史平移特征的平均值。
至此,我们对时间序列的简单特征工程结束。接下来我们将新的数据集投喂到机器学习模型——LGBM中。
2 GBDT
在使用LGBM模型,我们有必要先了解GBDT算法。
GBDT(Gradient Boosting Decision Tree)是机器学习中一种强大的集成学习算法,常称为梯度提升决策树。它通过将多个弱分类器(通常是决策树)结合起来,逐步提高模型的预测性能。GBDT以其高准确性和灵活性在各种应用中表现出色。尽管GBDT并不是为时间序列预测专门设计的,但它强大的非线性建模能力和对复杂特征的处理能力使其在时间序列预测中也表现出色。
2.1 GBDT核心原理
GBDT的核心思想是通过逐步构建一系列决策树,每棵树都在前一棵树的基础上进行改进,也就是一个逐步迭代非线性模型来捕捉时间序列与电力损耗的关系的过程。
具体步骤如下:
- 初始化模型:首先用一个常数模型进行初始化,通常是目标变量的均值。
- 计算残差:用当前模型计算残差(即预测值与实际值的差异)。
- 训练决策树:用残差作为目标变量训练一个新的决策树。
- 更新模型:将新树的预测结果乘以学习率后加入当前模型。
- 重复:重复步骤2-4,直到达到预定的树的数量或其他停止条件。
2.2 GBDT在时间序列预测中的优势
2.2.1 非线性建模
GBDT能捕捉复杂的非线性关系。
2.2.2 特征处理能力强
GBDT能够处理各种特征类型,包括连续特征和分类特征,并且能自动进行特征选择。
2.2.3 鲁棒性好
GBDT对噪声数据有较强的抵抗力,通过集成多个决策树,能提高模型的稳定性和泛化能力。
2.2.4 无需数据平稳化
与传统的时间序列模型不同,GBDT不需要对数据进行平稳化处理,简化了预处理步骤。
2.3 GBDT在时间序列预测中的劣势
2.3.1 时间依赖性处理有限
** **GBDT本质上是一个静态模型,不能直接处理时间依赖性,需要通过特征工程引入时间依赖性。
2.3.2 计算复杂度高
** **GBDT模型的训练过程可能比较耗时,尤其在处理大规模数据集时。
2.3.3 缺乏内置的时间序列特性
** **GBDT没有内置的时间序列特性处理能力,需要额外的特征工程来引入时间序列的相关信息。
3 LightGBM
LightGBM(Light Gradient Boosting Machine)是由微软开发的一种高效的GBDT算法的实现。LightGBM专为提升GBDT的计算效率和处理大规模数据的能力而设计,特别适用于处理大规模数据集和高维特征。
3.1 与GBDT算法的区别
3.1.1 树的构建方式
** GBDT通常采用水平生长方法,即在构建决策树时,每一层的所有节点同时进行分裂。LGBM**采用叶子生长方法,每次选择叶子节点上分裂收益最大的节点进行分裂。这种方法能够更快地降低损失函数,但可能导致树结构的不平衡。
3.1.2 基于直方图的决策树算法
** LGBM**将连续特征离散化成直方图桶,通过直方图算法进行分裂计算,显著提高了计算效率并减少了内存使用。
3.1.3 处理大规模数据
** LGBM**专为大规模数据设计,能够高效处理数亿级别的样本和特征。通过优化数据存储和并行计算,LGBM在处理大规模数据时具有显著优势。
3.1.4 并行和分布式训练
** LGBM**支持多线程并行计算、GPU加速和分布式训练,极大地提升了模型训练速度和计算效率。
3.2 训练得到LGBM模型
3.2.1设置LGBM的参数
# lightgbm参数
lgb_params = {
'boosting_type': 'gbdt', #指定提升类型为梯度提升决策树
'objective': 'regression', #指定目标函数为回归任务
'metric': 'mse', #指定评估指标为均方误差
'min_child_weight': 5, #指定叶子节点最小的样本权重和
'num_leaves': 2 ** 5, #指定每棵树的最大叶子数
'lambda_l2': 10, #L2 正则化系数。该参数用于控制模型的复杂度,防止过拟合。值越大,正则化越强,模型越不容易过拟合。
'feature_fraction': 0.8, #训练每棵树时使用的特征比例。为了避免过拟合,可以设置为小于1的数值。值越小,特征采样越少。
'bagging_fraction': 0.8, #每次训练时使用的样本比例。为了避免过拟合,可以设置为小于1的数值。
'bagging_freq': 4, #每次训练时使用的样本比例。为了避免过拟合,可以设置为小于1的数值。
'learning_rate': 0.05, #学习率,用于缩小每棵树的贡献。较小的学习率通常需要更多的迭代次数。
'seed': 2024, #随机种子,用于保证结果的可重复性。
'nthread': 16, #指定 LightGBM 运行时使用的线程数。
'verbose': -1, #控制 LightGBM 的输出信息。设置为 -1 表示不输出任何信息。
'device': 'gpu', # 使用 GPU
'gpu_platform_id': 0,
'gpu_device_id': 0,
}
3.2.2 训练模型
# 训练集和验证集切分
trn_x, trn_y = train_df[train_df.dt >= 31][cols], train_df[train_df.dt >= 31]['target']
val_x, val_y = train_df[train_df.dt <= 30][cols], train_df[train_df.dt <= 30]['target']
# 构建模型输入数据
train_matrix = lgb.Dataset(trn_x, label=trn_y)
valid_matrix = lgb.Dataset(val_x, label=val_y)
# 训练模型
# 设置早停函数:每 500 轮迭代打印一次早停信息。如果验证集的损失函数在连续 500 轮迭代中没有改善,则提前停止训练。
callback = [lgb.early_stopping(stopping_rounds=500, verbose=500)]
# LGBM的训练最大迭代次数为50000课树,其中没有其他分类特征
model = lgb.train(lgb_params, train_matrix, 50000, valid_sets=[train_matrix, valid_matrix],
categorical_feature=[], callbacks=callback)
3.2.3 应用模型进行预测
# 验证集和测试集结果预测
val_pred = model.predict(val_x, num_iteration=model.best_iteration)
test_pred = model.predict(test_df[cols], num_iteration=model.best_iteration)
# 离线分数评估
score = mean_squared_error(val_pred, val_y)
print(score)
4 总结
最后,我们保存得到的预测数据并提交,得到分数。
lgb_oof, lgb_test = time_model(lgb, train, test, train_cols)
# 6. 保存结果文件到本地
test['target'] = lgb_test
test[['id', 'dt', 'target']].to_csv('submit.csv', index=None)
print("Success")
可见,我们相比上一篇分数提升了100多分!也就是说我们使用机器学习的方法后预测效果更好了!正如那句话:“数据与特征决定了机器学习的上限,而模型和算法只是逼近这个上限。” 在本篇中,我们深刻地感受到机器学习的魅力!
也许下一篇学习笔记,我仍会继续使用机器学习的方法去进行电力预测。通过调整本篇的模型参数或作更多特征工程来进行优化,争取获得更高的分数!或许,下一篇学习笔记,我们尝试使用深度学习的方法来进行预测...
** 感谢Datawhale为广大学习者提供的一切!!!**
#机器学习 #电力预测赛 #Datawhale AI夏令营
版权归原作者 Kesenal 所有, 如有侵权,请联系我们删除。