4.2.2 激活函数

1.最常用的激活函数ReLU

数学表达式: ReLU(x) = max(0,x)

import torch as t
from torch import nn
from torch.autograd import Variable as V

relu = nn.ReLU(inplace=True) # inplace = True代表它会把输出直接覆盖到输入中,这样可以节省内存/显存‘
input = V(t.randn(2,3))
print(input)
output = relu(input)   # 等价于input.clamp(min=0)
print(output)

2.前馈神经网络简化forward函数的方法

  1. 对于前馈传播网络(前一层的输出作为下一层的输入),如果每次都写复杂的forward函数的话会有一些麻烦
  2. 有两种简化方法,ModuleList和Sequential。

Sequential代码

import torch as t
from torch import nn
from torch.autograd import Variable as V

# Sequential 三种写法
net1 = nn.Sequential()
net1.add_module('conv',nn.Conv2d(3,3,(3,3)))  # 卷积核个数为3
net1.add_module('batchnorm',nn.BatchNorm2d(3))
net1.add_module('activation_layer',nn.ReLU())

net2 = nn.Sequential(nn.Conv2d(3,3,3),nn.BatchNorm2d(3),nn.ReLU())

from collections import OrderedDict
net3 = nn.Sequential(OrderedDict([
    ('conv1',nn.Conv2d(3,3,3)),
    ('bn1',nn.BatchNorm2d(3)),
    ('relu1',nn.ReLU())
    ]))

print('net1',net1)
print('net2',net2)
print('net3',net3)

#可以根据名字或者序号取出子module
print('......................................................')
print(net1.conv)
print(net2[0])
print(net3.conv1)

print('......................................................')
input = V(t.randn(1,3,4,4))

output = net1(input)
print(output)
output = net2(input)
print(output)
output = net3(input)
print(output)
output = net3.relu1(net1.batchnorm(net1.conv(input)))

输出:

net1 Sequential(
  (conv): Conv2d(3, 3, kernel_size=(3, 3), stride=(1, 1))
  (batchnorm): BatchNorm2d(3, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (activation_layer): ReLU()
)
net2 Sequential(
  (0): Conv2d(3, 3, kernel_size=(3, 3), stride=(1, 1))
  (1): BatchNorm2d(3, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (2): ReLU()
)
net3 Sequential(
  (conv1): Conv2d(3, 3, kernel_size=(3, 3), stride=(1, 1))
  (bn1): BatchNorm2d(3, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
  (relu1): ReLU()
)
......................................................
Conv2d(3, 3, kernel_size=(3, 3), stride=(1, 1))
Conv2d(3, 3, kernel_size=(3, 3), stride=(1, 1))
Conv2d(3, 3, kernel_size=(3, 3), stride=(1, 1))
......................................................
......................................................
tensor([[[[0.0000, 0.8485],
          [0.0000, 0.6886]],

         [[0.0000, 0.1103],
          [0.2003, 0.5588]],

         [[0.0000, 0.0000],
          [0.0000, 1.5874]]]], grad_fn=<ThresholdBackward0>)
tensor([[[[1.0474, 0.0077],
          [0.0790, 0.0000]],

         [[0.1522, 0.8856],
          [0.0000, 0.0000]],

         [[0.0000, 0.0000],
          [0.1706, 0.1127]]]], grad_fn=<ThresholdBackward0>)
tensor([[[[0.3883, 0.0000],
          [0.0000, 0.0269]],

         [[0.0610, 0.1589],
          [0.0000, 0.0000]],

         [[0.0000, 0.0358],
          [0.0000, 0.0396]]]], grad_fn=<ThresholdBackward0>)

ModuleList代码

import torch as t
from torch import nn
from torch.autograd import Variable as V 

modellist = nn.ModuleList([nn.Linear(3,4),nn.ReLU(),nn.Linear(4,2)])
input = V(t.randn(1,3))
for model in modellist: #modellist没有实现forward,所以不能直接这样写:outout = modellist(input)
    input = model(input)

print(input)

输出:

tensor([[1.2580, 0.8318]], grad_fn=<AddmmBackward>)

3. 测试ModuleList中的子Module可以被主Module识别,而普通的List中的却不能

import torch as t
from torch import nn
from torch.autograd import Variable as V

class MyModule(nn.Module):
    def __init__(self):
        super(MyModule,self).__init__() # 显示调用父类构造函数
        self.list = [nn.Linear(2,3),nn.ReLU()]
        self.module_list = nn.ModuleList([nn.Conv2d(3,3,3),nn.ReLU()])
    def forward(self, *input):
        pass

model = MyModule()
print(model)

for name,param in model.named_parameters():
    print(name,param.size())

输出结果:

MyModule(
  (module_list): ModuleList(
    (0): Conv2d(3, 3, kernel_size=(3, 3), stride=(1, 1))
    (1): ReLU()
  )
)
module_list.0.weight torch.Size([3, 3, 3, 3])
module_list.0.bias torch.Size([3])

可见,list中的子module不能被主module识别,而ModuleList中的子module能够被module识别。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值