機械学習の詰め合わせ

機械学習周りで考えたことやインプットしたことをまとめる場所。

バイアスパラメータは重み減衰させるべきか?

「Biasパラメータはweight decayの対象から除外すべき」という意見[1]がある。

典拠

これの根拠について明示的に議論した論文は見つけられなかったが、Pytorch Forum[1]で言及されているように、NFNetの論文[2]において「biasとgain(どちらもscalar)のパラメータをweight decayの対象から除外した」という記述がある。

Critically, weight decay is not applied to the affine gains or biases in the weight standardized convolutional layers, or to the SkipInit gains.

なぜweight decayしてはいけないか?

典拠が見つけられなかったので以下に自分なりの考えを述べる。

そもそもweight decayがなぜ導入されたかというと、「重みのスケールが無限大に発散する」ことを防ぐためだった。現代の多くのニューラルネットワークではNormalizationレイヤーが挿入されており、「重みのスケールに対して不変」という性質を持っている。したがって、重みのスケールを小さくしたとしても、後続のnormalizationレイヤーによって適切な範囲に収まるため、重みを減衰したとしてもネットワークの表現力は影響を受けないことが推察される。

一方でバイアスパラメータは重みの「大きさ」を表現する量ではなく、「中心からのずれ」を表すパラメータである。これを小さくするということは、実質バイアスパラメータの役割を弱めることにつながる。

このように、ニューラルネットワークの「重み」と「バイアス」は異なる役割を果たすため、重み減衰についても異なる考え方が適用されるべき、という解釈が成り立つ。

実装方法

pytorchのOptimizerは上記で議論したような事情は考慮しないため、このような仕様を反映させようとすると自分でコーディングする必要がある。

最もシンプルな実装としては、[1]の回答で示されているような、「"weight"という文字列を含むパラメータはweight_decayを>0に、それ以外は0にする」というものがある。 pytorchのデフォルトのモジュールの多くは重みパラメータは*.weight、バイアスパラメータは*.biasというキーを持つので、多くのケースではこの実装で十分と思われる。ただし、自前でtorch.nn.parameter.Parameter()を使ってバイアスパラメータを定義した場合は専用の処理が必要になる。

model = models.resnet152()

decay = dict()
no_decay = dict()
for name, m in model.named_parameters():
    print('checking {}'.format(name))
    if 'weight' in name:
        decay[name] = param
    else:
        no_decay[name] = param
    
print(decay.keys())
print(no_decay.keys())

参考資料