0606-nn.functional

0606-nn.functional

pytorch完整教程目录:https://www.cnblogs.com/nickchen121/p/14662511.html

一、nn.functional 和 nn.Module 的区别

nn 中还有一个经常使用的模块 nn.functional,nn 中的绝大多数的 layer 在 functional 中都有一个和它对应的函数。

nn.functionalnn.Module的区别在于,Module 实现的 layers 是一个特殊的类,由 class Layer(nn.Module) 定义,会自动提取可学习的参数;而 functional 中的函数更像是一个纯函数,由 def fucntion(input) 定义。

import torch as t
from torch import nn
from torch.autograd import Variable as V
inp = V(t.randn(2, 3))
model = nn.Linear(3, 4)
output1 = model(inp)
output2 = nn.functional.linear(inp, model.weight, model.bias)
output1 == output2
tensor([[True, True, True, True],
        [True, True, True, True]])
b = nn.functional.relu(inp)
b2 = nn.ReLU()(inp)
b == b2
tensor([[True, True, True],
        [True, True, True]])

从上述代码可以看到 Module 和 functional 的功能类似,那么这两者我们什么时候会用到呢?

答案很简单,如果有可学习的参数时,最好用 Module,反之既可以用 functional,当然也可以用 Module,因为二者在性能上并没有很大的差别。

例如,由于激活函数、池化等层没有可学习参数,可以使用对应的 functional 函数代替,而卷积、全连接层有可学习参数,尽量使用 Module。

但是有一个例外,dropout 操作也没有可学习参数,但是由于 dropout 操作在训练和测试两个阶段的行为有区别,如果使用 Module 对象那个能够通过 model.eval 加以区分。

二、nn.functional 和 nn.Module 结合使用

下面举例将 functional 和 Module 结合使用。

from torch.nn import functional as F


class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.conv1 = nn.Conv2d(3, 6, 5)
        self.conv2 = nn.Conv2d(6, 16, 5)
        self.fc1 = nn.Linear(16 * 5 * 5, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)

    def forward(self, x):
        x = F.pool(F.relu(self.conv1(x)), 2)
        x = F.pool(F.relu(self.conv2(x)), 2)
        x = x.view(-1, 16 * 5 * 5)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = self.fc3(x)

        return x

没有可学习参数的层,可以用函数代替他们,因此可以不用放在构造函数中。

对于有可学习参数的层,虽然也可以用 functional 替代,只不过实现起来步骤麻烦,需要自己手动定义参数,比如前面实现的全连接层,既可以吧 weight 和 bias 两个参数拿出来,在构造函数中初始化为 parameter,例子如下:

class MyLinear(nn.Module):
    def __init__(self):
        super(MyLinear, sefl).__init__()
        self.weight = nn.Parameter(t.randn(3, 4))
        self.bias = nn.Parameter(t.zeros(3))

    def forward(self):
        return F.linear(input, weight, bias)

从上面的代码可以看出,如果通过 functional 去构造一个具有可学习参数的层,是非常麻烦的,不如 Module 那样简便。

很多同学现在可能会想,functional 看起也不是那么方便,并且 Module 已经够好了,为什么还要设计 functional 呢?想深入了解 functional 和 Module的区别的同学,可以参考论坛的讨论和作者写的说明:https://discuss.pytorch.org/search?q=nn.functional

posted @ 2021-04-25 20:15  B站-水论文的程序猿  阅读(901)  评论(0编辑  收藏  举报