datawhale夏令营机器学习笔记(一) | 时间序列回归预测baseline1

本文中包含的思考:

  • 什么是时间序列回归预测问题?
  • 为什么时间序列回归预测问题可以使用CatBoost,LightGBM、XGBoost等树模型?
    • 为什么说树模型能够比较好地处理数值型数据,可解释性较高?
  • catboost和xgboost、LightGBM有什么区别和联系?
  • 如果使用深度学习方法解决时间序列回归预测问题,我应该使用什么样的方法比较好?为什么?
  • 岭回归(Ridge)的简介
  • RepeatedKFold与KFold做交叉验证的区别
  • stacking过程中,使用pd.concat合并预测结果意味着什么?

赛题官方解读

以下出自官方baseline

2.2 赛事任务

给定数据集: 给定训练集(含验证集), 包括10只(不公开)股票、79个交易日的L1snapshot数据(前64个交易日为训练数据,用于训练;后15个交易日为测试数据,不能用于训练), 数据已进行规范化和隐藏处理,包括5档量/价,中间价,交易量等数据(具体可参考后续数据说明)。

预测任务:利用过往及当前数据预测未来中间价的移动方向,在数据上进行模型训练与预测

输入数据

  • 行情频率:3秒一个数据点(也称为1个tick的snapshot);
  • 每个数据点包括当前最新成交价/五档量价/过去3秒内的成交金额等数据;
  • 训练集中每个数据点包含5个预测标签的标注; 允许利用过去不超过100tick(包含当前tick)的数据,预测未来N个tick后的中间价移动方向。
  • 预测时间跨度:5、10、20、40、60个tick,5个预测任务;
  • 即在t时刻,分别预测t+5tick,t+10tick,t+20tick,t+40tick,t+60tick以后: 最新中间价相较t时刻的中间价:下跌/不变/上涨。

2.3 赛题数据集

  • 行情频率:3秒一个数据点(也称为1个tick的snapshot);
  • 每个数据点包括当前最新成交价/五档量价/过去3秒内的成交金额等数据;
  • 训练集中每个数据点包含5个预测标签的标注;允许利用过去不超过100tick(包含当前tick)的数据,预测未来N个tick后的中间价移动方向。
  • 预测时间跨度:5、10、20、40、60个tick,5个预测任务;即在t时刻,分别预测t+5tick,t+10tick,t+20tick,t+40tick,t+60tick以后:最新中间价相较t时刻的中间价:下跌/不变/上涨。
字段 含义 字段 含义
date 日期 n_bid1 买一价
time时间 时间戳 n_bsize1 买一量
sym 标的(仅序号) n_bid2 买二价
close 最新价/收盘价 n_bsize2 买二量
amount_delta 成交量变化 n_bid3 买三价
n_midprice 中间价 n_bsize3 买三量
n_bid4 买四价 n_ask1 卖一价
n_bsize4 买四量 n_asize1 卖一量
n_bid5 买五价 n_ask2 卖二价
n_bsize5 买五量 n_asize2 卖二量
n_ask3 卖三价 label5 5tick价格移动方向
n_asize3 卖三量 label10 10tick价格移动方向
n_ask4 卖四价 label20 20tick价格移动方向
n_asize4 卖四量 label40 40tick价格移动方向
n_ask5 卖五价 label60 60tick价格移动方向
n_asize5 卖五量

2.4 评价指标

本模型依据提交的结果文件,采用macro-F1 score进行评价,取label_5, label_10, label_20, label_40, label_60五项中的最高分作为最终得分。

官方解题思路

本题的任务是构建一种AI量化模型,利用过往及当前数据预测未来中间价的移动方向。

这种AI量化任务是典型的时间序列回归预测问题。处理该问题,一般推荐使用机器学习方法,如CatBoost,LightGBM、XGBoost等树模型,树模型能够比较好地处理数值型数据,可解释性较高。或者使用深度学习方法,但深度模型的搭建上比较复杂,需要自己构建模型结构,对于数值型数据需要进行标准化处理,可解释性弱。 我们在解决机器学习问题时,一般会遵循以下流程:

我对解题思路的理解

时间序列回归预测问题

时间序列回归预测问题涉及到基于过去的观测值来预测未来的一个或多个时间点的值。例如,股票价格、气温或销售量的预测。

为什么时间序列回归预测问题可以使用CatBoost、LightGBM、XGBoost这些树模型?

CatBoost、LightGBM、XGBoost等树模型虽然并非专为时间序列设计,但它们可以很好地捕捉到特征与目标之间的非线性关系。当我们为时间序列问题创建特征时(如滞后、滑动窗口统计等),这些模型可以有效地使用这些特征进行预测。

树模型的优势:

树模型,特别是决策树,可以直观地展示数据的分裂和决策过程,因此可解释性很强。此外,它们可以很好地处理数值型和分类型数据,不需要预先的特征缩放,能够自然地处理特征之间的交互,并且能够处理缺失数据。

CatBoost、XGBoost和LightGBM的区别和联系:

  • CatBoost

    • 全称为"Category Boosting"。
    • 专为处理分类特征而设计,并且不需要大量的数据预处理,如独热编码。
    • 通常在默认参数下表现得很好,不需要大量调参。
  • XGBoost

    • 全称为"Extreme Gradient Boosting"。
    • 是一个优化的分布式梯度增强库,旨在高效、灵活和便携。
    • 有很好的性能和速度。
  • LightGBM

    • 全称为"Light Gradient Boosting Machine"。
    • 使用基于树的学习算法,但与其他算法不同,它按叶子进行增长,而不是按层进行。
    • 更快,需要更少的内存。

三者都是基于树的模型,特别是基于梯度增强决策树(GBDT)。它们都可以处理分类和回归任务。

那么,如果使用深度学习方法,有什么适合时间序列预测问题吗?

对于时间序列预测,可以考虑使用循环神经网络(RNN)和其变种,如长短时记忆网络(LSTM)和门控循环单元(GRU)。这些模型特别适合处理序列数据,因为它们能够捕捉到数据中的时间依赖性。

选择深度学习的原因是,当数据量很大,并且存在复杂的非线性模式时,深度学习模型往往能够提供更好的性能。

之前和同学交流发现也有论文是使用决策树、梯度增强树以及随机森林等采模型集成方法对大数据时间序列问题进行预测的.

在baseline中学到的

1. 数据处理

  • 数据集的基本情况
    • 可以使用可视化查看
  • 数据预处理,包括去掉异常值、缺失值处理、数据类型转换等

2. 特征工程

本次官方提供了两种角度作为优化思路,其中进阶实战用了时间序列预测角度构建特征.

从业务角度构建特征,在量化交易方向中,常说的因子与机器学习中的特征基本一致,趋势因子、收益波动率因子、买卖压力、同成交量衰减、斜率 价差/深度,可以围绕成交量、买价和卖价进行构建。
也可以从时间序列预测角度构建特征,比如历史平移特征、差分特征、和窗口统计特征。

  • 买卖特征:基于买卖价格和买卖量进行构建,主要考虑买一卖一和买二卖二的相关特征。
  • 历史平移特征:获取上个阶段的信息。
  • 差分特征:获取相邻阶段的增长差异。可以进一步构建相邻数据比值变化、二阶差分等。
  • 窗口统计特征:基于不同的窗口大小,统计均值、最大值、最小值、中位数、方差等。

3. 模型融合

  • baseline中模型融合的方法有简单的取平均和stacking。

  • stacking是一种分层模型集成框架。以两层为例:

    • 第一层有多个基学习器,其输入为原始训练集。
    • 第二层的模型则是以第一层基学习器的输出作为特征再进行训练。

之前净好大佬做的模型融合就是取平均, 当然他也用了stacking的方法. 详见我之前的笔记

经典融合方式为stacking,stacking是一种分层模型集成框架。以两层为例,第一层由多个基学习器组成,其输入为原始训练集,第二层的模型则是以第一层基学习器的输出作为特征加入训练集进行再训练,从而得到完整的stacking模型。

第一层:(类比cv_model函数)

  1. 划分训练数据为K折(5折为例,每次选择其中四份作为训练集,一份作为验证集);

  2. 针对各个模型RF、ET、GBDT、XGB,分别进行5次训练,每次训练保留一份样本用作训练时的验证,训练完成后分别对Validation set,Test set进行预测,对于Test set一个模型会对应5个预测结果,将这5个结果取平均;对于Validation set一个模型经过5次交叉验证后,所有验证集数据都含有一个标签。此步骤结束后:**5个验证集(总数相当于训练集全部)在每个模型下分别有一个预测标签,每行数据共有4个标签(4个算法模型),测试集每行数据也拥有四个标签(4个模型分别预测得到的) **

第二层:(类比stack_model函数)

  1. 将训练集中的四个标签外加真实标签当作五列新的特征作为新的训练集 ,选取一个训练模型,根据新的训练集进行训练,然后应用测试集的四个标签组成的测试集进行预测作为最终的result。

Stacking参考代码(二分类):

python 复制代码
def stack_model(oof_1, oof_2, oof_3, predictions_1, predictions_2, predictions_3, y):
    
    '''
    输入的oof_1, oof_2, oof_3可以对应lgb_oof,xgb_oof,cat_oof
    predictions_1, predictions_2, predictions_3对应lgb_test,xgb_test,cat_test
    '''
    
    train_stack = pd.concat([oof_1, oof_2, oof_3], axis=1)
    test_stack = pd.concat([predictions_1, predictions_2, predictions_3], axis=1)
    
    oof = np.zeros((train_stack.shape[0],))
    predictions = np.zeros((test_stack.shape[0],))
    scores = []
    
    from sklearn.model_selection import RepeatedKFold
    folds = RepeatedKFold(n_splits=5, n_repeats=2, random_state=2021)
    
    for fold_, (trn_idx, val_idx) in enumerate(folds.split(train_stack, train_stack)): 
        print("fold n°{}".format(fold_+1))
        trn_data, trn_y = train_stack.loc[trn_idx], y[trn_idx]
        val_data, val_y = train_stack.loc[val_idx], y[val_idx]
        
        clf = Ridge(random_state=2021)
        clf.fit(trn_data, trn_y)

        oof[val_idx] = clf.predict(val_data)
        predictions += clf.predict(test_stack) / (5 * 2)
        
        score_single = roc_auc_score(val_y, oof[val_idx])
        scores.append(score_single)
        print(f'{fold_+1}/{5}', score_single)
    print('mean: ',np.mean(scores))
   
    return oof, predictions
  1. 输入参数
  • oof_1, oof_2, oof_3:分别对应三个模型(如LightGBM、XGBoost、CatBoost)在训练集上的out-of-fold预测结果。
  • predictions_1, predictions_2, predictions_3:分别对应这三个模型在测试集上的预测结果。
  • y:训练集的真实目标值。
  1. 特征堆叠
  • 使用pd.concat将三个模型在训练集和测试集上的预测结果合并,形成新的训练集和测试集。
    • 简而言之,pd.concat在这里的作用是将三个模型的预测结果并列放在一起,作为新的特征输入到二级模型进行训练和预测。
    • pd.concat是沿着列的方向(axis=1)合并数据的,也就是说,它并不是简单地取这三个模型的平均值,而是将它们的预测结果作为新的特征放在一起 。具体来说,如果oof_1oof_2oof_3分别有M个预测结果,那么train_stack会有3M个特征。
    • 这样做的好处是,当我们使用岭回归或其他模型时,可以学习到这三个模型预测结果之间的关系和权重,从而得到一个更好的融合预测。
  1. 初始化变量
  • oof:用于存储训练集上的融合预测结果。
  • predictions:用于存储测试集上的融合预测结果。
  • scores:用于存储每折验证的性能得分。
  1. 交叉验证策略
  • 使用RepeatedKFold进行交叉验证,其中进行了5折验证并重复了2次。
    • KFold:是一种常见的交叉验证方法,将数据集分为K个不相交的子集,每次选择一个子集作为验证集,其他的作为训练集。这个过程会重复K次,每个子集都会作为验证集一次。
    • RepeatedKFold:是KFold的扩展,它会重复执行KFold交叉验证N次。这样可以得到K*N个模型和预测结果,从而更稳健地评估模型的性能。
  1. Stacking过程
  • 对于每一折数据:

    • 划分出训练和验证子集。
    • 使用岭回归(Ridge)作为二级模型进行训练。
      • 岭回归是线性回归的一种正则化版本。它通过在损失函数中添加一个L2正则化项(所有系数的平方和)来避免过拟合。这个正则化项会惩罚那些权重过大的特征,使得模型更加稳健。
      • 岭回归的损失函数为: <math xmlns="http://www.w3.org/1998/Math/MathML"> L ( β ) = ∥ Y − X β ∥ 2 + λ ∥ β ∥ 2 L(\beta)=\|Y-X \beta\|^2+\lambda\|\beta\|^2 </math>L(β)=∥Y−Xβ∥2+λ∥β∥2
        • 其中, <math xmlns="http://www.w3.org/1998/Math/MathML"> β \beta </math>β 是模型的参数,
        • <math xmlns="http://www.w3.org/1998/Math/MathML"> λ \lambda </math>λ 是正则化强度,控制正则化的程度。
      • 当 <math xmlns="http://www.w3.org/1998/Math/MathML"> λ \lambda </math>λ 很大时,正则化的效果 更强,权重会更接近于0;
      • 当 <math xmlns="http://www.w3.org/1998/Math/MathML"> λ \lambda </math>λ 为 0 时,岭回归就变成了普通的线性回归。
    • 对验证子集和测试集进行预测。
    • 计算并打印该折的性能得分。

参考资料

官方baseline

相关推荐
程序猿进阶3 分钟前
堆外内存泄露排查经历
java·jvm·后端·面试·性能优化·oom·内存泄露
kitesxian9 分钟前
Leetcode448. 找到所有数组中消失的数字(HOT100)+Leetcode139. 单词拆分(HOT100)
数据结构·算法·leetcode
VertexGeek1 小时前
Rust学习(八):异常处理和宏编程:
学习·算法·rust
石小石Orz1 小时前
Three.js + AI:AI 算法生成 3D 萤火虫飞舞效果~
javascript·人工智能·算法
长风清留扬2 小时前
一篇文章了解何为 “大数据治理“ 理论与实践
大数据·数据库·面试·数据治理
jiao_mrswang2 小时前
leetcode-18-四数之和
算法·leetcode·职场和发展
qystca2 小时前
洛谷 B3637 最长上升子序列 C语言 记忆化搜索->‘正序‘dp
c语言·开发语言·算法
薯条不要番茄酱2 小时前
数据结构-8.Java. 七大排序算法(中篇)
java·开发语言·数据结构·后端·算法·排序算法·intellij-idea
今天吃饺子2 小时前
2024年SCI一区最新改进优化算法——四参数自适应生长优化器,MATLAB代码免费获取...
开发语言·算法·matlab
是阿建吖!2 小时前
【优选算法】二分查找
c++·算法