Pytorchのtensorのrequires_gradがTrueになるとき

概要

Pytorchでニューラルネットワークの学習を行う際に重要な誤差逆伝播を行うためのメソッドとしてTensor.backward()があります。このbackwardを使用する場合には使用するTensorでrequires_grad=Trueを設定し、勾配を記録させておく必要があるということがPytorchのドキュメントにも書かれています。

Autograd mechanics — PyTorch 2.0 documentation

しかし、いろんなプログラムを見ると、requires_grad=Trueを設定せずにbackwardを使用している場合があり、なぜそれらが正しく動作しているのか疑問でした。

例えばこちらのプログラムのような例です。

machine-learning-articles/how-to-create-a-neural-network-for-regression-with-pytorch.md at main · christianversloot/machine-learning-articles · GitHub

今回はその理由について調べてみたことを記載しておこうと思います。

検証環境

Python 3.8.10

Pytorch 2.0.1

requires_gradがTrueでないとどうなるか

まず、requires_gradがTrueでない場合にbackwardを行うとどうなるかを試してみます。tensorを定義した際、デフォルトではrequires_gradはFalseになっています。

import torch
x = torch.tensor([[1., -1.], [1., -1.]])
y = x.sum()
print(y.requires_grad)
False

この状態でbackwardを行ってみます。

y.backward()

すると、以下のようなエラーが発生してbackwardを行うことができません。

RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn

しかし、Tensorを宣言する際にrequires_grad=Trueを設定しておくと、問題なくbackwardを行うことができます。例えば以下のようなコードの場合はエラーが発生しません。

import torch
x = torch.tensor([[1., -1.], [1., -1.]], requires_grad=True)
y = x.sum()
y.backward()

requires_grad=Trueを宣言しなくてもbackwardできる場合

しかし、冒頭で述べている通り、requires_grad=Trueを設定しなくてもbackwardできているコードがあります。例えば以下のようなコードはrequires_grad=Tureを最初のTensorで設定していませんが、backwardができます。

import torch
import torch.nn as nn

# requires_grad=Trueを設定していない
x = torch.tensor([[1., -1.], [1., -1.]])

model = nn.Sequential(
    nn.Linear(2, 4),
    nn.ReLU(),
    nn.Linear(4, 1)
)

y = model(x).sum()

y.backward()

backwardできる理由としてはnn.Sequential()のおかげです。

nn.Sequential()を通すことでその出力のtensorが自動的にrequires_gradがTrueに設定されます。以下がその確認のコードです。

import torch
import torch.nn as nn
x = torch.tensor([[1., -1.], [1., -1.]])

print("x.requires_grad is ", x.requires_grad)

model = nn.Sequential(
    nn.Linear(2, 4),
    nn.ReLU(),
    nn.Linear(4, 1)
)

print("model(x).requires_grad is ", model(x).requires_grad)

y = model(x).sum()

print("y.requires_grad is ", y.requires_grad)

y.backward()
x.requires_grad is  False
model(x).requires_grad is  True
y.requires_grad is  True

このようにnn.Sequential()で定義したモデルの出力は自動的にrequires_grad=Trueになっていると思われます。そのため、わざわざtensor定義時に設定する必要がなくbackwardが動作します。

おすすめ

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です