【发布时间】:2021-06-17 21:27:23
【问题描述】:
torch.nn.functional.grid_sample(来源here,点击文档查看文档)目前是CoreML(及其转换实用程序库:coremltools)不支持的操作。
我正在寻找一种将下面显示的层从 PyTorch 的 torchscript(文档 here)导出到 CoreML(使用通过 Swift 创建的自定义 op 或通过有效的 PyTorch 重写 grid_sample)的方法.
有关帮助您入门的详细信息和提示,请参阅提示部分
最小可验证示例
import coremltools as ct
import torch
class GridSample(torch.nn.Module):
def forward(self, inputs, grid):
# Rest could be the default behaviour, e.g. bilinear
return torch.nn.functional.grid_sample(inputs, grid, align_corners=True)
# Image could also have more in_channels, different dimension etc.,
# for example (2, 32, 64, 64)
image = torch.randn(2, 3, 32, 32) # (batch, in_channels, width, height)
grid = torch.randint(low=-1, high=2, size=(2, 64, 64, 2)).float()
layer = GridSample()
# You could use `torch.jit.script` if preferable
scripted = torch.jit.trace(layer, (image, grid))
# Sanity check
print(scripted(image, grid).shape)
# Error during conversion
coreml_layer = ct.converters.convert(
scripted,
source="pytorch",
inputs=[
ct.TensorType(name="image", shape=image.shape),
ct.TensorType(name="grid", shape=grid.shape),
],
)
这会引发以下错误:
Traceback (most recent call last):
File "/home/REDACTED/Downloads/sample.py", line 23, in <module>
coreml_layer = ct.converters.convert(
File "/home/REDACTED/.conda/envs/REDACTED/lib/python3.9/site-packages/coremltools/converters/_converters_entry.py", line 175, in convert
mlmodel = mil_convert(
File "/home/REDACTED/.conda/envs/REDACTED/lib/python3.9/site-packages/coremltools/converters/mil/converter.py", line 128, in mil_convert
proto = mil_convert_to_proto(, convert_from, convert_to,
File "/home/REDACTED/.conda/envs/REDACTED/lib/python3.9/site-packages/coremltools/converters/mil/converter.py", line 171, in mil_convert_to_proto
prog = frontend_converter(, **kwargs)
File "/home/REDACTED/.conda/envs/REDACTED/lib/python3.9/site-packages/coremltools/converters/mil/converter.py", line 85, in __call__
return load(*args, **kwargs)
File "/home/REDACTED/.conda/envs/REDACTED/lib/python3.9/site-packages/coremltools/converters/mil/frontend/torch/load.py", line 81, in load
raise e
File "/home/REDACTED/.conda/envs/REDACTED/lib/python3.9/site-packages/coremltools/converters/mil/frontend/torch/load.py", line 73, in load
prog = converter.convert()
File "/home/REDACTED/.conda/envs/REDACTED/lib/python3.9/site-packages/coremltools/converters/mil/frontend/torch/converter.py", line 227, in convert
convert_nodes(self.context, self.graph)
File "/home/REDACTED/.conda/envs/REDACTED/lib/python3.9/site-packages/coremltools/converters/mil/frontend/torch/ops.py", line 54, in convert_nodes
raise RuntimeError(
RuntimeError: PyTorch convert function for op 'grid_sampler' not implemented.
依赖关系
Python (conda):
coremltools==4.1torch==1.8.0
您还可以使用 nightly/master 构建(至少在写作当天:2021-03-20)
提示
这些被分为我目前看到的两种可能的解决方案:
仅限 PyTorch
从头开始重写torch.nn.functional.grid_sample。
- 这将只需要在张量上坚持 PyTorch 操作,因为循环(例如三重嵌套)会挂起转换器并且效率太低
-
您不能在
list或相关类型上使用__getitem__- 似乎可以与torch.Tensor一起使用,但有问题,因此如果您收到RuntimeError: PyTorch convert function for op '__getitem__' not implemented,请记住这一点
优点:
- 无需两种语言并坚持单一技术
缺点:
- 受限于循环,需要坚持矢量化操作(大部分/所有时间)
Swift 和 CoreML
注册自定义层负责运行grid_sample。仅 CPU 的实现会很好(尽管使用 Apple 的 Metal 来加速 GPU 会很棒)。
由于我不熟悉 Swift,所以我收集了一些可能对您有所帮助的资源:
- https://coremltools.readme.io/docs/custom-operators - 起点,仅限 Python,非常简单,只需注册层进行转换
- https://developer.apple.com/documentation/coreml/mlcustomlayer - 必须在 Swift 中编码的层的 API
- https://developer.apple.com/documentation/coreml/core_ml_api/creating_a_custom_layer - 更多关于上述(但不多)
- https://machinethink.net/blog/coreml-custom-layers/ - 带有示例和向设备(GPU、CPU)调度层的博客文章。需要 Swift(CPU 版本)、Metal(GPU 实现)。最终的 Metal 实现可能基于 PyTorch 的 CUDA impl,CPU 和 Swift 也可能相关。 3 岁了,所以请注意,swish 激活层似乎是一个很好的起点(同一作者的其他帖子也对 CoreML 本身有所了解)。
- https://github.com/hollance/CoreML-Custom-Layers - 上面的仓库
优点:
- 可以使用循环并更好地控制算法
- 可能会更容易,因为我们不限于 CoreML 当前可以读取的操作
缺点:
- 两种语言
- 文档稀少
【问题讨论】:
-
你好,
grid_sample转换有进展吗?
标签: python swift pytorch coreml coremltools