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全部手动写入
计算图中去,这样是非常不方便的。如果我们全部使用类的方式来构建计算图,这样即使是非常简单的操作都需要构建类,这样是写代码的效率是
非常低的。所以我们将卷积层、全连接层使用类的方式来进行定义,将池化和激活操作使用函数的方式进行使用,这样使我们更方便的构建计算图。