📢 转载信息
原文链接:https://www.kdnuggets.com/is-your-machine-learning-pipeline-as-efficient-as-it-could-be
原文作者:Matthew Mayo
Image by Editor
# 流程的脆弱性
当代机器学习的“最先进”技术具有巨大的吸引力。研究团队和工程部门都痴迷于模型架构,从调整超参数到试验新颖的注意力机制,一切都是为了追逐最新的基准测试。然而,虽然构建一个稍微更精确的模型是一项崇高的追求,但许多团队却忽略了推动创新的一个更大杠杆:支持它的流程的效率。
流程效率是机器学习生产力的隐形引擎。它不仅仅是一种节省云费用的措施,尽管在那里的投资回报率确实非常可观。它的核心关乎迭代周期——即从一个假设到一个验证结果所经过的时间。
拥有一个缓慢、脆弱流程的团队实际上是被限制了速度。如果由于 I/O 瓶颈,您的训练运行需要 24 小时,那么您每周只能串行测试七个假设。如果您能将相同的流程优化到 2 小时内运行,您的发现速度将提高一个数量级。从长远来看,无论谁的架构最初更复杂,迭代更快的团队通常会获胜。
为了缩小迭代周期,您必须将流程视为一等工程产品。以下是需要审计的五个关键领域,以及可用来夺回团队时间的实用策略。
# 1. 解决数据输入瓶颈:饥饿的 GPU 问题
机器学习堆栈中最昂贵的组件通常是闲置的高端图形处理单元(GPU)。如果您的监控工具显示在主动训练期间 GPU 利用率徘徊在 20% - 30% 之间,那么您就没有计算问题;您有数据 I/O 问题。您的模型已准备好学习,但它正因数据样本不足而“挨饿”。
// 现实场景
考虑一个计算机视觉团队,他们正在使用存储在对象存储(如 Amazon S3)中的数百万张图像数据集来训练 ResNet 风格的模型。当数据存储为单个文件时,每个训练周期都会触发数百万次高延迟的网络请求。中央处理器(CPU)花费在网络开销和 JPEG 解码上的周期比花在向 GPU 喂送数据上的要多。在这种情况下增加更多的 GPU 实际上是适得其反的;瓶颈仍然是物理 I/O,而您只是为相同的吞吐量支付了更高的费用。
// 解决方案
- 预分片和打包:停止读取单个文件。对于高吞吐量训练,您应该将数据捆绑成更大、更连续的格式,如 Parquet、TFRecord 或 WebDataset。这使得顺序读取成为可能,顺序读取比跨数千个小文件的随机访问快得多。
- 并行化加载:现代框架(PyTorch、JAX、TensorFlow)提供支持多个工作进程的数据加载器。确保您能有效地使用它们。下一批次的数据应该在 GPU 完成当前梯度步骤之前就已经被预取、增强并等待在内存中。
- 上游过滤:如果您只在数据集的子集上进行训练(例如“过去 30 天的用户”),请使用分区查询在存储层过滤该数据,而不是加载整个数据集并在内存中进行过滤。
# 2. 支付预处理税
每次运行实验时,您是否都在重新运行完全相同的数据清理、分词或特征连接?如果是,您就在支付“预处理税”,这会随着每一次迭代而累加。
// 现实场景
一个用户流失预测团队每周运行数十次实验。他们的流程始于聚合原始点击流日志并将其与关系型人口统计表连接起来,这个过程需要,假设是四个小时。即使数据科学家只是在测试不同的学习率或略有不同的模型头,他们也会重新运行整个四个小时的预处理作业。这是被浪费的计算资源,更重要的是,是被浪费的人力时间。
// 解决方案
- 将特征与训练解耦:构建您的流程,使特征工程和模型训练成为独立阶段。特征流程的输出应该是一个干净的、不可变的工件。
- 工件版本控制和缓存:使用 DVC、MLflow 或简单的 S3 版本控制等工具来存储已处理的特征集。当开始新的运行时,计算输入数据和转换逻辑的哈希值。如果存在匹配的工件,则跳过预处理并直接加载缓存的数据。
- 特征存储:对于成熟的组织而言,特征存储可以充当中央存储库,昂贵的转换只需计算一次即可跨多个训练和推理任务重复使用。
# 3. 为问题正确调整计算规模
并非每个机器学习问题都需要一台 NVIDIA H100。过度配置是效率债务的常见形式,通常是由于“默认使用 GPU”的心态所驱动的。
// 现实场景
数据科学家经常启动重型 GPU 实例来训练梯度提升树(例如 XGBoost 或 LightGBM)处理中等规模的表格数据。除非特定实现针对 CUDA 进行了优化,否则 GPU 会空闲,而 CPU 则在努力跟上。相反,在单台机器上训练大型 Transformer 模型而不利用混合精度(FP16/BF16)会导致内存相关的崩溃,并且吞吐量远低于硬件的实际能力。
// 解决方案
- 将硬件与工作负载匹配:为深度学习工作负载(视觉、自然语言处理 (NLP)、大规模嵌入)保留 GPU。对于大多数表格和经典机器学习工作负载,高内存 CPU 实例更快且更具成本效益。
- 通过批处理最大化吞吐量:如果您正在使用 GPU,请将其饱和。增加批处理大小,直到接近该卡的内存限制。大型 GPU 上的小批量大小会导致时钟周期的大量浪费。
- 混合精度:始终利用支持的混合精度训练。它能减少内存占用并提高现代硬件上的吞吐量,而对最终准确率的影响可以忽略不计。
- 快速失败:实施提前停止。如果您的验证损失在第 10 个 epoch 就已停滞或爆炸,那么完成剩余的 90 个 epoch 没有任何意义。
# 4. 评估的严谨性与反馈速度的平衡
严谨性至关重要,但错误的严谨性会使开发瘫痪。如果您的评估循环过重,以至于占据了训练时间的大部分,那么您可能正在计算中间决策中不需要的指标。
// 现实场景
一个欺诈检测团队以其科学严谨性而自豪。在一次训练运行中,他们在每个 epoch 结束时都会触发一个完整的交叉验证套件。该套件会计算数百个概率阈值下的置信区间、精确率-召回率曲线下面积 (PR-AUC) 和 F1 分数。虽然训练周期本身需要 5 分钟,但评估却需要 20 分钟。反馈循环被指标生成所主导,而这些指标实际上没有人会在最终选择模型候选者之前进行审查。
// 解决方案
- 分层评估策略:为训练中验证实施“快速模式”。使用更小、具有统计学意义的保留集,并关注核心的代理指标(例如验证损失、简单准确率)。仅将昂贵、全谱的评估套件用于最终的模型候选者或定期的“检查点”审查。
- 分层抽样:您可能不需要整个验证集就能了解模型是否正在收敛。一个经过良好分层的样本通常能以更低的计算成本提供相同的方向性见解。
- 避免重复推理:确保您正在缓存预测结果。如果您需要在同一验证集上计算五种不同的指标,请只运行一次推理并将结果重用,而不是为每个指标重新运行前向传播。
# 5. 尽早解决推理约束
一个准确率为 99% 的模型,如果返回预测需要 800 毫秒,而在系统中仅有 200 毫秒的延迟预算,那么它就是一个负累。效率不仅仅是训练问题;它是部署要求。
// 现实场景
一个推荐引擎在一个研究笔记本中表现完美,点击率 (CTR) 提高了 10%。然而,一旦部署到应用程序编程接口 (API) 后面,延迟就会激增。团队意识到模型依赖于复杂的运行时特征计算,这些计算在批处理笔记本中微不足道,但在实时环境中却需要昂贵的数据库查找。该模型在技术上更优越,但在操作上却不可行。
// 解决方案
- 将推理作为约束条件:在开始训练之前,定义您的操作约束——延迟、内存占用和每秒查询次数 (QPS)。如果模型无法满足这些基准,无论其在测试集上的性能如何,它都不适合生产。
- 最小化训练-服务偏差:确保训练期间使用的预处理逻辑与服务环境中的逻辑完全相同。逻辑不匹配是生产机器学习中静默失败的主要来源。
- 优化和量化:利用 ONNX Runtime、TensorRT 或量化等工具,从生产硬件中挤出最大的性能。
- 批量推理:如果您的用例不需要严格的实时评分,请切换到异步批量推理。一次性为 10,000 个用户评分比处理 10,000 个单独的 API 请求效率高出数倍。
# 结论:效率是一种特性
优化您的流程不是“杂务工作”;它是高杠杆的工程实践。通过缩短迭代周期,您不仅节省了云成本,还增加了团队可以产生的总体智能量。
您的下一步很简单:从这个列表中挑选一个瓶颈,并在本周对其进行审计。衡量修复前后实现结果所需的时间。您可能会发现,一个快速的流程比一个花哨的架构更胜一筹,原因很简单:它让您比竞争对手学得更快。
Matthew Mayo (@mattmayo13) 拥有计算机科学硕士学位和数据挖掘研究生文凭。作为 KDnuggets 和 Statology 的执行编辑,以及 Machine Learning Mastery 的特约编辑,Matthew 致力于使复杂的数据科学概念易于理解。他的专业兴趣包括自然语言处理、语言模型、机器学习算法以及探索新兴人工智能。他致力于在数据科学界普及知识。Matthew 从 6 岁起就开始编程。
🚀 想要体验更好更全面的AI调用?
欢迎使用青云聚合API,约为官网价格的十分之一,支持300+全球最新模型,以及全球各种生图生视频模型,无需翻墙高速稳定,文档丰富,小白也可以简单操作。
评论区