如何并行化基于机器学习模型的交易策略回测?

为了回测基于机器学习模型的交易策略,我希望能够并行计算模型的重新训练过程。

现在我的问题是:

有没有机会提高我的算法速度?

它是使用scikit-learn在Python中实现的。回测过程定义如下:

  1. 在前900个数据点(前三年)上训练模型
  2. 对下一天的t+1进行预测
  3. 在下一个数据点t+1上重新训练模型
  4. 再次用模型对t+2天进行预测
  5. 重新训练模型….
  6. 进行预测…

简单来说,就是对下一个数据点进行预测,然后在这个数据点上重新训练模型。一直这样做,直到当前天(最后一个数据点)。对于某些股票预测,这可能是多达5000个数据点,这意味着通过从最初的900个数据点开始训练模型,我需要重新训练和预测模型4100次。

为了并行化这个过程,我使用了多处理。我有机会使用一台提供40个CPU内核的服务器。所以我所做的是:

  1. 将4100个数据点分成40份
  2. 在每个内核上启动一个进程,运行一部分的过程
  3. 完成过程后,将结果写入磁盘
  4. 收集每个结果并汇总

Python代码:

pool = Pool()results = []for i in range(len(parts)):    try:        result = pool.apply_async(classify_parts,[parts[i], parts[i+1]])        results.append(result)    except IndexError:        continuefor result in results:    result.get()

方法classify_parts启动给定范围的过程。例如,如果我有500个数据点,并且通过在100个数据点上训练模型开始整个回测,那么剩下的400个数据点(天)用于回测,这意味着:

  1. 将400个数据点分为40份 [10,20,30,…,380,390,400]
  2. 在每个内核上启动一个进程:
    • classify_parts( 10, 20 ), … , classify_parts( 390, 400 )
  3. 从磁盘收集结果并汇总

希望我能清晰地说明我的概念。

所以我最大的问题是,是否有更有效的方法来进行基于机器学习模型的回测,该模型在每个下一个数据点(天)上重新训练?因为用这种方法,对5000个数据点的回测过程需要超过10分钟。

也许增量/在线学习是这里的出路?


回答:

首先,这并不是并行化进程调度。

如果有疑问,阅读进一步内容前,可以重新审视一下关于串行并行仅并发进程调度的理论细节。

用简单英语表达

事情可能基于原则(意图)或某种资源限制而进入串行操作模式。如果一个人要在键盘上输入单词”parallel“,字母p、接下来a、接下来r…等必须按顺序(串行)触碰,否则输入过程无法提供保证正确的结果——即屏幕上的单词”parallel“(为了这个例子的清晰度,我们假设忽略了使用Shift键的可能性)。

任何人都可以测试,如果尝试同时按下所有键,或成对按下,或在键盘上有猫站着时会产生什么…欢迎任何额外的想法进行实践实验。

串行进程无法加速

在任何其他情况下,除了通过获取更快的处理资源和/或降低进程间传输延迟(或在存在已知的新、更智能的算法,且该算法对善良的程序员来说可行并能在可用资源上实现的情况下)。


什么是真正的并行进程?

另一方面,有些事情必须组织起来,以便在光谱的另一端发生——如果所有事情必须同时开始、发生和完成,否则进程的结果被认为是错误的。能举个例子吗?

  • 想象几个视觉上简单易懂的例子——红箭飞行表演队——一组9架喷气式飞机,展示高难度的飞行表演和机动

    enter image description here

    或者Frecce Tricolori

    enter image description here

    所有飞机必须在同一时间以相同的方式移动,否则精彩的表演就会失败。

  • 想象一场音乐会必须进行。这正是最终的PARALLEL进程,人们会立即认识到,如果不是这样会多么具有破坏性

    enter image description here

  • 想象一个多自由度机器人控制系统,其中所有运动必须在闭环[执行器 – 检测器 – 驱动器]子系统的同步、协调控制下进行,适用于所有几个编程控制的轴。系统必须作为一个并行进程一起控制所有数控轴——否则机器人手臂将永远无法跟随黑线——定义的、曲线的、时空轨迹在+4-D空间中(最好实时观看)。

    enter image description here

机器人控制的例子显示,当我们从特技飞行或交响乐的例子中走得越远,对于我们有一些直接经验(或我们的想象力可以提供一些理解)的例子,并行进程调度可能看起来更难感知或实现,但交响乐似乎是最好的提醒,当我们质疑一个问题是否确实是真正的并行时。

只需问问自己,如果只有一半的乐队准时到达19:00开始演奏,或者如果一些小提琴以加速的速度演奏…或者如果演奏者只演奏一个音符,然后顺序地让他的/她的左侧邻居演奏他的/她的音符,等待演奏顺序回到同一个演奏者以演奏他的/她的下一个音符在音乐会上。没错,那将是纯粹的串行调度。)


那么,40个CPU核心能否加速我的问题?

问题仍然取决于处理过程。

enter image description here

如果学习方法(在未公开的MCVE中)内置了依赖性,例如如果classify_parts( 20, 30 )需要从classify_parts( 10, 20 )的“前一步”中获取一些输入或信息,那么答案是否定的。

如果学习方法在上述定义的意义上是独立的,那么就有机会将进程调度为“仅并发”,并从高速公路上有更多“自由”车道的事实中受益,这不仅允许车辆在一个车道上行驶,还允许一辆车超越另一辆较慢的车,在从起点到终点的路上。橄榄球队可以从城市A移动到城市B“更快”,如果在城市A的体育场有2辆或3辆或更多4座车可用,而不是只有一辆,它必须来回往返以成功地将所有球员移动到城市B。

接下来,即使有足够的车辆将所有球员移动到城市B,持续时间也会不舒服地高,如果从A到B的道路只有一条车道,并且从B到A的方向有高流量(不允许超车),而且有一辆拖拉机也从A到B行驶,但速度为1英里/小时。

警告:(如果在寻找真正快速的处理,更是为了最快可能的处理)

即便没有上述概述的“外部”障碍,人们也必须非常小心,不要失去从“更大”的机器+“更宽”的高速公路(更多可用资源)中获得的“仅并发”进程调度的优势。

是的,这里问题与编程工具有关。

Python在快速原型制作方面帮助很大,但要注意全局解释器锁(GIL)对代码执行的影响。

在你的情况下,使用40个线程的Pool()可能看起来很有吸引力,但仍然会等待GIL的获取/释放,所有工作将再次变成SERIAL,仅仅是因为忽略了在Python线程的Pool()上已知的GIL机制。

是的,还有其他更有前景的替代方案,如ThreadPool()等,但不仅是与代码相关的GIL步骤在破坏你加速进程的努力,而且共享数据结构也是需要注意和避免的问题。此外,Pool()的简单复制环境可能会超出系统RAM容量,交换机制将使加速进程的尝试完全不可用。不共享任何东西,否则你加速处理的梦想将因共享机制而失去,你将回到起点1号方格。

最好的方法是将代码设计为独立进程,具有零共享、非阻塞(MEM, IO)操作。

鉴于以上所有,40个CPU核心可能有助于加速“仅并发”进程。

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注