画像処理のニューラルネットワークを軽量化!PyTorch QuantizationでConvBn3dモジュールを使いこなす


ConvBn3dモジュールは、3D空間における畳み込み演算とバッチ正規化を効率的に実行するために設計されています。具体的には、以下の操作を行います。

  • バッチ正規化
    出力特徴マップを正規化し、各特徴マップのスケールとシフトを調整します。
  • 畳み込み演算
    入力特徴マップとカーネルを用いて、出力特徴マップを生成します。

このモジュールは、3D画像処理や動画処理などにおいて、幅広く活用されています。

量子化対応ConvBn3dモジュールの実現

torch.ao.nn.intrinsic.qat.ConvBn3dモジュールは、ConvBn3dモジュールを量子化に対応させるために、以下の機能を備えています。

  • 量子の推論モード
    推論時には、実際の量子化操作を実行し、計算効率を向上させます。
  • FakeQuantizeモジュール
    重量と活性化関数の出力に擬似量子化モジュールを挿入し、量子のスケールとゼロポイントを推定します。

これらの機能により、torch.ao.nn.intrinsic.qat.ConvBn3dモジュールは、精度を維持しながらモデルの軽量化を実現します。

import torch
import torch.nn as nn
import torch.ao.nn.intrinsic.qat as qnn

# 畳み込み層とバッチ正規化層を定義
conv = nn.Conv3d(in_channels=16, out_channels=32, kernel_size=3, padding=1)
bn = nn.BatchNorm3d(32)

# 量子化対応`ConvBn3d`モジュールを作成
qat_conv_bn3d = qnn.ConvBn3d(conv, bn)

# モデルを構築
model = nn.Sequential(
    qat_conv_bn3d,
    nn.ReLU(),
    # ...
)

# 量子化を行う
quantizer = torch.quantization.quantize.QuantStub(model)
quantizer.quantize()

# 量子の推論モードでモデルを実行
model.eval()
with torch.quantization.quantize.quantized_jit_script_version(model):
    # 推論処理
    output = model(input)

この例では、ConvBn3dモジュールの量子化対応バージョンであるtorch.ao.nn.intrinsic.qat.ConvBn3dモジュールを用いて、モデルを量子化しています。

torch.ao.nn.intrinsic.qat.ConvBn3dモジュールは、PyTorch Quantizationにおける重要な役割を担うモジュールです。このモジュールを活用することで、3D画像処理や動画処理などにおけるモデルの軽量化と精度維持を実現できます。



import torch
import torch.nn as nn
import torch.ao.nn.intrinsic.qat as qnn
import torch.quantization

# 畳み込み層とバッチ正規化層を定義
conv = nn.Conv3d(in_channels=16, out_channels=32, kernel_size=3, padding=1)
bn = nn.BatchNorm3d(32)

# 量子化対応`ConvBn3d`モジュールを作成
qat_conv_bn3d = qnn.ConvBn3d(conv, bn)

# モデルを構築
model = nn.Sequential(
    qat_conv_bn3d,
    nn.ReLU(),
    # ...
)

# 入力データと疑似入力を作成
input = torch.randn(1, 16, 32, 32, 32)
q_input = torch.quantization.quantize.quantize_static(input, dtype=torch.quint8)

# 量子化を行う
quantizer = torch.quantization.quantize.QuantStub(model)
quantizer.quantize()

# 量子の推論モードでモデルを実行
model.eval()
with torch.quantization.quantize.quantized_jit_script_version(model):
    # 推論処理
    output = model(q_input)

# 出力を表示
print(output)

このコードでは、以下の処理を実行しています。

  1. 畳み込み層とバッチ正規化層を定義します。
  2. 量子化対応ConvBn3dモジュールを作成します。
  3. モデルを構築します。
  4. 入力データと疑似入力を作成します。
  5. 量子化を行います。
  6. 量子の推論モードでモデルを実行します。
  7. 出力を表示します。

このコードはあくまでも例であり、実際の用途に合わせて変更する必要があります。

モデルの構築

このコードでは、シンプルな畳み込みニューラルネットワークを構築しています。実際のモデルでは、より複雑な構造になる可能性があります。

量子化の設定

このコードでは、quantize.QuantStubモジュールを用いて量子化を行っています。このモジュールは、モデル内の各モジュールに対して量子化設定を指定することができます。

このコードでは、model.eval()with torch.quantization.quantize.quantized_jit_script_version(model)を用いて、量子の推論モードを設定しています。

  • 出力は量子化された形式で表示されます。
  • このコードでは、疑似入力データを作成するためにtorch.quantization.quantize.quantize_static関数を使用しています。


torch.quantization.quantized.QuantAwareConvBn3d

torch.quantization.quantized.QuantAwareConvBn3dは、torch.ao.nn.intrinsic.qat.ConvBn3dと同様の機能を提供するモジュールです。主な違いは以下の通りです。

  • メモリ使用量
    torch.quantization.quantized.QuantAwareConvBn3dは、torch.ao.nn.intrinsic.qat.ConvBn3dよりも多くのメモリを使用します。
  • 量子化スケールとゼロポイントの推定方法
    torch.ao.nn.intrinsic.qat.ConvBn3dは擬似量子化を用いて推定しますが、torch.quantization.quantized.QuantAwareConvBn3dは実際の量子化操作を用いて推定します。

利点

  • より高い精度が期待できる
  • より正確な量子化スケールとゼロポイントを取得できる

欠点

  • 計算コストが高い
  • メモリ使用量が多い

使用例

import torch
import torch.nn as nn
import torch.quantization

# 畳み込み層とバッチ正規化層を定義
conv = nn.Conv3d(in_channels=16, out_channels=32, kernel_size=3, padding=1)
bn = nn.BatchNorm3d(32)

# 量子化対応`QuantAwareConvBn3d`モジュールを作成
qat_conv_bn3d = torch.quantization.quantized.QuantAwareConvBn3d(conv, bn)

# モデルを構築
model = nn.Sequential(
    qat_conv_bn3d,
    nn.ReLU(),
    # ...
)

# 量子化を行う
quantizer = torch.quantization.quantize.QuantStub(model)
quantizer.quantize()

# 量子の推論モードでモデルを実行
model.eval()
with torch.quantization.quantize.quantized_jit_script_version(model):
    # 推論処理
    output = model(input)

# 出力を表示
print(output)

torch.ao.nn.intrinsic.qat.ConvBn3dtorch.quantization.quantized.QuantAwareConvBn3dを使用せずに、手動で量子化を行うことも可能です。

利点

  • 計算コストを抑えられる
  • メモリ使用量を抑えられる

欠点

  • 量子化精度を調整するのが難しい
  • 複雑なコーディングが必要
import torch
import torch.nn as nn
import torch.quantization

# 畳み込み層とバッチ正規化層を定義
conv = nn.Conv3d(in_channels=16, out_channels=32, kernel_size=3, padding=1)
bn = nn.BatchNorm3d(32)

# 量子化を行う
def quantize_module(module):
    if isinstance(module, torch.nn.Conv3d):
        # 量子化スケールとゼロポイントを推定
        scale, zero_point = get_scale_and_zero_point(module)
        # 量子化操作を行う
        module = torch.quantization.quantized.quantize_static(
            module, dtype=torch.quint8, scale=scale, zero_point=zero_point
        )
    elif isinstance(module, torch.nn.BatchNorm3d):
        # 量子化スケールとゼロポイントを推定
        scale, zero_point = get_scale_and_zero_point(module)
        # 量子化操作を行う
        module = torch.quantization.quantized.quantize_static(
            module, dtype=torch.quint8, scale=scale, zero_point=zero_point
        )
    return module

# モデルを構築
model = nn.Sequential(
    quantize_module(conv),
    nn.ReLU(),
    # ...
)

# 量子の推論モードでモデルを実行
model.eval()
with torch.quantization.quantize.quantized_jit_script_version(model):
    # 推論処理
    output = model(input)