应用最佳实践¶
TorchX 应用可以使用任何语言以及任何库集编写,以实现最大灵活性。但是,我们确实有一套标准的推荐库和实践,作为用户的起点,并为内置组件和应用程序提供一致性。
有关如何处理组件管理和 AppDefs 的信息,请参阅 组件最佳实践。
数据传递和存储¶
我们推荐 fsspec。fsspec 允许可插拔文件系统,因此应用可以编写一次,并在大多数基础设施上运行,只需更改输入和输出路径即可。
TorchX 内置组件使用 fsspec 进行所有存储访问,以便可以通过使用不同的 fsspec 后端或添加新的后端在新的环境中运行。
Pytorch Lightning 原生支持 fsspec,因此在其他地方使用 fsspec 使得它与您的训练器无缝集成。
使用远程存储还使将您的应用程序转换为使用 torch.distributed.elastic 等库运行的分布式支持变得更加容易。
训练循环¶
有许多方法可以构建训练循环,这很大程度上取决于您的模型类型和架构,因此我们没有提供开箱即用的循环。
一些常见的选择是
纯 Pytorch
- 使用托管的训练循环
有关更多信息,请参阅 训练。
指标¶
为了记录指标和监控您的作业,我们建议使用独立的 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 文档。
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(...)