#AI夏令营 #Datawhale #夏令营
笔记按照学习顺序进行整理
Task1: 跑通baseline
一、赛题介绍
1.背景
题目:训练时序预测模型助力电力需求预测
电力需求的准确预测对于电网的稳定运行、能源的有效管理以及可再生能源的整合至关重要。
2.赛题任务
给定多个房屋对应电力消耗历史N天的相关序列数据等信息,预测房屋对应电力的消耗。
3.赛题数据简介
赛题数据由训练集和测试集组成,为了保证比赛的公平性,将每日日期进行脱敏,用1-N进行标识。
即1为数据集最近一天,其中1-10为测试集数据。
数据集由字段id(房屋id)、 dt(日标识)、type(房屋类型)、target(实际电力消耗)组成。
二、数据展示
1.train.csv训练数据展示
2.test.csv测试数据展示
3.baseline运行结果(submit.csv)
第一次跑baseline,得分为373.89846
三、对代码的理解
(一)代码展示
import pandas as pd
import numpy as np
train = pd.read_csv('./data/data283931/train.csv')
test = pd.read_csv('./data/data283931/test.csv')
target_mean = train[train['dt']<=20].groupby(['id'])['target'].mean().reset_index()
test = test.merge(target_mean, on=['id'], how='left')
test[['id','dt','target']].to_csv('submit.csv', index=None)
(二)理解
1. 导入需要用到的相关库
# 导入 pandas 库,用于数据处理和分析
import pandas as pd
# 导入 numpy 库,用于科学计算和多维数组操作
import numpy as np
2. 读取训练集和测试集
# 使用 read_csv() 函数从文件中读取训练集数据,文件名为 'train.csv'
train = pd.read_csv('./data/data283931/train.csv')
# 使用 read_csv() 函数从文件中读取测试集数据,文件名为 'train.csv'
test = pd.read_csv('./data/data283931/test.csv')
3. 计算训练数据小于20单位时间内对应id的目标均值(原代码这步解释不太完善)
target_mean = train[train['dt']<=20].groupby(['id'])['target'].mean().reset_index()
这一行代码执行以下操作:
-
首先,筛选出训练数据中
dt
小于等于 20 的记录。 -
然后,对这些记录按
id
进行分组。 -
计算每个
id
对应的target
列的均值。 -
最后,将分组后的结果重置索引,生成一个新的数据框
target_mean
,包含id
和对应的target
均值。
4. 将target_mean作为测试集结果进行合并
test = test.merge(target_mean, on=['id'], how='left')
这一行代码将 target_mean
数据框与 test
数据框合并:
-
使用
id
列作为合并的键。 -
使用
left
合并方式,即保留test
数据框中的所有记录,并在匹配到id
时合并target_mean
中的target
均值。
5. 保存结果文件到本地
test[['id','dt','target']].to_csv('submit.csv', index=None)
这一行代码将合并后的 test
数据框中的 id
、dt
和 target
列保存到名为 'submit.csv' 的文件中,不保存索引。
6.总结
这段baseline虽然有读取train.csv和test.csv文件,但是后面并没有对各个房屋对应电力的消耗进行预测和验证,只是简单的进行了均值处理,即:
-
筛选出训练集数据中
dt
小于等于 20 的记录,计算每个id
的target
均值。 -
将计算得到的均值与测试集数据按
id
进行合并。
可以参照这个简单的格式,在3步对数据进行预测,后面加一步对预测结果的验证来评估模型的好坏,必要时可加入可视化帮助理解数据分布和训练测试情况,还可对数据进行预处理,排除异常数据、填补缺失数据等。
(三)代码修改测试
1.修改后的代码
# 1. 导入需要用到的相关库
# 导入 pandas 库,用于数据处理和分析
import pandas as pd
# 导入 numpy 库,用于科学计算和多维数组操作
import numpy as np
# 2. 读取训练集和测试集
# 使用 read_csv() 函数从文件中读取训练集数据,文件名为 'train.csv'
train = pd.read_csv('train.csv')
# 使用 read_csv() 函数从文件中读取测试集数据,文件名为 'test.csv'
test = pd.read_csv('test.csv')
# 3. 计算训练数据最近11-20单位时间内对应id的目标均值
# 筛选出 dt 在 11 到 20 之间的记录
filtered_train = train[(train['dt'] >= 11) & (train['dt'] <= 20)]
# 按 id 分组并计算 target 均值
target_mean = filtered_train.groupby(['id'])['target'].mean().reset_index()
# 4. 将target_mean作为测试集结果进行合并
test = test.merge(target_mean, on=['id'], how='left')
# 5. 保存结果文件到本地
test[['id','dt','target']].to_csv('submit.csv', index=None)
2.预测结果
3.评分
四、收获
熟悉了baseline的运行流程,熟悉了代码逻辑,为后面运行测试打下了基础。
Task2:入门lightgbm,开始特征工程
一、LightGBM和GBDT介绍
(一)LightGBM
1.原理概述
LightGBM基于梯度提升决策树(GBDT),它通过构建多个弱学习器(通常是决策树)来提升模型的性能。每棵树都是在前一棵树的基础上建立的,通过最小化残差(实际值与预测值的差异)来提高模型的精度。
2.特性
2.1 高效性
-
快速训练:LightGBM使用基于直方图的方法来加速训练过程。它将连续特征离散化为直方图,并在离散化后的值上进行分裂,减少计算量。
-
支持大规模数据:LightGBM在处理大规模数据时表现优异,尤其适用于高维数据集和大数据量场景。
2.2 准确性
-
Leaf-wise生长策略:与按层生长的策略不同,LightGBM采用按叶子生长的策略,每次选择叶子节点分裂,可以更好地降低损失,提高模型的准确性。
-
支持多种损失函数:LightGBM支持多种损失函数,如均方误差(MSE)、交叉熵损失(Cross-Entropy Loss)等,适用于不同类型的任务。
2.3 灵活性
-
支持类别特征:LightGBM可以直接处理类别特征,不需要预处理。
-
多线程支持:LightGBM可以利用多核CPU进行并行计算,加速训练过程。
3.优缺点
3.1 优点
-
高效的训练速度和内存使用。
-
可以处理大规模数据和高维数据。
-
支持并行和分布式训练。
-
提供多种调优参数,灵活性高。
3.2 缺点
-
对数据噪声较敏感,需要进行特征选择和预处理。
-
参数调优复杂,需要较多经验。
4.代码示例
import lightgbm as lgb
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
# 加载数据集
data = load_iris()
X_train, X_test, y_train, y_test = train_test_split(data.data, data.target, test_size=0.2, random_state=42)
# 创建LightGBM数据集
train_data = lgb.Dataset(X_train, label=y_train)
test_data = lgb.Dataset(X_test, label=y_test, reference=train_data)
# 设置参数
params = {
'objective': 'multiclass',
'num_class': 3,
'metric': 'multi_logloss',
'boosting_type': 'gbdt',
'num_leaves': 31,
'learning_rate': 0.05,
'feature_fraction': 0.9
}
# 训练模型
gbm = lgb.train(params, train_data, num_boost_round=100, valid_sets=[test_data], early_stopping_rounds=10)
# 预测
y_pred = gbm.predict(X_test, num_iteration=gbm.best_iteration)
y_pred_max = [list(x).index(max(x)) for x in y_pred]
# 计算准确率
accuracy = accuracy_score(y_test, y_pred_max)
print(f'Accuracy: {accuracy:.2f}')
(二)GBDT
GBDT梯度提升决策树(Gradient Boosting Decision Tree,简称GBDT)是本次测试使用到的模型,它是一种广泛使用的机器学习方法,特别适用于回归和分类任务。它结合了决策树模型和梯度提升算法的优势,能够在各种任务中提供高精度的预测。GBDT广泛应用于各种领域,如金融风险预测、广告点击率预测、推荐系统等。其高效性和灵活性使其成为解决复杂机器学习问题的强大工具。
二、数据可视化
(一)不同房屋类型对应的实际电力消耗
1.图像(使用柱状图)
2.代码
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()
(二)某个房屋每天对应的实际电力消耗
本次可视化测试选取的是id为00037f39cf的房屋
1.图像(使用折线图)
2.代码
specific_id_df = train[train['id'] == '00037f39cf']
plt.figure(figsize=(10, 5))
plt.plot(specific_id_df['dt'], specific_id_df['target'], marker='o', linestyle='-')
plt.xlabel('DateTime')
plt.ylabel('Target Value')
plt.title("Line Chart of Target for ID '00037f39cf'")
plt.show()
三、特征工程
1.历史平移特征
通过历史平移获取上个阶段的信息;如下图所示,可以将d-1时间的信息给到d时间,d时间信息给到d+1时间,这样就实现了平移一个单位的特征构建。
2.窗口统计特征
窗口统计可以构建不同的窗口大小,然后基于窗口范围进统计均值、最大值、最小值、中位数、方差的信息,可以反映最近阶段数据的变化情况。如下图所示,可以将d时刻之前的三个时间单位的信息进行统计构建特征给我d时刻。
3.代码
# 合并训练数据和测试数据,并进行排序
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']]
四、模型训练和测试代码理解
(一)代码
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,
}
# 训练模型
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.train()
lgb_params:
-
类型:字典
-
含义:包含LightGBM模型的超参数设置。超参数决定了模型的具体行为和性能,例如学习率、最大深度等。常用参数包括:
-
'objective'
:定义目标函数,例如'regression'
、'binary'
、'multiclass'
等。 -
'metric'
:定义评估指标,例如'rmse'
、'logloss'
、'error'
等。 -
'boosting_type'
:提升方法,例如'gbdt'
、'dart'
、'goss'
等。 -
'num_leaves'
:控制树的复杂度,叶子节点数。 -
'learning_rate'
:学习率,控制每次更新的步长。 -
'feature_fraction'
:每次分裂使用的特征比例。
-
train_matrix:
-
类型:
lgb.Dataset
-
含义:训练数据集,包含特征和标签,已经转换为LightGBM的数据格式。通常使用
lgb.Dataset
来创建。
num_boost_round:
-
类型:整数
-
含义:训练的迭代次数(即树的数量)。在每一轮迭代中,模型都会训练一棵新的树并添加到现有的模型中。
valid_sets:
-
类型:列表
-
含义:包含验证数据集的列表,用于在训练过程中评估模型的性能。通常包含训练集和验证集,以便可以监控模型在训练数据和验证数据上的表现。
categorical_feature:
-
类型:列表
-
含义:指定哪些特征是类别特征。类别特征会被特殊处理,可以直接用于分裂而不需要编码。
verbose_eval:
-
类型:整数或布尔值
-
含义:控制训练过程中日志输出的频率。例如,设置为500表示每500次迭代输出一次训练和验证结果。如果设置为True,则每轮迭代都输出日志。
early_stopping_rounds:
-
类型:整数
-
含义:早停的轮数。如果在指定轮数内验证集的指标没有改善,训练将提前停止,避免过拟合。
2.lgb_params
boosting_type:
-
类型:字符串
-
含义:指定提升方法(boosting method)。
-
选项:
-
'gbdt'
(梯度提升决策树):常用的提升方法。 -
'rf'
(随机森林):一种特殊的提升方法。 -
'dart'
(Dropouts meet Multiple Additive Regression Trees):改进的GBDT,添加了dropout。 -
'goss'
(Gradient-based One-Side Sampling):通过采样减少计算量。
-
objective:
-
类型:字符串
-
含义:指定目标函数。
-
选项:
-
'regression'
:回归任务。 -
'binary'
:二分类任务。 -
'multiclass'
:多分类任务。
-
metric:
-
类型:字符串
-
含义:指定评估指标。
-
选项:
-
'mse'
(均方误差):回归任务中常用的评估指标。 -
'rmse'
(均方根误差):回归任务中常用的评估指标。 -
'logloss'
:分类任务中的对数损失。 -
'error'
:分类错误率。
-
min_child_weight:
-
类型:整数
-
含义:指定子节点中最小的样本权重和。用于控制过拟合。较大的值可以避免模型学习到局部的噪音。
num_leaves:
-
类型:整数
-
含义:每棵树的叶子节点数。值越大,模型的复杂度越高。计算量和内存消耗也会增加。
lambda_l2:
-
类型:浮点数
-
含义:L2正则化项的权重。用于控制模型的复杂度,防止过拟合。
feature_fraction:
-
类型:浮点数
-
含义:每次分裂时随机选择的特征比例。用于防止过拟合。值在0到1之间。
bagging_fraction:
-
类型:浮点数
-
含义:每次迭代时随机选择的样本比例。用于防止过拟合。值在0到1之间。
bagging_freq:
-
类型:整数
-
含义:bagging的频率,即每隔多少次迭代进行一次bagging。0表示禁用bagging。
learning_rate:
-
类型:浮点数
-
含义:学习率,控制每次更新的步长。较小的学习率通常需要更多的树(num_boost_round)。
seed:
-
类型:整数
-
含义:随机种子,确保实验的可重复性。
nthread:
-
类型:整数
-
含义:用于训练的线程数。指定为多线程可以加速训练过程。
verbose:
-
类型:整数
-
含义:控制日志输出的详细程度。-1表示不输出日志。
3.model.predict()
val_x(test_df[cols]):
-
类型:numpy数组或pandas DataFrame
-
含义:要进行预测的数据集。每一行代表一个样本,每一列代表一个特征。
val_x
即为验证集(或测试集)的特征矩阵。
num_iteration:
-
类型:整数
-
含义:指定使用多少次迭代训练的模型来进行预测。可以通过
model.best_iteration
来获得最佳迭代次数。 -
默认值:如果未指定,使用全部迭代次数训练的模型进行预测。
4.mean_squared_error
用于计算均方误差
五、结果
(一)20000轮
1.训练和测试过程
开始训练:
结束训练:
当选取的训练轮次为20000轮,可以看到最后训练的损失还在一直下降,但是验证的损失趋于稳定甚至有上升的趋势,可以初步估计模型训练次数太多导致了过拟合。
2.结果
(二)8888轮
1.训练和测试过程
2.结果
(三)1888轮
1.训练和测试过程
2.结果
六、收获
本次task让我了解了LightGBM框架和GBDT模型,让我第一次感受到了LightGBM框架的便捷,可以直接传入参数对模型直接定义然后进行训练即可,不用重新搭建网络训练检验。还让我再次学习到了数据可视化的其他方法,让我更加直观的看到数据的分布,从而对数据有个大致的了解。对于特征工程,先前我并不了解时序预测的方法,本次学习让我更加深刻的了解了历史平移特征和窗口统计特征,收获颇多。训练数据时,我也感受到了微调模型的乐趣,逐步修改训练轮次,观察训练损失和验证损失等。