文章目录
前言
此次任务是使用进阶的机器学习模型lightgbm解决基于讯飞开放平台的“电力需求预测挑战赛”,以达到更好的预测效果。
你可以从中学会
- 使用数据集绘制柱状图和折线图,
- 使用时间序列数据构建历史平移特征和窗口统计特征,
- 使用lightgbm模型进行训练并预测。
一、基础概念
1.机器学习
-
机器学习模型的主要步骤为:探索性数据分析、数据预处理、提取特征、切分训练集与验证集、训练模型、预测结果。
-
特征工程是参与机器学习竞赛的重要环节,可以通过观察数据并结合专业背景知识改善特征或者构建新的特征。
-
机器学习中的一个经典理论是:数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限。
-
使用机器学习方法一般主要需要从获取数据&增强、特征提取和模型 三个方面下手。
2.特征工程
在构建时间序列预测模型时,合理设计历史平移特征和窗口统计特征对于提高模型的预测能力至关重要。它们可以帮助模型捕捉到时间序列数据中的复杂模式,从而提高模型的准确性和泛化能力。
(1)历史平移特征(Historical Shift Feature)
历史平移特征是通过将时间序列中过去的值平移(或延迟)一定数量的时间步来创建的。这种方法可以揭示数据中的滞后关系或趋势。
例如:如果你有一个按天记录的股票价格序列,你可以创建一个历史平移特征,将今天的股价与昨天、前天甚至更早期的股价进行比较。可以帮助模型识别价格的短期变动、增长趋势或季节性模式。
(2)窗口统计特征(Window Statistics Feature)
窗口统计特征是通过计算时间序列中特定窗口(连续时间段)内的数据的统计量来创建的。
这些统计量可以包括:平均值(Mean)、中位数(Median)、最大值(Maximum)/最小值(Minimum)、标准差(Standard Deviation)、范围(Range)、求和(Sum)、计数(Count)。
这些特征有助于模型理解数据在不同时间尺度上的行为,例如,通过计算过去30天的日平均温度,可以为气象预测模型提供有价值的信息。
应用场景
- 金融领域:在股票市场分析中,历史平移特征可以帮助识别股票价格的趋势,而窗口统计特征可以揭示价格波动性。
- 气象学:在天气预报中,历史平移特征可以展示温度或降水的短期变化,而窗口统计特征可以提供一段时间内的天气模式。
- 工业监控:在设备性能监控中,这些特征可以揭示设备的运行状态和潜在的故障模式。
3.GBDT
- 梯度提升决策树GBDT (Gradient Boosting Decision Tree)主要思想是利用弱预测模型(决策树)迭代训练以得到最优模型,该模型具有训练效果好、不易过拟合等优点。
- GBDT通常被用于多分类、点击率预测、搜索排序等任务;
- GBDT在Kaggle等数据科学竞赛和工业应用中非常流行,因为它通常能够提供高质量的预测结果。据统计Kaggle上的比赛有一半以上的冠军方案都是基于GBDT。
- GBDT的训练过程可能需要仔细的调参和较长的时间,特别是当使用大量树和深层次的树时。
- GBDT模型的解释性不如单棵决策树,但仍然可以通过特征重要性评估和其他方法来理解模型的行为。
4.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')
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()
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()
# 合并训练数据和测试数据,并进行排序
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']]
from lightgbm import early_stopping, log_evaluation
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=[],
callbacks=[
early_stopping(500, verbose=True), # 正确的调用方式
log_evaluation(period=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.参数说明
LightGBM的参数分为几个主要类别:通用参数、学习任务参数、增强方法参数、具体算法参数、数据分割参数和回调函数参数。
-
.通用参数
‘boosting_type’: 梯度提升框架的类型,‘gbdt’代表传统的决策树提升方法。其他选项包括’dart’、‘goss’和’rf’。 -
学习任务参数
‘objective’: 定义模型的优化目标,‘regression’用于回归任务。对于分类任务,可以使用’binary’或’multiclass’。 -
增强方法参数
‘metric’: 用于评估模型性能的指标,‘mse’是均方误差,适用于回归任务。其他选项包括’mae’、'rmse’等。 -
具体算法参数
- ‘min_child_weight’: 子树的最小权重,增加可以减少过拟合。
- ‘num_leaves’:树的最大叶子节点数,影响模型的复杂度。
- ‘lambda_l2’: L2正则化参数,用于惩罚模型的复杂度,增加可以减少过拟合。
- 数据分割参数
- ‘feature_fraction’: 每次分裂时随机选择的特征比例,用于防止过拟合。
- ‘bagging_fraction’:用于构建每个树的随机样本的比例。
- ‘bagging_freq’: 每多少个迭代进行一次bagging。
- 学习率和迭代次数
- ‘learning_rate’: 学习率,较小的学习率通常需要更多的迭代次数。
- ‘nthread’:使用的线程数,设置为-1可以自动检测。
- 随机性和调试
- ‘seed’: 随机数种子,用于结果的可重复性。
- ‘verbose’: 控制训练过程中的输出信息量。
2.调优建议
模型复杂度:‘min_child_weight’、‘num_leaves’ 和 ‘lambda_l2’ 可以调整以控制模型的复杂度和防止过拟合。
正则化:‘lambda_l2’ 可以调整以增加或减少模型的平滑度。
数据多样性:‘feature_fraction’ 和 ‘bagging_fraction’ 可以调整以增加训练数据的多样性。
学习率:‘learning_rate’ 可以与 ‘num_boost_round’ 结合调整,找到最佳的模型性能。
迭代次数:‘num_boost_round’ 应该根据早停法的结果进行调整,以避免过拟合。
3.调参结果
调了好多次参数就没有优化,调了学习率、叶子结点数、早停、迭代次数等等,不知道问题出在哪里,今天提交次数用完了,明天再试试。