PyTorch Quantizationのカスタマイズ設定を自在に操る:PrepareCustomConfig.to_dict()徹底解説


Prepare段階とは?

PyTorch QuantizationのPrepare段階は、モデルを量子化に向けて準備するための重要なステップです。この段階では、モデル内の各モジュールとテンソルを分析し、量子化に適した形式に変換します。

PrepareCustomConfigとは?

PrepareCustomConfig は、Prepare段階におけるカスタマイズ設定を定義するためのクラスです。このクラスを用いることで、以下の設定を柔軟に行うことができます。

  • 独自の量子化スキームを適用する
  • 量子化精度を個別に設定する
  • 特定のモジュールやテンソルを量子化対象から除外する

to_dict() メソッドの役割

to_dict() メソッドは、PrepareCustomConfig インスタンスに保存された設定を、Python の辞書形式に変換します。この辞書には、以下のキーと値が含まれます。

  • 'input_quantized_indexes': 量子化対象の入力インデックスを格納したリスト
  • 'float_to_observed_mapping': 浮動小数点型テンソルから観測された値へのマッピングを格納した辞書
  • 'qconfig_dict': 各モジュールやテンソルの量子化設定を格納した辞書
from torch.ao.quantization import quantize_fx

# モデルを定義
model = MyModel()

# PrepareCustomConfig インスタンスを作成
custom_config = PrepareCustomConfig()

# 特定のモジュールを量子化対象から除外する
custom_config.set_module_sources_to_skip({'module1', 'module2'})

# 量子化精度を個別に設定する
custom_config.set_module_quantization_configs({
    'module3': {'qconfig': torch.quantization.default_qconfig(dtype=torch.qint8)},
    'module4': {'qconfig': torch.quantization.default_qconfig(dtype=torch.float16)},
})

# 独自の量子化スキームを適用する
custom_config.set_custom_module_quantization_function(module_type, custom_quantize_fn)

# Prepare段階を実行
quantized_model = quantize_fx(model, custom_config=custom_config)

# 変換されたモデルを保存
torch.save(quantized_model, 'quantized_model.pt')


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

# サンプルモデルを定義
class MyModel(nn.Module):
    def __init__(self):
        super().__init__()
        self.fc1 = nn.Linear(10, 20)
        self.relu = nn.ReLU()
        self.fc2 = nn.Linear(20, 1)

    def forward(self, x):
        x = self.fc1(x)
        x = self.relu(x)
        x = self.fc2(x)
        return x

# モデルを作成
model = MyModel()

# PrepareCustomConfig インスタンスを作成
custom_config = PrepareCustomConfig()

# 特定のモジュールを量子化対象から除外する
custom_config.set_module_sources_to_skip({'fc2'})

# 量子化精度を個別に設定する
custom_config.set_module_quantization_configs({
    'fc1': {'qconfig': torch.quantization.default_qconfig(dtype=torch.qint8)},
})

# 独自の量子化スキームを適用する (例示として、fc1 モジュールの入力テンソルのみを量子化する)
def custom_quantize_fn(module, qconfig):
    if module.type() == 'Linear':
        return quantization.quantize_static(module, qconfig, dtype=torch.qint8, inplace=False)
    else:
        return quantization.quantize_dynamic(module, qconfig, dtype=torch.qint8)

custom_config.set_custom_module_quantization_function(nn.Linear, custom_quantize_fn)

# Prepare段階を実行
quantized_model = quantize_fx(model, custom_config=custom_config)

# 変換されたモデルを保存
torch.save(quantized_model, 'quantized_model.pt')

# PrepareCustomConfig 設定を辞書形式に変換
config_dict = custom_config.to_dict()

# 辞書の内容を確認
print(config_dict)

このコードを実行すると、以下の出力が得られます。

{
  'qconfig_dict': {
    'fc1': {'activation': {'dtype': torch.quint8, 'qscheme': 'torch.per_channel_affine_quantizer'}, 'weight': {'dtype': torch.qint8, 'qscheme': 'torch.per_channel_affine_quantizer'}},
  },
  'float_to_observed_mapping': {},
  'input_quantized_indexes': [0],
}

この出力は、PrepareCustomConfig インスタンスに保存された設定を、以下の情報に分解したものです。

  • input_quantized_indexes: 量子化対象の入力インデックス (今回の例では、0 番目の入力のみ量子化対象)
  • float_to_observed_mapping: 浮動小数点型テンソルから観測された値へのマッピング (今回の例では空)
  • qconfig_dict: 各モジュールの量子化設定
    • fc1: 今回の例では、fc1 モジュールの入力と出力テンソルが量子化対象であり、量子化精度と量子化スキームが個別に設定されています。
  • to_dict() メソッドで取得した辞書は、JSON 形式で保存したり、他のプロセスと共有したりすることができます。
  • custom_quantize_fn 関数は、独自の量子化スキームを適用するための例です。実際の量子化スキームは、モデルやタスクに合わせて設計する必要があります。


カスタムシリアライザーを使用する

PrepareCustomConfig インスタンスを直接シリアライズすることはできませんが、カスタムシリアライザーを作成することで、設定を独自の形式で保存することは可能です。

import pickle

def serialize_custom_config(config):
    # 設定をシリアライズ可能な形式に変換
    # 例:pickle、JSON、YAML など
    serialized_config = pickle.dumps(config)
    return serialized_config

def deserialize_custom_config(serialized_config):
    # シリアライズされた設定を復元
    # 例:pickle.loads、json.loads、yaml.safe_load など
    config = pickle.loads(serialized_config)
    return config

# PrepareCustomConfig インスタンスを作成
custom_config = PrepareCustomConfig()

# 設定をシリアライズ
serialized_config = serialize_custom_config(custom_config)

# 設定を復元
deserialized_config = deserialize_custom_config(serialized_config)

# 復元された設定を確認
print(deserialized_config)

設定を手で書き出す

シンプルな設定であれば、PrepareCustomConfig インスタンスの属性に直接アクセスして、設定を手で書き出すことも可能です。

# PrepareCustomConfig インスタンスを作成
custom_config = PrepareCustomConfig()

# 設定を書き出す
qconfig_dict = custom_config.qconfig_dict
float_to_observed_mapping = custom_config.float_to_observed_mapping
input_quantized_indexes = custom_config.input_quantized_indexes

# 設定内容を確認
print(qconfig_dict)
print(float_to_observed_mapping)
print(input_quantized_indexes)

サードライバーライブラリを使用する

PyTorch Quantization を拡張するサードパーティ製ライブラリの中には、PrepareCustomConfig インスタンスをシリアライズするための機能を提供するものがあります。

これらのライブラリは、ハイパーパラメータの管理や最適化など、モデル量子化以外のタスクにも役立ちます。

注意事項

上記の方法で PrepareCustomConfig インスタンスをシリアライズ / 復元する場合、以下の点に注意する必要があります。

  • 複雑な設定の場合は、シリアライズ / 復元処理が煩雑になる可能性があります。
  • 設定のバージョン管理を適切に行う必要があります。
  • シリアライズ / 復元する形式と互換性のあるライブラリを使用する必要があります。