PyTorch ParametrizationList API リファレンス:ニューラルネットワークのパラメータ変換と制約に関する包括的なガイド


  • ParametrizationListは、nn.Moduleサブクラスとして実装されており、ネットワークアーキテクチャにシームレスに統合できます。
  • パラメータの変換や制約を定義するParametrizationモジュールをリスト形式で保持します。
  • ParametrizationListは、ニューラルネットワークのパラメータを管理するモジュールです。

ParametrizationListの役割

  • 動的なパラメータ更新: 訓練中にパラメータを変換または制約し、モデルの学習を制御できます。
  • パラメータの制約: 重み行列の対称性、正定性、スパース性などの制約を定義できます。
  • パラメータの変換: 重み行列の直交化、スケーリング、正規化など、パラメータに対する任意の変換を定義できます。

ParametrizationListの利点

  • モデルの解釈可能性を向上: パラメータ変換や制約により、モデルの動作をより理解しやすくなります。
  • モデルの学習を安定化: パラメータ制約により、勾配消失や爆発などの問題を防ぎ、訓練を安定化させます。
  • モデルの表現力を向上: パラメータ変換により、モデルがより複雑な関数を学習できるようにします。

ParametrizationListの例

  • 活性化関数の変換: ReLU活性化関数をシグモイド関数に変換することで、モデルの出力をより滑らかにすることができます。
  • 重み行列のスパース化: 重み行列の要素をスパースにすることで、モデルの複雑さを削減し、解釈性を向上できます。
  • 重み行列の直交化: 重み行列を直交行列に制約することで、勾配消失問題を防ぎ、訓練を安定化できます。

ParametrizationListの使用方法

  1. Parametrizationモジュールを作成する: パラメータの変換または制約を定義するモジュールを作成します。
  2. ParametrizationListを作成する: Parametrizationモジュールのリストを作成します。
  3. ParametrizationListをネットワークに適用する: ParametrizationListをネットワークのパラメータに適用します。
  • ParametrizationListは、研究論文や最先端のニューラルネットワークアーキテクチャで広く使用されています。
  • ParametrizationListは、PyTorch 1.10以降で使用できます。


import torch
import torch.nn as nn
import torch.nn.utils.parametrize as parametrize

class OrthogonalWeightParametrization(parametrize.Parametrization):
    def __init__(self, module):
        super().__init__(module)
        self.q = nn.Parameter(torch.randn(module.weight.size()))

    def forward(self):
        w = self.module.weight
        q = self.q.reshape(w.size())
        return q.t() @ w

def model(x):
    layer = nn.Linear(in_features=x.shape[1], out_features=10)
    layer = parametrize.register_parametrization(layer, "weight", OrthogonalWeightParametrization)
    return layer(x)

x = torch.randn(10, 20)
y = model(x)
print(y)

例2: 重み行列のスパース化

import torch
import torch.nn as nn
import torch.nn.utils.parametrize as parametrize

class SparseWeightParametrization(parametrize.Parametrization):
    def __init__(self, module, sparsity):
        super().__init__(module)
        self.sparsity = sparsity
        self.mask = nn.Parameter(torch.zeros(module.weight.size()))

    def forward(self):
        w = self.module.weight
        mask = self.mask.sigmoid()
        return w * mask

def model(x):
    layer = nn.Linear(in_features=x.shape[1], out_features=10)
    layer = parametrize.register_parametrization(layer, "weight", SparseWeightParametrization(sparsity=0.5))
    return layer(x)

x = torch.randn(10, 20)
y = model(x)
print(y)

例3: 活性化関数の変換

import torch
import torch.nn as nn
import torch.nn.utils.parametrize as parametrize

class SigmoidParametrization(parametrize.Parametrization):
    def __init__(self, module):
        super().__init__(module)
        self.alpha = nn.Parameter(torch.ones_like(module.relu.gain))

    def forward(self):
        relu = self.module.relu
        return relu(x) * self.alpha

def model(x):
    layer = nn.Sequential(
        nn.Linear(in_features=x.shape[1], out_features=10),
        nn.ReLU(),
    )
    layer = parametrize.register_parametrization(layer, "relu", SigmoidParametrization)
    return layer(x)

x = torch.randn(10, 20)
y = model(x)
print(y)

これらの例は、ParametrizationListを使用してパラメータを変換および制約する方法を説明しています。ParametrizationListは、より複雑な変換や制約を定義するために拡張できます。

  • ParametrizationListに関する詳細は、PyTorchの公式ドキュメントを参照してください。
  • ParametrizationListは、PyTorch 1.10以降で使用できます。
  • 上記のコードはあくまで例であり、具体的な用途に合わせて調整する必要があります。


関数フック

  • ParametrizationListよりも柔軟性がありますが、コードが冗長になる可能性があります。
  • パラメータ更新時に任意の変換や制約を適用する関数を定義できます。
import torch
import torch.nn as nn

def orthogonalize_weights(module):
    if hasattr(module, "weight"):
        w = module.weight
        q, _ = torch.qr(w)
        module.weight = q.t()

def model(x):
    layer = nn.Linear(in_features=x.shape[1], out_features=10)
    layer.register_forward_hook(orthogonalize_weights)
    return layer(x)

x = torch.randn(10, 20)
y = model(x)
print(y)

カスタムモジュール

  • ParametrizationListよりもコードが読みやすくなりますが、汎用性が低くなります。
  • パラメータ変換や制約をカプセル化するカスタムモジュールを作成できます。
import torch
import torch.nn as nn

class OrthogonalLinear(nn.Module):
    def __init__(self, in_features, out_features):
        super().__init__()
        self.linear = nn.Linear(in_features, out_features)

    def forward(self, x):
        w = self.linear.weight
        q, _ = torch.qr(w)
        self.linear.weight = q.t()
        return self.linear(x)

model = OrthogonalLinear(in_features=x.shape[1], out_features=10)
y = model(x)
print(y)

手動のパラメータ更新

  • 最も低レベルな方法ですが、コードが冗長でエラーが発生しやすい可能性があります。
  • 訓練ループ内でパラメータを直接更新できます。
import torch
import torch.nn as nn

def model(x):
    layer = nn.Linear(in_features=x.shape[1], out_features=10)
    for epoch in range(10):
        w = layer.weight
        q, _ = torch.qr(w)
        layer.weight = q.t()
        y = layer(x)
        # ...

最適な代替方法は、具体的なニーズと要件によって異なります。

ParametrizationListは、汎用性と柔軟性の高い選択肢ですが、関数フックはより柔軟性があり、カスタムモジュールはコードの可読性を向上させます。手動のパラメータ更新は、最も低レベルな方法ですが、特定の状況で役立つ場合があります。