PyTorch报”AttributeError: ‘function’ object has no attribute ‘requires_grad_’ “的原因以及解决办法

  • Post category:Python

PyTorch是一个流行的深度学习框架,其使用非常广泛。在使用PyTorch进行深度学习的过程中可能会遇到“AttributeError: ‘function’ object has no attribute ‘requires_grad_'”这个错误,本文将详细介绍其原因以及解决方法。

问题原因

这个错误通常出现在使用PyTorch进行反向传播时。出现此错误的原因通常是在定义网络时,通过调用一个函数(比如nn.ReLU())作为层的初始化方法。然而,在使用该函数初始化层后,我们还需要对该层的参数进行更新。问题在于,该函数是一个“计算图节点”,无法像参数一样进行参数更新,所以我们必须将其转换为参数后再进行更新操作。

在PyTorch中,所有可以进行优化的参数都与requires_grad_属性相关联。 该属性指示该参数是否可以进行梯度计算。但是,错误信息显示“requires_grad_”不可用,通常是由于将函数视为参数时出现了问题。

解决方法

要解决此问题,有两个解决方法:

  1. 将函数替换为相应的类

替换函数为类通常是解决此问题的最佳方法。PyTorch中的大多数函数都有相应的类,而这些类可以直接用于参数更新。这些类实现了nn.Module的基本功能,包括将计算图节点转换为可优化的参数,并附加requires_grad_属性。

例如,如果您使用了ReLU函数来初始化一个层,可以将其替换为nn.ReLU()类的实例。请参阅以下示例代码:

import torch.nn as nn
import torch.optim as optim

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(1, 20, 5)      
        self.relu1 = nn.ReLU(inplace=True)  

    def forward(self, x):
        x = self.conv1(x)
        x = self.relu1(x)
        return x

net = Net()
criterion = nn.MSELoss()
optimizer = optim.SGD(net.parameters(), lr=0.01)

# 正确的参数更新方式
for epoch in range(3):
    for i, data in enumerate(trainloader, 0):
        inputs, labels = data
        optimizer.zero_grad()
        outputs = net(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()
  1. 对函数返回值执行detach()方法

如果您不想将函数替换为相应的类,也可以通过对函数返回值执行detach()方法来实现参数更新。detach()方法从计算图中分离张量,使其成为不需要梯度的新张量。此外,将.detach()与.requires_grad_ = True组合使用,可以将新张量重新附加到计算图中,并使其可以进行优化。

例如,如果您使用了ReLU函数来初始化一个层,可以将其替换为函数并对其返回值执行detach()方法,接着对新张量的requires_grad_属性进行修改。请参阅以下示例代码:

import torch.nn as nn
import torch.optim as optim

class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(1, 20, 5)      
        self.relu1 = nn.ReLU(inplace=True) 

    def forward(self, x):
        x = self.conv1(x)
        x = self.relu1(x).detach()      # 将ReLU函数的返回值进行分离
        x.requires_grad_ = True         # 重新附加到计算图中,并更新requires_grad_属性
        return x

net = Net()
criterion = nn.MSELoss()
optimizer = optim.SGD(net.parameters(), lr=0.01)

# 正确的参数更新方式
for epoch in range(3):
    for i, data in enumerate(trainloader, 0):
        inputs, labels = data
        optimizer.zero_grad()
        outputs = net(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()

总之,避免将函数视为参数而导致”AttributeError: ‘function’ object has no attribute ‘requires_grad_'”错误的最好方法是使用相应的类进行初始化。如果不想使用相应的类,请执行detach()方法以便能够对其返回值进行参数更新。