1. ホーム
  2. パイソン

[解決済み】PyTorchでzero_grad()を呼び出す必要があるのはなぜ?

2022-04-06 15:07:46

質問

方法 zero_grad() はトレーニング中に呼び出される必要があります。しかし ドキュメント はあまり参考にならない

|  zero_grad(self)
|      Sets gradients of all model parameters to zero.

なぜ、このメソッドを呼び出す必要があるのでしょうか?

どのように解決するのですか?

PyTorch の間、ミニバッチごとに トレーニング フェーズでは、バックプロパゲーションを開始する前に明示的に勾配をゼロに設定したいものです(つまり、勾配をゼロにするために W エイト b ケース ) なぜならPyTorchは はグラデーションを蓄積します。 を、その後のバックワードパスで使用します。この蓄積動作は、RNNの学習時や、複数の ミニバッチ . そのため、デフォルトのアクションは グラデーションを累積する(=合計する すべての loss.backward() を呼び出します。

このため、トレーニングループを開始するとき、理想的には、次のようにします。 zero out the gradients で、パラメータの更新を正しく行うことができます。そうしないと、モデルパラメータの更新に使った古い勾配と、新しく計算した勾配を組み合わせた勾配になってしまうからです。そのため、この勾配は 最小 (または 最大 最大化目的の場合)。

ここで簡単な例を挙げます。

import torch
from torch.autograd import Variable
import torch.optim as optim

def linear_model(x, W, b):
    return torch.matmul(x, W) + b

data, targets = ...

W = Variable(torch.randn(4, 3), requires_grad=True)
b = Variable(torch.randn(3), requires_grad=True)

optimizer = optim.Adam([W, b])

for sample, target in zip(data, targets):
    # clear out the gradients of all Variables 
    # in this optimizer (i.e. W, b)
    optimizer.zero_grad()
    output = linear_model(sample, W, b)
    loss = (output - target) ** 2
    loss.backward()
    optimizer.step()


あるいは、もしあなたが バニラグラディエントディセント であれば、です。

W = Variable(torch.randn(4, 3), requires_grad=True)
b = Variable(torch.randn(3), requires_grad=True)

for sample, target in zip(data, targets):
    # clear out the gradients of Variables 
    # (i.e. W, b)
    W.grad.data.zero_()
    b.grad.data.zero_()

    output = linear_model(sample, W, b)
    loss = (output - target) ** 2
    loss.backward()

    W -= learning_rate * W.grad.data
    b -= learning_rate * b.grad.data


備考 :

  • 蓄積 (すなわち 合計 の場合、グラデーションが発生します。 .backward() が呼び出されます。 loss テンソル .
  • v1.7.0では、Pytorchは勾配をリセットするオプションを提供しており、勾配を None optimizer.zero_grad(set_to_none=True) をゼロのテンソルで埋めないでください。ドキュメントによれば、この設定は必要なメモリを減らし、わずかにパフォーマンスを向上させるが、注意深く扱わなければエラーを起こしやすいかもしれないとのことである。