应用最佳实践¶
TorchX 应用程序可以使用任何语言以及任何库集来编写,以实现最大的灵活性。然而,我们确实有一套标准的推荐库和实践,为用户提供一个起点,并在内置组件和应用程序之间提供一致性。
请参阅组件最佳实践了解如何处理组件管理和AppDefs。
数据传递与存储¶
我们推荐 fsspec。fsspec 允许可插拔的文件系统,因此应用程序只需编写一次,就可以通过更改输入和输出路径在大多数基础设施上运行。
TorchX内置组件使用fsspec进行所有存储访问,以便通过使用不同的fsspec后端或添加新的后端来在新环境中运行。
Pytorch Lightning 默认支持 fsspec,因此在其他地方使用 fsspec 可以无缝集成到您的训练器中。
使用远程存储还可以更轻松地将您的应用程序过渡到通过诸如torch.distributed.elastic等库运行分布式支持。
训练循环¶
有很多方法可以构建训练循环,这在很大程度上取决于你的模型类型和架构,这就是为什么我们不提供一个现成的解决方案。
一些常见的选择是:
纯Pytorch
- Use a managed train loop
查看训练获取更多信息。
指标¶
为了记录指标和监控您的任务,我们推荐使用独立的Tensorboard,因为它原生支持 Pytorch tensorboard integrations 和 Pytorch Lightning logging。
由于Tensorboard可以记录到远程存储如s3或gcs,您可以在模型训练时查看有关模型的复杂信息。
有关TorchX中指标处理的更多信息,请参见指标。
检查点¶
定期检查点允许您的应用程序从故障中恢复,并且在某些情况下允许您在不丢失训练进度的情况下使用不同的参数重新启动训练器。
Pytorch Lighting 提供了一种标准化的方式来保存你的模型检查点。
微调¶
为了支持诸如迁移学习、微调和从检查点恢复等功能,我们建议在您的应用程序中添加一个命令行参数,以便从检查点文件恢复。
这将允许您从暂时性错误中恢复,继续在新数据上进行训练,或者稍后调整学习率而不会丢失训练进度。
拥有负载支持可以减少代码量并提高可维护性,因为你可以让一个应用程序执行多个类似的任务。
可解释性¶
我们推荐使用captum进行模型可解释性和分析模型结果。这可以从Jupyter笔记本或组件中交互式使用。
查看 解释 获取更多信息。
模型打包¶
PyTorch社区尚未标准化一种包格式。以下是几种选项以及您可能需要使用它们的情况。
Python + 保存的权重¶
这是打包模型的最常见格式。使用时,您将从python文件中加载模型定义,然后从.ckpt或.pt文件中加载权重和状态字典。
这是Pytorch Lightning的 ModelCheckpoint钩子的工作原理。
这是最常见的情况,但会使创建可重用的应用程序变得更加困难,因为您的训练应用程序需要包含模型定义代码。
TorchScript 模型¶
TorchScript 是一种创建可序列化和优化的 Pytorch 模型的方法,这些模型可以在没有 Python 的情况下执行。这可以用于推理或训练,以高性能的方式运行,而不依赖于 Python 的 GIL。
这些模型文件是完全自描述的,但并非所有的PyTorch模型都可以自动转换为TorchScript。
请参阅TorchScript文档。
TorchServe 模型归档器 (.mar)¶
如果你想使用TorchServe进行推理,你需要将你的模型导出为这种格式。对于推理,通常使用模型的量化版本,因此最好让你的训练器导出一个用于微调的全精度模型,以及一个供TorchServe使用的量化.mar文件。
查看 模型归档文档。
torch.package¶
这是自 PyTorch 1.9.0 以来的新格式,可用于保存和加载模型定义及其权重,因此您不需要单独管理模型定义。
请参阅torch.package文档。
它相当新,尚未得到广泛的采用或支持。
服务 / 推理¶
对于服务和推理,我们推荐使用 TorchServe 来处理常见的使用场景。 我们提供了一个组件,允许您通过管理API将您的模型上传到TorchServe。
查看服务内置组件以获取更多信息。
出于更复杂的服务和性能原因,您可能需要编写自己的自定义推理逻辑。Torchscript 和 torch::deploy 是一些标准工具,您可以使用它们来构建自己的推理服务器。
测试¶
由于TorchX应用程序通常是标准的Python代码,因此您可以像对待任何其他Python代码一样为它们编写单元测试。
import unittest
from your.custom.app import main
class CustomAppTest(unittest.TestCase):
def test_main(self) -> None:
main(["--src", "src", "--dst", "dst"])
self.assertTrue(...)