当扩展此类时,它的一种方法现在需要一个额外的参数。为什么?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了当扩展此类时,它的一种方法现在需要一个额外的参数。为什么?相关的知识,希望对你有一定的参考价值。

[当我想对初始化的model = nn.Sequential对象进行前向传递时,我只使用:

out = model(X)
# OR
out = model.forward(X)

但是,我尝试扩展Sequential类,现在这两个方法突然都需要第二个参数。例如,在以下方法中记下我对self(x)的调用:

def train(self, trainloader, epochs):
        for e in range(epochs):
            for x, y in trainloader:
                x = x.view(x.shape[0], -1)
                self.optimizer.zero_grad()
                loss = self.criterion(self(x), y) # CALL OCCURS HERE
                loss.backward()
                self.optimizer.step()


此代码现在给了我TypeError: forward() missing 1 required positional argument: 'target'

我的问题:由于除了扩展类外我什么也没做,所以为什么呢?

以下完整课程的代码:

class Network(nn.Sequential):
    def __init__(self, layers):
        super().__init__(self.init_modules(layers))
        self.criterion = nn.NLLLoss()
        self.optimizer = optim.Adam(self.parameters(), lr=0.003)

    def init_modules(self, layers):

        n_layers = len(layers)
        modules = OrderedDict()

        # Layer definitions for input and inner layers:
        for i in range(n_layers - 2):
            modules[f'fc{i}']   = nn.Linear(layers[i], layers[i+1])
            modules[f'relu{i}'] = nn.ReLU()

        # Definition for output layer:
        modules['fc_out'] = nn.Linear(layers[-2], layers[-1])
        modules['smax_out'] = nn.LogSoftmax(dim=1)

        return modules


    def train(self, trainloader, epochs):
        for e in range(epochs):
            for x, y in trainloader:
                x = x.view(x.shape[0], -1)
                self.optimizer.zero_grad()
                loss = self.criterion(self(x), y)
                loss.backward()
                self.optimizer.step()

完整堆栈跟踪:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-63-490e0b9eef22> in <module>
----> 1 model2.train(trainloader, 5, plot_loss=True)

<ipython-input-61-e173e5672f18> in train(self, trainloader, epochs, plot_loss)
     32                 x = x.view(x.shape[0], -1)
     33                 self.optimizer.zero_grad()
---> 34                 loss = self.criterion(self(x), y)
     35                 loss.backward()
     36                 self.optimizer.step()

c:\program files\python38\lib\site-packages\torch\nn\modules\module.py in __call__(self, *input, **kwargs)
    548             result = self._slow_forward(*input, **kwargs)
    549         else:
--> 550             result = self.forward(*input, **kwargs)
    551         for hook in self._forward_hooks.values():
    552             hook_result = hook(self, input, result)

c:\program files\python38\lib\site-packages\torch\nn\modules\container.py in forward(self, input)
     98     def forward(self, input):
     99         for module in self:
--> 100             input = module(input)
    101         return input
    102 

c:\program files\python38\lib\site-packages\torch\nn\modules\module.py in __call__(self, *input, **kwargs)
    548             result = self._slow_forward(*input, **kwargs)
    549         else:
--> 550             result = self.forward(*input, **kwargs)
    551         for hook in self._forward_hooks.values():
    552             hook_result = hook(self, input, result)

TypeError: forward() missing 1 required positional argument: 'target'

答案

问:由于我除了扩展课程外什么都没做,为什么呢?

实际上,您有。您选择了“错误的”基类。 forwardnn.Sequential仅遍历所有模块,并且在您定义时:

self.criterion = nn.NLLLoss()

您将损失注册为模块。因此,当您调用self(x)时,实际上是在某个时候调用了self.criterion(x),因此实际上是在调用TypeError

另一答案

注意self.criterion是类nn.NLLLoss的一个实例。您需要传递一个火炬张量作为第二个参数,确保y满足该类型要求。另外,我不确定此行loss = self.criterion(self(x), y)为什么要呼叫self(x)?第一个参数应该是通过激活函数传递的输入数据。

以上是关于当扩展此类时,它的一种方法现在需要一个额外的参数。为什么?的主要内容,如果未能解决你的问题,请参考以下文章

当 Python __call__ 方法获得额外的第一个参数时?

Qt on Python 中的 QThread

添加额外的渲染调用时,GLFW 挂起关闭

在 TypeScript 中,当类型是函数的参数时,有没有办法限制 Partial<T> 类型的额外/多余属性?

设计模式

什么是参数化查询?