【保存版】PyTorchでモデルをトレースする3つの方法:torch.export.FakeTensorを超えた手法も紹介
PyTorch の torch.export
関数は、Tensor 計算グラフを事前コンパイル (AOT) してトレースし、そのグラフを ExportedProgram
オブジェクトとしてカプセル化します。この ExportedProgram
は、シリアル化して保存したり、異なる入力で後から実行したりすることができます。
torch.export.FakeTensor の役割
torch.export
関数でトレースを行う際、torch.export.FakeTensor
を使用すると、計算を実際に行わずに、Tensor のサイズやデータ型などの情報を取得することができます。これは、特に大規模なモデルをトレースする場合に有効です。
FakeTensor
は、実際の Tensor と同様に動作しますが、実際にはデータを持っていません。これは、計算を実行せずに、Tensor の形状やデータ型などの情報を取得する必要がある場合に役立ちます。
torch.export.FakeTensor の使用方法
torch.export.FakeTensor
を使用するには、まず FakeTensorMode
オブジェクトを作成する必要があります。このオブジェクトは、トレース対象のコードを実行するコンテキストを設定します。
from torch._subclasses.fake_tensor import FakeTensorMode
fake_mode = FakeTensorMode()
次に、fake_mode
オブジェクトを使用して、実際の Tensor を FakeTensor
に変換します。
x = torch.randn(10, 20)
fake_x = fake_mode.from_real_tensor(x)
FakeTensor
を torch.export
関数に渡すことで、計算を実行せずに Tensor の形状やデータ型などの情報を取得することができます。
def my_function(x):
# 計算を実行する
@torch.export(my_function, fake_args=(fake_x,))
def my_exported_function(x):
# 計算を実行しない
torch.export.FakeTensor の利点
- モデルのシリアル化と保存を容易化
- 計算を実行せずに Tensor の形状やデータ型などの情報を取得
- 大規模なモデルのトレース時間を短縮
FakeTensor
を使用してトレースを行った場合、モデルをデバッグするのが難しくなる場合があります。FakeTensor
は実際の Tensor とは異なる動作をする場合があります。
import torch
from torch._subclasses.fake_tensor import FakeTensorMode
# モデル定義
class LinearRegression(torch.nn.Module):
def __init__(self, in_features, out_features):
super().__init__()
self.linear = torch.nn.Linear(in_features, out_features)
def forward(self, x):
return self.linear(x)
# モデルを作成
model = LinearRegression(2, 1)
# FakeTensorMode を作成
fake_mode = FakeTensorMode()
# 入力データを FakeTensor に変換
x = torch.randn(10, 2)
fake_x = fake_mode.from_real_tensor(x)
# モデルをトレースして ExportedProgram を取得
traced_model = torch.jit.trace(model, fake_x)
# ExportedProgram をシリアル化して保存
torch.jit.save(traced_model, "model.pt")
# モデルをロードして実行
loaded_model = torch.jit.load("model.pt")
y = loaded_model(x)
print(y)
このコードでは、まず LinearRegression
クラスというシンプルな線形回帰モデルを定義します。次に、FakeTensorMode
オブジェクトを作成して、トレース対象のコードを実行するコンテキストを設定します。
その後、入力データ (x
) を FakeTensor
に変換し、torch.jit.trace
関数を使用してモデルをトレースします。トレースされたモデルは ExportedProgram
オブジェクトとしてカプセル化され、torch.jit.save
関数を使用してシリアル化して保存されます。
最後に、シリアル化されたモデルを torch.jit.load
関数を使用してロードし、実際の入力データ (x
) で実行します。
torch.jit.save
関数を使用して保存されたモデルは、PyTorch でのみ実行できます。- モデルをトレースする前に、モデルのトレーニングを完了しておく必要があります。
- このコードは、PyTorch 1.10 以降で使用できます。
ランダムな入力を使用する
最も簡単な代替方法は、トレース対象の関数にランダムな入力を使用することです。これは、torch.randn
や torch.rand
などの関数を使用して行うことができます。
import torch
def my_function(x):
# 計算を実行する
@torch.export(my_function, args=(torch.randn(10, 20),))
def my_exported_function(x):
# 計算を実行しない
この方法は、単純ですが、入力データの分布が実際のデータと異なる場合、トレースされたモデルの精度が低下する可能性があります。
動的な形状を使用する
torch.export.FakeTensor
の代わりに、動的な形状を使用することができます。動的な形状は、Tensor の形状をシンボリックな表現で表すことができます。
import torch
from torch.jit.annotations import shape
def my_function(x: torch.Tensor) -> torch.Tensor:
# 計算を実行する
@torch.export(my_function, shape_dict={"x": [shape(None, 20)]})
def my_exported_function(x):
# 計算を実行しない
この方法は、torch.export.FakeTensor
よりも柔軟性が高く、入力データの分布が実際のデータと異なる場合でも、トレースされたモデルの精度を維持することができます。
TorchScript のトレースツールを使用する
TorchScript には、torch.jit.trace_module
や torch.jit.trace
などのトレースツールが用意されています。これらのツールは、torch.export.FakeTensor
を使用せずにモデルをトレースすることができます。
import torch
import torch.jit
model = LinearRegression(2, 1)
traced_model = torch.jit.trace(model, torch.randn(10, 2))
この方法は、最も汎用性が高く、複雑なモデルをトレースするのに適しています。
ONNX を使用する
ONNX は、機械学習モデルを表現するためのオープンフォーマットです。PyTorch には、ONNX 形式にモデルをエクスポートするための torch.onnx.export
関数が用意されています。
import torch
import torch.onnx
model = LinearRegression(2, 1)
torch.onnx.export(model, torch.randn(10, 2), "model.onnx")
この方法は、PyTorch 以外のフレームワークでモデルを実行したい場合に役立ちます。
torch.export.FakeTensor
は、PyTorch の torch.export
関数でトレースを行う際に役立つツールですが、いくつかの代替方法があります。
- ONNX を使用する
- TorchScript のトレースツールを使用する
- 動的な形状を使用する
- ランダムな入力を使用する