文章目录
基础概念入门
GBDT
GBDT (Gradient Boosting Decision Tree) 是机器学习中一个长盛不衰的模型,其主要思想是利用弱分类器(决策树)迭代训练以得到最优模型,该模型具有训练效果好、不易过拟合等优点。GBDT不仅在工业界应用广泛,通常被用于多分类、点击率预测、搜索排序等任务;在各种数据挖掘竞赛中也是致命武器,据统计Kaggle上的比赛有一半以上的冠军方案都是基于GBDT。
LightGBM
LightGBM(Light Gradient Boosting Machine)是一个实现GBDT算法的框架,支持高效率的并行训练,并且具有更快的训练速度、更低的内存消耗、更好的准确率、支持分布式可以快速处理海量数据等优点。
LightGBM 框架中还包括随机森林和逻辑回归等模型。通常应用于二分类、多分类和排序等场景。
例如:在个性化商品推荐场景中,通常需要做点击预估模型。使用用户过往的行为(点击、曝光未点击、购买等)作为训练数据,来预测用户点击或购买的概率。根据用户行为和用户属性提取一些特征,包括:
- 类别特征(Categorical Feature):字符串类型,如性别(男/女)。
- 物品类型:服饰、玩具和电子等。
- 数值特征(Numrical Feature):整型或浮点型,如用户活跃度或商品价格等。
一、导入模块
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')
这段代码导入了一些Python库并设置了一些初始条件。以下是每行代码的解释:
import numpy as np: 导入NumPy库,提供支持大型多维数组和矩阵的数学函数。
import pandas as pd: 导入Pandas库,提供高效的数据操作和分析工具。
import lightgbm as lgb: 导入LightGBM库,这是一种基于决策树的梯度提升框架,特别适用于快速的分布式训练和大数据处理。
from sklearn.metrics import mean_squared_log_error, mean_absolute_error, mean_squared_error: 从scikit-learn库导入几个用于评估回归模型性能的指标函数,包括均方对数误差(mean_squared_log_error)、平均绝对误差(mean_absolute_error)和均方误差(mean_squared_error)。
import tqdm: 导入tqdm库,用于显示循环进度条,方便监控长时间运行的迭代过程。
import sys: 导入sys模块,提供对与Python解释器相关的变量和函数的访问。
import os: 导入os模块,提供了一些用于与操作系统交互的函数。
import gc: 导入gc模块,提供对垃圾回收机制的访问,允许手动释放未使用的内存。
import argparse: 导入argparse模块,用于解析命令行参数。
import warnings: 导入warnings模块,允许控制Python解释器的警告信息。
warnings.filterwarnings(‘ignore’): 这行代码设置为忽略所有的警告信息,通常在不希望警告信息干扰程序输出时使用。
总结一下,这段代码导入了多个用于数据处理、模型训练、评估和系统交互的库,并设置了忽略警告信息的选项,为后续的数据处理和模型训练做准备。
二、探索性数据分析(EDA)
在数据准备阶段,主要读取训练数据和测试数据,并进行基本的数据展示。
train = pd.read_csv('./data/train.csv')
test = pd.read_csv('./data/test.csv')
数据简单介绍:
- 其中id为房屋id,
- dt为日标识,训练数据dt最小为11,不同id对应序列长度不同;
- type为房屋类型,通常而言不同类型的房屋整体消耗存在比较大的差异;
- target为实际电力消耗,也是我们的本次比赛的预测目标。
不同type类型对应target的柱状图
代码如下(示例):
import matplotlib.pyplot as plt
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()
这段代码利用Matplotlib库生成一个柱状图,展示不同类型(type)与目标变量(target)之间的关系。以下是每行代码的解释:
import matplotlib.pyplot as plt: 导入Matplotlib库中的pyplot模块,用于绘制各种图形。
type_target_df = train.groupby(‘type’)[‘target’].mean().reset_index(): 对训练数据集(train)按type列分组,并计算每个类型对应的目标变量(target)的平均值,结果保存在type_target_df数据框中。reset_index()方法用于重置索引,使得分组结果变为一个新的数据框。
plt.figure(figsize=(8, 4)): 创建一个新的图形对象,并设置图形的大小为8英寸宽、4英寸高。
plt.bar(type_target_df[‘type’], type_target_df[‘target’], color=[‘blue’, ‘green’]): 使用plt.bar方法绘制柱状图,x轴为type_target_df数据框中的type列,y轴为type_target_df数据框中的target列,柱状图的颜色分别为蓝色和绿色。
plt.xlabel(‘Type’): 设置x轴标签为“Type”。
plt.ylabel(‘Average Target Value’): 设置y轴标签为“Average Target Value”。
plt.title(‘Bar Chart of Target by Type’): 设置图形的标题为“Bar Chart of Target by Type”。
plt.show(): 显示绘制好的图形。
这段代码的目的是生成一个柱状图,直观展示每种类型(type)的平均目标变量(target)值的差异。通过这种方式,可以观察不同类型对目标变量的影响,从而为数据分析和建模提供参考。
id为00037f39cf的按dt为序列关于target的折线图
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()
这段代码利用Matplotlib库生成一条折线图,展示特定ID的目标变量(target)随时间变化的趋势。以下是每行代码的解释:
specific_id_df = train[train[‘id’] == ‘00037f39cf’]: 从训练数据集中筛选出ID为’00037f39cf’的行,结果保存在specific_id_df数据框中。
plt.figure(figsize=(10, 5)): 创建一个新的图形对象,并设置图形的大小为10英寸宽、5英寸高。
plt.plot(specific_id_df[‘dt’], specific_id_df[‘target’], marker=‘o’, linestyle=‘-’): 使用plt.plot方法绘制折线图,x轴为specific_id_df数据框中的dt列(日期时间),y轴为specific_id_df数据框中的target列(目标值)。折线图中,数据点用圆形标记(marker=‘o’),线条为实线(linestyle=‘-’)。
plt.xlabel(‘DateTime’): 设置x轴标签为“DateTime”。
plt.ylabel(‘Target Value’): 设置y轴标签为“Target Value”。
plt.title(“Line Chart of Target for ID ‘00037f39cf’”): 设置图形的标题为“Line Chart of Target for ID ‘00037f39cf’”。
plt.show(): 显示绘制好的图形。
这段代码的目的是生成一个折线图,直观展示ID为’00037f39cf’的记录中,目标变量(target)随时间(dt)的变化趋势。通过这种方式,可以观察目标变量在不同时间点的变化情况,从而为数据分析和建模提供参考。
三、特征工程
这里主要构建了 历史平移特征 和 窗口统计特征;每种特征都是有理可据的,具体说明如下:
历史平移特征:
通过历史平移获取上个阶段的信息;如下图所示,可以将d-1时间的信息给到d时间,d时间信息给到d+1时间,这样就实现了平移一个单位的特征构建。
窗口统计特征:
窗口统计可以构建不同的窗口大小,然后基于窗口范围进统计均值、最大值、最小值、中位数、方差的信息,可以反映最近阶段数据的变化情况。如下图所示,可以将d时刻之前的三个时间单位的信息进行统计构建特征给我d时刻。
完整代码如下:
# 合并训练数据和测试数据,并进行排序
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,
}
# 训练模型
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)
复盘总结
在目前阶段,我们使用lightgbm完成了基本的模型训练,并且添加了时序问题中常见的特征提取方式,通过特征工程挖掘特征可以很快的提升模型预测效果。