最佳应用实践¶
TorchX 应用程序可以使用任何语言编写,也可以使用任何一组库来实现最大的灵活性。然而,我们确实有一套推荐的库和实践标准,作为用户开始时的起点,并确保内置组件和应用程序的一致性。
请参阅 组件最佳实践 以获取有关如何处理组件管理和AppDefs的信息。
数据传递和存储¶
我们推荐 fsspec. fsspec 允许可插拔文件系统,因此应用程序可以一次编写并在大多数基础设施上运行,只需更改输入和输出路径。
TorchX内置组件使用fsspec进行所有存储访问,以使其在使用不同的fsspec后端或添加新后端的情况下运行于新的环境中成为可能。
Pytorch Lightning内置支持fsspec,因此在其他地方使用fsspec可以无缝地将其集成到您的训练器中。
使用远程存储还可以使您的应用程序更容易通过诸如torch.distributed.elastic等库过渡到分布式支持。
训练循环¶
有很多方法来结构训练循环,这在很大程度上取决于你的模型类型和架构,这就是为什么我们没有提供一个标准的。
一些常见的选择是:
纯粹的 Pytorch
- Use a managed train loop
请参阅 训练 获取更多信息。
指标¶
对于记录指标和监控您的作业,我们建议使用独立的Tensorboard,因为它原生支持 Pytorch tensorboard集成 和 Pytorch Lightning日志记录。
由于 Tensorboard 可以将日志记录到远程存储,如 S3 或 GCS,因此在模型训练过程中可以查看其复杂信息。
请参阅 指标 以获取有关TorchX中指标处理的更多信息。
断点¶
周期性检查点允许你的应用程序从失败中恢复,并在某些情况下允许你重新启动训练器,使用不同的参数而不会丢失训练进度。
Pytorch Lightning 提供了一种标准化的方式来保存您的模型。
微调¶
为了支持像迁移学习、微调和从检查点恢复这样的功能,我们建议在你的应用程序中添加一个命令行参数,该参数将从检查点文件中恢复。
这将允许你从临时错误中恢复,继续在新数据上进行训练,或者以后调整学习率而不会丢失训练进度。
加载支持使得代码量减少,维护性更好,因为你可以有一个应用程序执行多种相似的任务。
可解释性¶
我们推荐使用 captum 来进行模型可解释性和分析模型结果。这可以在交互式 Jupyter 笔记本或组件中使用。
请参阅 解释 以获取更多信息。
模型包装¶
PyTorch社区尚未统一采用一个包格式。这里有几个选项以及在什么情况下可能需要使用它们。
Python + 保存的权重¶
这是最常见的模型打包格式。要使用它,你需要从Python文件加载你的模型定义,然后从.ckpt或.pt文件加载权重和状态字典。
这是Pytorch Lightning的 ModelCheckpoint 钩子的工作方式。
这是最常见的,但这也使得制作可重用的应用程序更加困难,因为你的训练应用程序需要包含模型定义代码。
TorchScript模型¶
TorchScript是一种创建可序列化和优化的Pytorch模型的方法,这些模型可以在不使用Python的情况下执行。这可以用于高效的推理或训练,而无需依赖Python的GIL。
这些模型文件是完全自描述的,但并非所有PyTorch模型都可以自动转换为TorchScript。
请参阅TorchScript文档。
PyTorch模型存档器 (.mar)¶
如果您想使用TorchServe进行推理,您需要将您的模型导出为这种格式。对于推理,通常会使用模型的量化版本,因此最好让您的训练器同时导出一个全精度模型用于微调以及一个量化 .mar 文件供TorchServe消费。
请参阅 模型存档器文档。
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(...)