PyTorchで異なる形状の入力を受け入れるモデルを作る:`torch.export.dynamic_dim()` とその代替方法


torch.export.dynamic_dim() は、PyTorch の「Traced Graph Export」機能で使用される関数であり、モデルのトレースされたグラフをエクスポートする際に、入力テンソルの特定の次元を動的に扱えるようにします。これは、モデルが異なる形状の入力を受け入れられるようにする場合に役立ちます。

機能

torch.export.dynamic_dim() は、_Constraint オブジェクトを作成します。このオブジェクトは、テンソル t の次元インデックスの動的な特性を記述します。

使用方法

torch.export.dynamic_dim() を使用するには、以下の手順に従います。

  1. エクスポートする関数に @torch.jit.trace デコレータを適用します。
  2. 関数内で、torch.export.dynamic_dim() を使用して、動的な次元である必要があるテンソルの次元を指定します。
  3. torch.jit.save を使用して、トレースされたグラフをエクスポートします。

以下の例は、torch.export.dynamic_dim() を使用して、1 つまたは 2 つの整数を引数として受け取り、それらを足す関数をエクスポートする方法を示しています。

import torch

@torch.jit.trace
def add_numbers(x: torch.Tensor, y: torch.Tensor):
    # 指定された次元が動的であることを示します
    torch.export.dynamic_dim(x, 0)

    return x + y

# モデルをエクスポートします
torch.jit.save(add_numbers, "add_numbers.pt")

このコードを実行すると、add_numbers.pt という名前のファイルにトレースされたグラフがエクスポートされます。このモデルは、1 つまたは 2 つの整数を引数として受け取り、それらを足すことができます。

注意事項

torch.export.dynamic_dim() は、PyTorch 1.10 以降でのみ使用できます。



例 1: 1 つまたは 2 つの整数を足す関数

この例では、1 つまたは 2 つの整数を引数として受け取り、それらを足す関数をエクスポートします。

import torch

@torch.jit.trace
def add_numbers(x: torch.Tensor, y: torch.Tensor):
    # 指定された次元が動的であることを示します
    torch.export.dynamic_dim(x, 0)

    return x + y

# モデルをエクスポートします
torch.jit.save(add_numbers, "add_numbers.pt")

例 2: バッチサイズが動的な畳み込み層

この例では、バッチサイズが動的な畳み込み層を実装する方法を示します。

import torch
import torch.nn as nn

class ConvLayer(nn.Module):
    def __init__(self, in_channels, out_channels, kernel_size):
        super().__init__()
        self.conv = nn.Conv2d(in_channels, out_channels, kernel_size)

    @torch.jit.trace
    def forward(self, x: torch.Tensor):
        # バッチ次元が動的であることを示します
        torch.export.dynamic_dim(x, 0)

        return self.conv(x)

# モデルを構築します
model = ConvLayer(3, 32, 3)

# モデルをエクスポートします
torch.jit.save(model, "conv_layer.pt")

説明

  • 例 2 では、ConvLayer モジュールはバッチサイズが異なる入力を受け取ることができます。
  • 例 1 では、add_numbers 関数は 1 つまたは 2 つの整数を引数として受け取ることができます。
  • これにより、モデルは異なる形状の入力を受け入れられるようになります。
  • 上記の例では、torch.export.dynamic_dim() 関数を使用して、モデルの入力テンソルの特定の次元が動的であることを示しています。
  • モデルを異なる形状の入力に汎用化する場合には、モデルの動作とパフォーマンスに注意する必要があります。
  • torch.export.dynamic_dim() は、PyTorch 1.10 以降でのみ使用できます。


しかし、torch.export.dynamic_dim() にはいくつかの制限があります。

  • モデルの動作とパフォーマンスに注意する必要があります。
  • PyTorch 1.10 以降でのみ使用できます。

これらの制限を回避するために、torch.export.dynamic_dim() の代替方法をいくつか検討することができます。

torch.jit.annotate() を使用する

torch.jit.annotate() は、トレースされたグラフに注釈を追加するために使用できます。この機能を使用して、入力テンソルの形状に関する情報を注釈として追加することができます。

import torch

@torch.jit.trace
def add_numbers(x: torch.Tensor, y: torch.Tensor):
    # 入力テンソルの形状に関する情報を注釈として追加します
    torch.jit.annotate(x, type_hint=torch.Tensor[(-1, )])

    return x + y

# モデルをエクスポートします
torch.jit.save(add_numbers, "add_numbers.pt")

torch.nn.Module を使用する

torch.nn.Module を使用して、動的な形状の入力を処理できるカスタムモジュールを作成することができます。

import torch
import torch.nn as nn

class AddNumbers(nn.Module):
    def __init__(self):
        super().__init__()

    def forward(self, x: torch.Tensor, y: torch.Tensor):
        return x + y

# モデルを構築します
model = AddNumbers()

# モデルをエクスポートします
torch.jit.save(model, "add_numbers.pt")

ONNX 形式でエクスポートする

ONNX は、機械学習モデルを表現するためのオープンフォーマットです。PyTorch モデルを ONNX 形式でエクスポートすると、ONNX ランタイムを使用してさまざまなプラットフォームで実行することができます。

import torch
import torchvision

model = torchvision.models.resnet18()

# モデルを ONNX 形式でエクスポートします
torch.onnx.export(model, torch.randn(1, 3, 224, 224), "resnet18.onnx")

TensorFlow に変換する

TensorFlow は、もう 1 つの一般的な機械学習フレームワークです。PyTorch モデルを TensorFlow 形式に変換すると、TensorFlow ランタイムを使用して実行することができます。

import torch
import tensorflow as tf

model = torchvision.models.resnet18()

# モデルを TensorFlow 形式に変換します
tf.saved_model.save(model, "resnet18")

torch.export.dynamic_dim() は、モデルを異なる形状の入力に汎用化するための強力なツールですが、いくつかの制限があります。これらの制限を回避するために、torch.jit.annotate(), torch.nn.Module, ONNX 形式でのエクスポート、TensorFlow への変換などの代替方法を検討することができます。