为什么在打印net时未列出torch.nn.Parameter?

时间:2019-02-19 15:54:25

标签: python pytorch

我最近不得不构造一个需要包含张量的模块。尽管使用torch.nn.Parameter可以很好地进行反向传播,但是在打印网络对象时却没有显示。为什么不像其他类似parameter的模块那样包含此layer? (它的行为不应该像layer吗?)

import torch
import torch.nn as nn

class MyNet(torch.nn.Module):
    def __init__(self):
        super(MyNet, self).__init__()
        self.layer = nn.Linear(10, 10)
        self.parameter = torch.nn.Parameter(torch.zeros(10,10, requires_grad=True))

net = MyNet()
print(net)

输出:

MyNet(
  (layer): Linear(in_features=10, out_features=10, bias=True)
)

2 个答案:

答案 0 :(得分:4)

调用print(net)时,将调用__repr__方法。 __repr__给出对象的“正式”字符串表示形式。

在PyTorch的{​​{3}}(MyNet模型的基类)中,__repr__的实现方式如下:

def __repr__(self):
        # We treat the extra repr like the sub-module, one item per line
        extra_lines = []
        extra_repr = self.extra_repr()
        # empty string will be split into list ['']
        if extra_repr:
            extra_lines = extra_repr.split('\n')
        child_lines = []
        for key, module in self._modules.items():
            mod_str = repr(module)
            mod_str = _addindent(mod_str, 2)
            child_lines.append('(' + key + '): ' + mod_str)
        lines = extra_lines + child_lines

        main_str = self._get_name() + '('
        if lines:
            # simple one-liner info, which most builtin Modules will use
            if len(extra_lines) == 1 and not child_lines:
                main_str += extra_lines[0]
            else:
                main_str += '\n  ' + '\n  '.join(lines) + '\n'

        main_str += ')'
        return main_str

请注意,上述方法返回main_str,其中仅包含对_modulesextra_repr的调用,因此默认情况下仅打印模块。


PyTorch还提供了nn.Module方法,您可以自己实现该方法以额外表示模块。

  

要打印自定义的其他信息,应在自己的模块中重新实现此方法。单行和多行字符串都是可以接受的。

答案 1 :(得分:1)

根据nn.Parameter文档:

  

参数是:class:~torch.Tensor子类,它们具有       与:class:Module一起使用时非常特殊的属性-当它们       分配为模块属性后,它们会自动添加到以下列表中       其参数,并会出现在在:meth:~Module.parameters迭代器中。

因此您可以在net.parameters中找到它。让我们看下面的例子:

代码:

import torch
import torch.nn as nn

torch.manual_seed(42)

class MyNet(nn.Module):
    def __init__(self):
        super(MyNet, self).__init__()
        self.layer = nn.Linear(4, 4)
        self.parameter = nn.Parameter(torch.zeros(4, 4, requires_grad=True))
        self.tensor = torch.ones(4, 4)
        self.module = nn.Module()

net = MyNet()
print(net)

输出:

MyNet(
  (layer): Linear(in_features=4, out_features=4, bias=True)
  (module): Module()
)

如您所见,没有tensor或'parameter'对象(因为parametertensor的子类),只有Module个。

现在让我们尝试获取我们的净参数:

代码:

for p in net.parameters():
    print(p)

输出:

Parameter containing:
tensor([[0., 0., 0., 0.],
        [0., 0., 0., 0.],
        [0., 0., 0., 0.],
        [0., 0., 0., 0.]], requires_grad=True)
Parameter containing:
tensor([[ 0.3823,  0.4150, -0.1171,  0.4593],
        [-0.1096,  0.1009, -0.2434,  0.2936],
        [ 0.4408, -0.3668,  0.4346,  0.0936],
        [ 0.3694,  0.0677,  0.2411, -0.0706]], requires_grad=True)
Parameter containing:
tensor([ 0.3854,  0.0739, -0.2334,  0.1274], requires_grad=True)

好的,所以第一个是您的net.parameter。接下来的两个是net.layer的权重和偏差。让我们验证一下:

代码:

print(net.layer.weight)
print(net.layer.bias)

输出:

Parameter containing:
tensor([[ 0.3823,  0.4150, -0.1171,  0.4593],
        [-0.1096,  0.1009, -0.2434,  0.2936],
        [ 0.4408, -0.3668,  0.4346,  0.0936],
        [ 0.3694,  0.0677,  0.2411, -0.0706]], requires_grad=True)
Parameter containing:
tensor([ 0.3854,  0.0739, -0.2334,  0.1274], requires_grad=True)