Press "Enter" to skip to content

关于Dask数据框分区大小的几乎所有你想知道的事情

如何有效地在XGBoost模型中使用它

预览图片(作者提供)

最近,我和我的同事们一直在开发一个大型高负载服务,该服务利用Xgboost机器学习模型和Dask作为分布式数据处理和预测生成工具。在这里,我想分享我们在数据准备和ML模型拟合方面能够最大化使用Dask的一些发现。

Dask是什么?

Dask是一个用于处理大量数据的分布式处理库。其基本概念是将大型数组分割成小的部分(分区)。

这就是Dask数据帧的存储和处理方式:表可以被分割成小的数据帧(可以将其视为pandas数据帧),因此无需将整个表存储在内存中。整个源表可能太大而无法加载到内存中,但是单独的分区可以加载。此外,此类数据存储方式可以有效利用多个处理器核心并行化计算。

同时,这些分区(块)的大小由开发人员确定。因此,可以使用例如“Split 1”或“Split 2”将同一数据帧分割成多个分区(见图1)。

图1. 将Dask数据帧分割成分区(图片由作者提供)

选择最佳的分区大小至关重要,因为如果分区大小不合适,数据处理可能会变慢。最佳的分区大小取决于整个数据集的大小以及服务器(或笔记本电脑)的资源:CPU的数量和可用的内存。

免责声明:在接下来的内容中,为了方便起见,我们将以数据集的行数来衡量数据集的大小。所有表都由4列组成(3个特征+1个目标)。在系统中实现算法时,我们建立了对表中元素总数(行数×列数)而不是表中行数的依赖关系。

问题

Dask可以用于计算简单的统计数据和聚合,也可以用于训练大型机器学习模型(使用大量数据),例如XGBoost。由于我们开发的服务可能需要在仅有8-16GB RAM的情况下对200万至1000万条记录进行模型训练(当使用小型虚拟机时),因此我们决定进行实验。

即使在计算简单统计数据的情况下,分区的大小也非常重要,因为它可以在两种情况下显着减慢计算算法的速度:

  • 分区过大,因此在RAM中处理它们需要太多的时间和资源
  • 分区过小,因此为了处理所有分区,Dask需要频繁将这些表加载到RAM中,这会导致更多的时间用于同步和上传/下载而不是计算本身

因此,通过选择非最佳的分区大小,即使使用相同的计算资源,也会严重降低程序的性能(图2)。图2显示了使用不同分区大小的Dask数据帧拟合XGBoost模型的时间。显示了5次运行的平均执行时间。

图2. 分区大小对XGBoost模型拟合速度的影响。这些实验中的原始数据帧包含500,000行和4列(图片由作者提供)

在这篇文章中,我们讨论了寻找Dask数据框的最佳分区大小的算法。本文中展示的所有表格都是用于拟合Dask Xgboost机器学习模型的。我们还会分享一些可能对你有帮助的技巧。

文档提示

在官方的Dask文档中,有一些关于如何正确处理Dask对象(数据框、数组等)的技巧的网页,比如Dask数据框最佳实践

在这个页面上,你可以看到如下的建议:

你应该让每个分区的数据量约为100MB。

然而,这个建议是粗略的,没有考虑到服务器的计算规格、源数据集的大小以及解决问题的具体情况。

实验设置

如上所述,假设最佳分区大小取决于以下三个条件:

  • 完整数据集的大小;
  • XGBoost和Dask可以使用的CPU资源(进程数);
  • 可用的随机存取内存(RAM)。

因此,在实验过程中,计算资源的数量以及源数据集的大小是变化的。考虑的情况包括:

  • 分区大小,以千行计:[5, 10, 50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000](13种情况)
  • 完整数据集的大小,以千行计:[100, 200, 300, 400, 500, 600, 1000, 2000, 3000, 4000](10种情况)
  • CPU资源(工作进程数):[2, 3, 4](3种情况)
  • 每个工作进程可用的随机存取内存(RAM):[1GB, 2GB, 4GB](3种情况)

注意:Dask中的Worker是计算机(在服务器上)中使用分配给它的计算资源运行并与其他Worker隔离并并行工作的进程。

因此,总共分析了1170个(13 x 10 x 3 x 3)情况。为了获得更稳健的执行时间估计,每个情况都被运行了5次,然后取平均值作为指标。

作为研究的一部分,我们想要找出数据集大小的极限,虚拟机在这个极限下无法处理负载,以便更成功地扩展服务。

结果

首先,让我们来看看实验中的一般可视化结果。我们进行了不同数量的CPU核心和不同数量的RAM的运行,同时改变了原始数据集的大小和分区的大小。完成实验后,我们准备了一张仅显示最佳解决方案(分区大小)的表格。最佳分区大小是在给定条件(RAM、CPU和源数据集大小)下执行时间最短的大小。收集到的指标的相关矩阵如图3所示。

图3:实验结果的相关矩阵(作者提供的图像)

从图中可以看出,对执行时间影响最大的显然是源数据集的大小。工作进程的数量和内存的容量对拟合时间也有显著影响。块大小的影响相对较小。不过,这可能是因为执行时间和分区大小之间的依赖关系是非线性的,这也通过图2中的曲线得到了证实。此外,图4证实了测量结果的准确性,因为结果与我们的预期是一致的。

让我们来看一下带有3D图的动画(动画1)。

动画1:不同测试情况的图表,其中每一帧都是固定大小的源数据集。每个情况下的最佳表面都被显示出来(作者提供的图像)

在动画中,最优解(对于每个进程数和每个工作节点的RAM的组合)用红色圈出。也就是说,对于给定的数据集大小、核心数、RAM和分区大小,算法的执行时间最小的条件被显示出来。图表还以灰色显示了分段恒定的最优曲面(注:曲面对所有情况全局有效)。

从动画中可以看到,在某些帧中没有实验数据(没有点)(图4)。这意味着提出的计算资源不足以运行模型。

图4.包含400万行数据集的建模结果。 RAM小于4时没有结果(作者提供的图像)

从图中可以观察到,在这个数据集大小下,如果核心数较小,则应该形成更大的分区。请注意,这种关联性并非对所有情况都适用。

基于对计算资源不足的执行结果,制作了如下可视化材料(图5)。

图5.超过此限制的数据量将无法启动模型拟合。对象的数量是根据表格中的行数乘以列数计算的(作者提供的图像)

此外,根据关于失败运行的统计数据,得出了以下结论(提示):如果内存量有限,则使用较小的分区大小更可靠。

讨论

基于此研究,形成了一些关于基于Dask XGBoost模型更有效配置系统的建议。请注意,这项研究是为了在相对较小的服务器上更高效地运行Dask(而不是拥有数百吉字节RAM和数十个CPU的服务器)。

实验揭示了最优超平面。它们使用高斯过程建模。根据此算法,自动选择最佳分区大小(动画2)。

动画2.不同条件(CPU、RAM和源数据集大小)的最佳曲面。每帧显示特定源数据集大小的条件(作者提供的图像)

从动画中可以看出,平均而言,源数据集中的行数增加时,最佳分区大小会减小

结论(及提示)

希望您对了解XGBoost模型的最佳分区大小有兴趣。

我知道这篇文章变得非常“技术性”。因此,对于那些成功读到文章结尾的人,我将给出一些提示:

  • 如果您正在测量执行时间,请多次运行计算并平均结果,因为运行时间是随机的;
  • 如果您对分区大小有疑问,最好做一个小错误(否则算法不仅会运行很长时间,还可能会出现错误导致崩溃);
  • 要在Dask中本地初始化集群,使用cluster = LocalCluster()和Client(cluster) 命令。我们强烈建议仅在代码中使用单例模式初始化此类集群。您可以在此处查看如何在Python中实现单例模式。否则,每次启动时都会初始化一个新的集群;
  • 平均而言,源数据集中的行数增加时,最佳分区大小会减小。

关于Dask和机器学习的故事由Mikhail SarafanovWiredhut团队展示。

Leave a Reply

Your email address will not be published. Required fields are marked *