Pytorch本人疑问(1) torch.nn和torch.nn.functional之间的区别

在写代码时发现我们在定义Model时,有两种定义方法:

torch.nn.Conv2d()和torch.nn.functional.conv2d()

那么这两种方法到底有什么区别呢,我们通过下述代码看出差别,先拿torch.nn.Conv2d

  • torch.nn.Conv2d
class Conv2d(_ConvNd):
    def __init__(self, in_channels, out_channels, kernel_size, stride=1,
                 padding=0, dilation=1, groups=1,
                 bias=True, padding_mode='zeros'):
        kernel_size = _pair(kernel_size)
        stride = _pair(stride)
        padding = _pair(padding)
        dilation = _pair(dilation)
        super(Conv2d, self).__init__(
            in_channels, out_channels, kernel_size, stride, padding, dilation,
            False, _pair(0), groups, bias, padding_mode)

        def forward(self, input):
            return self.conv2d_forward(input, self.weight)    
  • torch.nn.functional.conv2d
def conv2d(input, weight, bias=None, stride=1, padding=0, dilation=1,
                groups=1):
    if input is not None and input.dim() != 4:
        raise ValueError("Expected 4D tensor as input, got {}D tensor instead.".format(input.dim()))
    f = _ConvNd(_pair(stride), _pair(padding), _pair(dilation), False,
                        _pair(0), groups, torch.backends.cudnn.benchmark,
            torch.backends.cudnn.deterministic,torch.backends.cudnn.enabled)  
    return f(input, weight, bias)

对比上述代码我们可以发现,torch.nn.Conv2d是一个类,而torch.nn.functiona.conv2d()是一个函数,并且torch.nn.Conv2d中的forward()函数

是由torch.nn.functiona.conv2d()实现的(在Module类中有一个__call__实现了forward的调用)所以他们在功能的使用上并没有什么区别,但是我

们有了一个疑问,为什么要有着两个功能一样的方法呢?

其实主要的原因在乎我们构建计算图的时候,有些操作不需要进行体现在计算图中的,例如ReLu层,池化层。但是像卷积层、全连接层还是

需要体现在计算图中的。如果所有的层我们都用torch.nn.functional来定义,那么我们需要将卷积层和全连接层中的weights、bias全部手动写入

计算图中去,这样是非常不方便的。如果我们全部使用类的方式来构建计算图,这样即使是非常简单的操作都需要构建类,这样是写代码的效率是

非常低的。所以我们将卷积层、全连接层使用类的方式来进行定义,将池化和激活操作使用函数的方式进行使用,这样使我们更方便的构建计算图。

猜你喜欢

转载自www.cnblogs.com/sjq12138/p/12374459.html