PyTorch Quantization:`torch.ao.quantization.fx.custom_config.ConvertCustomConfig.set_preserved_attributes()`の徹底解説


torch.ao.quantization.fx.custom_config.ConvertCustomConfig.set_preserved_attributes() は、PyTorch Quantizationにおいて、カスタムモジュールの属性を量子化変換時に保持するための設定方法を定義します。

役割

量子化変換では、モデル内のモジュールを量子化対応のものに置き換えます。この際、一部の属性は量子化の影響を受けずに保持する必要があります。set_preserved_attributes() は、このような属性を個別に指定するためのメソッドです。

使用方法

このメソッドは、ConvertCustomConfig オブジェクトに対して呼び出し、以下の引数を渡します。

  • module_type: 対象となるカスタムモジュールの型
  • preserved_attributes: 保持する属性名のリスト

from torch.ao.quantization import fx

def my_custom_module(input):
    # カスタム処理を行う
    return output

ConvertCustomConfig().set_preserved_attributes(
    preserved_attributes=["weight", "bias"],
    module_type=my_custom_module
)

上記の例では、my_custom_module 型のカスタムモジュールの weight 属性と bias 属性を量子化変換時に保持するように設定しています。

注意点

  • 保持する属性は、カスタムモジュールの定義に記載されている属性名と一致する必要があります。
  • このメソッドは、静的量子化でのみ使用できます。
from torch.ao.quantization import fx

qconfig = {
    'my_custom_module': {
        'weight': {'dtype': torch.qint8},
        'activation': {'dtype': torch.quint8}
    }
}

fx.convert_fx(model, qconfig=qconfig)

上記の例では、my_custom_module 型のカスタムモジュールの weight 属性を 8 ビット整数の量子化データ型 torch.qint8 に、activation 属性を 8 ビット符号付き整数の量子化データ型 torch.quint8 に変換するように設定しています。



import torch
import torch.nn as nn
from torch.ao.quantization import fx

# カスタムモジュールを定義
class MyCustomModule(nn.Module):
    def __init__(self):
        super().__init__()
        self.weight = nn.Parameter(torch.randn(10, 20))
        self.bias = nn.Parameter(torch.randn(20))

    def forward(self, input):
        # カスタム処理を行う
        output = torch.matmul(input, self.weight) + self.bias
        return output

# 静的量子化を行う
model = fx.convert_fx(MyCustomModule(), qconfig=None)

# カスタムモジュールの属性を保持するように設定
ConvertCustomConfig().set_preserved_attributes(
    preserved_attributes=["weight", "bias"],
    module_type=MyCustomModule
)

# モデルを保存する
torch.save(model, "my_model.pth")

このコードでは、MyCustomModule というカスタムモジュールを定義し、量子化変換時に weight 属性と bias 属性を保持するように設定しています。

QConfig オブジェクトを用いて属性を保持する

import torch
import torch.nn as nn
from torch.ao.quantization import fx

# カスタムモジュールを定義
class MyCustomModule(nn.Module):
    def __init__(self):
        super().__init__()
        self.weight = nn.Parameter(torch.randn(10, 20))
        self.bias = nn.Parameter(torch.randn(20))

    def forward(self, input):
        # カスタム処理を行う
        output = torch.matmul(input, self.weight) + self.bias
        return output

# QConfig オブジェクトを作成
qconfig = {
    'my_custom_module': {
        'weight': {'dtype': torch.qint8},
        'activation': {'dtype': torch.quint8},
        'preserved_attributes': ['weight', 'bias']  # 属性を保持するように設定
    }
}

# 静的量子化を行う
model = fx.convert_fx(MyCustomModule(), qconfig=qconfig)

# モデルを保存する
torch.save(model, "my_model.pth")

このコードでは、QConfig オブジェクトを用いて、カスタムモジュールの属性を保持するように設定しています。preserved_attributes キーに属性名をリストとして渡すことで、量子化変換時に属性が保持されます。

カスタムモジュールと QConfig オブジェクトを組み合わせる

import torch
import torch.nn as nn
from torch.ao.quantization import fx

# カスタムモジュールを定義
class MyCustomModule(nn.Module):
    def __init__(self):
        super().__init__()
        self.weight = nn.Parameter(torch.randn(10, 20))
        self.bias = nn.Parameter(torch.randn(20))

    def forward(self, input):
        # カスタム処理を行う
        output = torch.matmul(input, self.weight) + self.bias
        return output

# QConfig オブジェクトを作成
qconfig = {
    'my_custom_module': {
        'weight': {'dtype': torch.qint8},
        'activation': {'dtype': torch.quint8}
    }
}

# カスタムモジュールの属性を保持するように設定
ConvertCustomConfig().set_preserved_attributes(
    preserved_attributes=["weight", "bias"],
    module_type=MyCustomModule
)

# 静的量子化を行う
model = fx.convert_fx(MyCustomModule(), qconfig=qconfig)

# モデルを保存する
torch.save(model, "my_model.pth")

このコードでは、カスタムモジュールの属性を保持するために ConvertCustomConfigQConfig オブジェクトを組み合わせて使用しています。QConfig オブジェクトで量子化設定を行い、ConvertCustomConfig で属性を保持するモジュールを個別に指定することで、より柔軟な設定が可能になります。

  • 詳細については、PyTorch Quantization のドキュメントを参照してください。
  • これらの例はあくまで基本的な使用方法であり、実際のユースケースに合わせて調整する必要があります。


QConfig オブジェクト

import torch
from torch.ao.quantization import fx

qconfig = {
  "my_custom_module": {
    "weight": {"dtype": torch.qint8},
    "activation": {"dtype": torch.quint8},
    "preserved_attributes": ["weight", "bias"],  # 属性を保持するように設定
  }
}

# 静的量子化を行う
model = fx.convert_fx(my_custom_module, qconfig=qconfig)

この方法では、preserved_attributes キーに保持したい属性名をリストとして渡すことで、量子化変換時に属性が保持されます。コードが簡潔になり、可読性も向上します。

prepare_custom_module 関数

カスタムモジュールに対して量子化を適用する前に、prepare_custom_module 関数を利用して、属性を明示的にコピーする方法もあります。

import torch

def prepare_custom_module(model):
  # カスタムモジュールの属性をコピーして保持する処理
  custom_module = model.my_custom_module
  custom_module.preserved_weight = custom_module.weight.detach()
  custom_module.preserved_bias = custom_module.bias.detach()
  # 以降の処理

  return model

model = fx.prepare(MyCustomModule(), prepare_custom_module)
# ... (量子化処理)

この方法では、prepare_custom_module 関数内で、コピーしたい属性を明示的にコピーして、新しい属性名で保持します。ただし、コードが冗長になりやすく、メンテナンス性が低下する可能性があります。

トレースの修正

高度なテクニックですが、量子化前のトレース (fx.graph) を修正して、属性を保持させる方法もあります。ただし、この方法は複雑でエラーが発生しやすいため、推奨されません。