可以看下面的代码
其实TestNet_1和TestNet_2执行的结果是一样的,但是明显 Relu的位置是不一样的,一个是nn库内的,一个是nn.functional内的
import torch.nn as nn
import torch.nn.functional as F
import torch.nn as nn
class TestNet_1(nn.Module):
def __init__(self, num_classes=n):
super(TestNet_1, self).__init__()
self.features = nn.Sequential(
nn.Conv2d(3, 64, kernel_size=3, stride=2, padding=1),
nn.BatchNorm2d(64),
nn.ReLU(inplace=True),
)
def forward(self, x):
x = self.features(x)
class TestNet_2(nn.Module):
def __init__(self, num_classes=n):
super(TestNet_2, self).__init__()
self.features = nn.Sequential(
nn.Conv2d(3, 64, kernel_size=3, stride=2, padding=1),
nn.BatchNorm2d(64),
)
def forward(self, x):
x = self.features(x)
x = F.ReLU(x)
不同点在于:
nn.ReLU作为一个层结构,必须添加到nn.Module容器中才能使用,而F.ReLU则作为一个函数调用,看上去作为一个函数调用更方便更简洁。具体使用哪种方式,取决于编程风格。
在PyTorch中,nn.X都有对应的函数版本F.X,但是并不是所有的F.X均可以用于forward或其它代码段中,因为当网络模型训练完毕时,在存储model时,在forward中的F.X函数中的参数是无法保存的。也就是说,在forward中,使用的F.X函数一般均没有状态参数,比如F.ReLU,F.avg_pool2d等,均没有参数,它们可以用在任何代码片段中。
另外nn.ReLU()和nn.ReLU(inplace=True)的不同
参数: inplace-选择是否进行覆盖运算
意思是是否将得到的值计算得到的值覆盖之前的值,比如:
x = x +1
即对原值进行操作,然后将得到的值又直接复制到该值中
而不是覆盖运算的例子如:
y = x + 1
x = y
这样就需要花费内存去多存储一个变量y
即加了inplace=True的relu,能够节省运算内存,不用多存储其他变量