【pytorch】torch.nn 与 torch.nn.functional 的区别

在初学Pytorch 创建模型的时候,总会出现不知道要把layer放在 init() 中还是 forwad() 中,也不知道到底该使用nn.Conv2d 还是F.conv2d. 为此带来了不必要的烦恼.我为了搞清用法查看了官方doc并在pytorch论坛上做了询问,此为讨论的链接
整理结果如下:


torch.nn

torch.nn 这个模块下面存的主要是 Module类.以torch.nn.Conv2d为例, 也就是说 torch.nn.Conv2d这种"函数"其实是个 Module类,在实例化类后会初始化2d卷积所需要的参数. 这些参数会在你做forward和 backward之后根据loss进行更新,所以通常存放在定义模型的 _init_() 中.如:

class MyModel(nn.Module):
    def __init__(self):
        super(MyModel, self).__init__()
        #其实这里就是类的实例化,需要定义初始参数
        self.conv1 = nn.Conv2d(3, 6, 3, 1, 1)
        self.act = nn.ReLU()
        
    def forward(self, x):
        x = self.act(self.conv1(x))
        return x

那在定义模型时,可不可以把nn.Conv2d写在forward处?

  • 不可以
    如果写成类似这样会有什么影响呢?
class MyModel(nn.Module):
    def __init__(self):
        super(MyModel, self).__init__()
        self.act = nn.ReLU()
        
    def forward(self, x):
        # 把卷积函数写在forward中
        x= nn.Conv2d(3, 6, 3, 1, 1)(x)
        x = self.act(x)
        return x

把nn.Conv2d写在forward中就相当于模型每次跑forward的时候,都重新实例化了nn.Conv2d和nn.Conv2d的参数,导致模型学不到参数.

torch.nn.functional

torch.nn.functional.x 为函数,与torch.nn不同, torch.nn.x中包含了初始化需要的参数等 attributes 而torch.nn.functional.x则需要把相应的weights 作为输入参数传递,才能完成运算, 所以用torch.nn.functional创建模型时需要创建并初始化相应参数.
例如:

import torch.nn.functional as F
class MyModel(nn.Module):
    def __init__(self):
        super(MyModel, self).__init__()
        self.act = nn.ReLU()
        self.weighs = nn.Parameter(torch.rand(x,x,x,x))
        self.bias = nn.Parameter(torch.rand(x))
        
    def forward(self, x):
        # 把卷积函数写在forward中,把w和b传入函数
        x= F.conv2d(x,self.weighs,self.bias)
        x = self.act(x)
        return x

查看两者的doc即可看出区别:

torch.nn.functional.conv2d(input, weight, bias=None, stride=1, padding=0, dilation=1, groups=1) → Tensor

CLASS torch.nn.Conv2d(in_channels, out_channels, kernel_size, stride=1, padding=0, dilation=1, groups=1, bias=True, padding_mode=‘zeros’)

即一个侧重数据结构,一个侧重算法运算. 其实两个都是完成了同样的功能,只是实现方式有些不同而已

总结

torch.nn.Xtorch.nn.functional.X
是 类是函数
结构中包含所需要初始化的参数需要在函数外定义并初始化相应参数,并作为参数传入
一般情况下放在_init_ 中实例化,并在forward中完成操作一般在_init_ 中初始化相应参数,在forward中传入

所以 模型要么写成这样

class MyModel(nn.Module):
    def __init__(self):
        super(MyModel, self).__init__()
        # which has its own hidden parameters 
        self.conv_like = nn.convlike() 
        
    def forward(self, x):
        x = self.conv_like(x)

要么写成这样:

class MyModel(nn.Module):
    def __init__(self):
        super(MyModel, self).__init__()
        # which will be used in nn.functional.funs 
        self.func_params = params 
        
    def forward(self, x):
        x = nn.functional.funs(x,self.func_params)
当所需的函数不含有需要学习的参数且在train和test阶段运行方法一致时,无论用torch.nn.X 还是torch.nn.functional.X 都可以,并且既可以现在 init中声明,也可以直接在forward中使用
  • 如: torch.nn.functional.relu, torch.nn.ReLU
train和test阶段运行方法一致时,尽量用 torch.nn,避免了手动控制的麻烦
  • batch normalization 和 dropout
  • 42
    点赞
  • 97
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值