赞
踩
本文是基于Datawhale AI 夏令营第2期电力需求竞赛的task2学习所写。首先我们来回顾一下机器学习方法的步骤,依次为探索性数据分析、数据预处理、提取特征、切分训练集与验证集、训练模型、预测结果。在以上的步骤中,特征的提取是一关键所在,提取的特征越精确合理,模型才能更好地去学习预测结果。我们将对特征的处理称之为“特征工程”。
在机器学习中,特征工程是指从原始数据中提取、选择和构建有意义有价值的特征,以便模型能够更好地理解和处理数据,并作出准确的预测或决策。其步骤分为以下三步:一、从原始数据中挖掘出潜在的、能够反映数据本质的特征,称为特征提取;二、从提取的数据中挑选出对模型性能提升最有帮助的特征,称为特征选择;三、通过对原始特征进行组合变换等操作,创建新的特征,称为特征构建。
GBDT(Gradient Boosting Decision Tree) :梯度提升决策树是一种常用的机器学习算法,基于Boosting提升思想,通过迭代地训练一系列的决策树来最小化损失函数。在每一次迭代中,新的决策树学习之前决策树的残差,逐步对预测结果进行修正和改进,从而不断提升模型的性能。该模型训练效果好,不易过拟合,但是缺点是计算复杂度高,训练时间较长。
LightGBM(Light Gradient Boosting Machine):这是一个实现GBDT算法的框架,采用了基于直方图的算法,减少了数据分割的计算量,从而大大提高了训练效率。此外,通过优化数据结构和算法,降低内存使用,同时能支持并行学习,有效利用多核CPU进行并行计算,在处理海量数据时能够保持较好性功能,提高效率。
给定多个房屋对应电力消耗历史N天的相关序列数据等信息,预测房屋对应电力的消耗。赛题数据由训练集和测试集组成,为了保证比赛的公平性,将每日日期进行脱敏,用1-N进行标识,即1为数据集最近一天,其中1-10为测试集数据。数据集由字段id(房屋id)、 dt(日标识)、type(房屋类型)、target(实际电力消耗)组成。预测结果以 mean square error 作为评判标准,具体公式如下:
其中是真实电力消耗,是预测电力消耗。
首先导入本次代码所需的库。
- import numpy as np
- import pandas as pd
- import lightgbm as lgb
- from sklearn.metrics import mean_squared_log_error, mean_absolute_error, mean_squared_error
- import tqdm
- import sys
- import os
- import gc
- import argparse
- import warnings
- warnings.filterwarnings('ignore')
这几个库的作用如下:
numpy:提供了对多维数组和矩阵的支持,以及用于处理这些数据结构的数学运算函数。在数据处理和科学计算中被广泛使用。
pandas:提供了高性能、易于使用的数据结构和数据分析工具,特别是用于结构化数据的处理和分析。
lightgbm:是一个梯度提升框架,专注于处理大规模数据集和高效训练速度的机器学习算法。
sklearn.metrics:提供了一系列用于评估模型性能的指标,比如均方对数误差、平均绝对误差以及均方误差等。
tqdm:用于在循环中显示进度条以监视代码的运行进度。
sys:提供了对 Python 解释器的访问,支持与系统交互的功能。
os:提供了与操作系统交互的功能,如文件操作等。
gc:Python 的垃圾回收模块,用于管理内存中不再需要的对象。
argparse:解析命令行参数和选项的模块,可以帮助程序处理命令行传入的参数。
warnings:用于控制警告输出的模块,可以在代码中灵活地设置对警告的处理方式。
之后进入机器学习第一步——探索性数据分析。
- train = pd.read_csv('./data/train.csv')
- test = pd.read_csv('./data/test.csv')
在读取数据后,对数据进行可视化操作。
- import matplotlib.pyplot as plt
- # 不同type类型对应target的柱状图
- type_target_df = train.groupby('type')['target'].mean().reset_index()
- plt.figure(figsize=(8, 4))
- plt.bar(type_target_df['type'], type_target_df['target'], color=['blue', 'green'])
- plt.xlabel('Type')
- plt.ylabel('Average Target Value')
- plt.title('Bar Chart of Target by Type')
- plt.show()
得到如下柱状图
其中采用蓝绿间隔绘制使得视觉效果更好。
代码的特征工程主要构建了 历史平移特征(Lag Feature) 和 窗口统计特征(Window Statistics Features)。
历史平移特征是指在时间序列数据或者其他具有时间相关性的数据中,将过去某个时刻的特征值作为当前时刻的特征之一。这种特征的引入可以帮助机器学习模型捕捉到数据随时间变化的趋势和周期性,从而提高预测的准确性。具体来说,历史平移特征可以通过将前几个时间点(如前一天、前一周、前一个月等)的特征值作为当前时间点的输入特征之一,从而反映出数据在不同时间点上的状态变化。
如下图所示,可以将d-1时间的信息给到d时间,d时间信息给到d+1时间,这样就实现了平移一个单位的特征构建。
窗口统计特征是一种在时间序列数据或者具有时间相关性的数据中常用的特征工程技术。它与历史平移特征类似,但更为灵活和广泛应用于不同领域。具体来说,窗口统计特征是通过定义一个滑动窗口(或称为窗口大小),在每个时间点上计算该窗口内数据的统计量,然后将这些统计量作为新的特征引入模型中。这些统计量可以包括均值、标准差、最大值、最小值、中位数等。窗口统计特征的引入有助于模型捕捉到数据在不同时间段内的变化趋势和周期性,从而增强模型对数据动态特性的理解和预测能力。与简单的历史平移特征相比,窗口统计特征能够更全面地反映出数据在时间上的复杂性和变化规律。
如下图所示,可以将d时刻之前的三个时间单位的信息进行统计构建特征给我d时刻。这里采用前三天的均值,笔者尝试过使用前4天与前5天的均值,但效果都不如原先采用的前三天均值。
代码实现如下
- # 合并训练数据和测试数据,并进行排序
- data = pd.concat([test, train], axis=0, ignore_index=True)
- data = data.sort_values(['id','dt'], ascending=False).reset_index(drop=True)
-
- # 历史平移
- for i in range(10,30):
- data[f'last{i}_target'] = data.groupby(['id'])['target'].shift(i)
-
- # 窗口统计
- data[f'win3_mean_target'] = (data['last10_target'] + data['last11_target'] + data['last12_target']) / 3
-
- # 进行数据切分
- train = data[data.target.notnull()].reset_index(drop=True)
- test = data[data.target.isnull()].reset_index(drop=True)
-
- # 确定输入特征
- train_cols = [f for f in data.columns if f not in ['id','target']]
这里选择使用Lightgbm模型,也是通常作为数据挖掘比赛的基线模型,在不需要过程调参的情况的也能得到比较稳定的分数。另外需要注意训练集和验证集的构建:因为数据存在时序关系,所以需要严格按照时序进行切分,这里选择原始给出训练数据集中dt为30之后的数据作为训练数据,之前的数据作为验证数据,这样保证了数据不存在穿越问题(不使用未来数据预测历史数据)。
- def time_model(lgb, train_df, test_df, cols):
- # 训练集和验证集切分
- 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)
- # lightgbm参数
- lgb_params = {
- 'boosting_type': 'gbdt',
- 'objective': 'regression',
- 'metric': 'mse',
- 'min_child_weight': 5,
- 'num_leaves': 2 ** 5,
- 'lambda_l2': 10,
- 'feature_fraction': 0.8,
- 'bagging_fraction': 0.8,
- 'bagging_freq': 4,
- 'learning_rate': 0.05,
- 'seed': 2024,
- 'nthread' : 16,
- 'verbose' : -1,
- }
对于LightGBM模型参数的设置,这里给出如下解释:
1. boosting_type:gbdt表示使用梯度提升决策树(Gradient Boosting Decision Tree)。LightGBM 支持几种 boosting 类型,包括 GBDT、DART 和 Goss。
2. objective:regression表示模型的目标是回归任务,即预测连续值。根据具体任务,也可以设置为 `'regression_l1'`(L1 损失)、`'regression_l2'`(L2 损失)等。
3.metric:mse表示评估指标是均方误差(Mean Squared Error),用于回归任务的模型评估。可以根据任务的不同选择其他指标,如 mae(平均绝对误差)等。
4. min_child_weight:5是控制每个叶子节点最小的样本权重和。较高的值可以防止过拟合。对于分类问题,也可以设置为 min_child_samples,用于控制每个叶子节点最小的样本数。
5. num_leaves:表示树的最大叶子节点数,此处为 32。增加 num_leaves可以增加模型的复杂性。
6. lambda_l2:10是L2 正则化(Ridge 正则化)的系数,用于控制模型复杂度,减小过拟合风险。值越大,正则化效果越强。
7. feature_fraction:0.8为每棵树使用的特征的比例,即每次迭代时随机选择 80% 的特征用于训练。可以防止过拟合。
8. bagging_fraction:0.8为每棵树使用的样本的比例即每次迭代时随机选择 80% 的样本用于训练。与bagging_freq一起使用时,可以提高训练的稳定性。
9.bagging_freq:4表示每隔4次迭代进行一次 bagging 操作。与 bagging_fraction配合使用,控制样本采样的频率。
10. learning_rate:0.05为每棵树对最终预测结果的贡献程度。较小的学习率通常会提高模型的泛化能力,但需要更多的迭代次数。
11. seed:随机种子,确保实验的可重复性。不同的种子值可以导致不同的模型结果。
12. nthread:16为设置 LightGBM 使用的线程数。用来控制计算的并行度,利用多核 CPU 来加快训练速度。
13.verbose:控制日志的详细程度。-1表示关闭所有的日志输出。其他值如0或1可以用来控制日志的输出等级。
最后对模型进行训练,并进行结果预测。
-
- # 训练模型
- model = lgb.train(lgb_params, train_matrix, 50000, valid_sets=[train_matrix, valid_matrix],
- categorical_feature=[], verbose_eval=500, early_stopping_rounds=500)
- # 验证集和测试集结果预测
- 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)
-
- return val_pred, test_pred
-
- lgb_oof, lgb_test = time_model(lgb, train, test, train_cols)
-
- # 保存结果文件到本地
- test['target'] = lgb_test
- test[['id','dt','target']].to_csv('submit.csv', index=None)
在模型训练中,部分参数的解释如下:
1.lgb_params
是之前定义的模型参数。
2.train_matrix
是训练数据集的特征矩阵。
3.50000
表示最大迭代次数。
4.valid_sets=[train_matrix, valid_matrix]
指定了用于验证的数据集(训练集和验证集)。
5.categorical_feature=[]
表示没有指定特征为分类特征。
6.verbose_eval=500
表示每隔 500 次迭代打印一次训练日志。
7.early_stopping_rounds=500
表示当验证集上的评估指标在连续 500
轮迭代中没有提升时,停止训练。
通过学习特征工程以及LightGBM的使用,使得数据的预测更加精准。当然,还需要对上述的代码进行调试,可以使用其他的特征来使用。引用国际机器学习协会联合创始人之一的Pedro Domingos的一句话,“在机器学习的世界里,数据就像燃料,算法就像引擎。” 只有不断提升算法,才能让数据的作用发挥最大化。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。