PyTorch---(EGNet开小灶)(1)---nn.Module, nn.Sequential, nn.Conv2d

1 nn.Module

"""Pytorch中神经网络模块化接口nn的了解"""

torch.nn是专门为神经网络设计的模块化接口。
nn构建于autograd之上,可以用来定义和运行神经网络
nn.Module是nn中十分重要的类,包含网络各层的定义forward方法
定义自已的网络:
    需要继承nn.Module类,并实现forward方法。
 => 一般把网络中具有可学习参数的层放在构造函数__init__()中,
 =>  不具有可学习参数的层(如ReLU)可放在构造函数中,也可不放在构造函数中(而在forward中使用nn.functional来代替)
    
    只要在nn.Module的子类中定义了forward函数backward函数就会被自动实现(利用Autograd)。
    在forward函数中可以使用任何Variable支持的函数,毕竟在整个pytorch构建的图中,是Variable在流动。
    还可以使用 if,for,print,log 等python语法.
    
    注:Pytorch基于nn.Module构建的模型中,只支持mini-batch的Variable输入方式,
    比如,只有一张输入图片,也需要变成 N x C x H x W 的形式:
    
    input_image = torch.FloatTensor(1, 28, 28)
    input_image = Variable(input_image)
    input_image = input_image.unsqueeze(0)   # 1 x 1 x 28 x 28

    
"""

 

# coding=utf-8
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.autograd import Variable
 
 
"""Pytorch中神经网络模块化接口nn的了解"""
"""
torch.nn是专门为神经网络设计的模块化接口。nn构建于autograd之上,可以用来定义和运行神经网络。
nn.Module是nn中十分重要的类,包含网络各层的定义及forward方法。
定义自已的网络:
    需要继承nn.Module类,并实现forward方法。
    一般把网络中具有可学习参数的层放在构造函数__init__()中,
    不具有可学习参数的层(如ReLU)可放在构造函数中,也可不放在构造函数中(而在forward中使用nn.functional来代替)
    
    只要在nn.Module的子类中定义了forward函数,backward函数就会被自动实现(利用Autograd)。
    在forward函数中可以使用任何Variable支持的函数,毕竟在整个pytorch构建的图中,是Variable在流动。还可以使用
    if,for,print,log等python语法.
    
    注:Pytorch基于nn.Module构建的模型中,只支持mini-batch的Variable输入方式,
    比如,只有一张输入图片,也需要变成 N x C x H x W 的形式:
    
    input_image = torch.FloatTensor(1, 28, 28)
    input_image = Variable(input_image)
    input_image = input_image.unsqueeze(0)   # 1 x 1 x 28 x 28
    
"""
 
 
class LeNet(nn.Module):
    def __init__(self):
        # nn.Module的子类函数必须在构造函数中执行父类的构造函数
        super(LeNet, self).__init__()   # 等价与nn.Module.__init__()
 
        # nn.Conv2d返回的是一个Conv2d class的一个对象,该类中包含forward函数的实现
        # 当调用self.conv1(input)的时候,就会调用该类的forward函数
        self.conv1 = nn.Conv2d(1, 6, (5, 5))   # output (N, C_{out}, H_{out}, W_{out})`
        self.conv2 = nn.Conv2d(6, 16, (5, 5))
        self.fc1 = nn.Linear(256, 120)
        self.fc2 = nn.Linear(120, 84)
        self.fc3 = nn.Linear(84, 10)
 
    def forward(self, x):
        # 不具有可学习参数的层(如ReLU)可放在构造函数中,也可不放在构造函数中(而在forward中使用nn.functional来代替)
        x = F.max_pool2d(F.relu(self.conv1(x)), (2, 2))  # F.max_pool2d的返回值是一个Variable
        x = F.max_pool2d(F.relu(self.conv2(x)), (2, 2))
        x = x.view(x.size()[0], -1)
        x = F.relu(self.fc1(x))
        x = F.relu(self.fc2(x))
        x = F.relu(self.fc3(x))
 
        # 返回值也是一个Variable对象
        return x
 
 
def output_name_and_params(net):
    for name, parameters in net.named_parameters():
        print('name: {}, param: {}'.format(name, parameters))
 
 
if __name__ == '__main__':
    net = LeNet()
    print('net: {}'.format(net))
    params = net.parameters()   # generator object
    print('params: {}'.format(params))
    output_name_and_params(net)
 
    input_image = torch.FloatTensor(10, 1, 28, 28)
 
    # 和tensorflow不一样,pytorch中模型的输入是一个Variable,而且是Variable在图中流动,不是Tensor。
    # 这可以从forward中每一步的执行结果可以看出
    input_image = Variable(input_image)
 
    output = net(input_image)
    print('output: {}'.format(output))
    print('output.size: {}'.format(output.size()))

 

 

补充说明:

x = x.view(x.size(0), -1)

一般出现在model类的forward函数中,具体位置一般都是在调用分类器之前。
分类器是一个简单的nn.Linear()结构输入输出都是维度为一的值,
x = x.view(x.size(0), -1)  这句话的出现就是为了将前面多维度的tensor展平成一维
下面是个简单的例子,我将会根据例子来对该语句进行解析。
 

class NET(nn.Module):
    def __init__(self,batch_size):
        super(NET,self).__init__()
        self.conv = nn.Conv2d(outchannels=3,in_channels=64,kernel_size=3,stride=1)
        self.fc = nn.Linear(64*batch_size,10)
 
    def forward(self,x):
        x = self.conv(x)
        x = x.view(x.size(0), -1)  
        out = self.fc(x)

上面是个简单的网络结构,包含一个卷积层和一个分类层。
forward()函数中,
input首先经过卷积层,此时的输出x是包含batchsize维度为4的tensor,即(batchsize,channels,x,y)
x.size(0)batchsize的值
x = x.view(x.size(0), -1)简化x = x.view(batchsize, -1)
view()函数的功能与reshape类似,用来转换size大小
x = x.view(batchsize, -1)中batchsize指转换后有几行
-1指在不告诉函数有多少列的情况下,根据原tensor数据batchsize自动分配列数
eg: 这里batchsize是1,所以就是打平为一维数组

 

2 nn.Sequential

 

PyTorch - torch.nn.Sequential
官网的示例

# Example of using Sequential
model = nn.Sequential(
          nn.Conv2d(1,20,5),
          nn.ReLU(),
          nn.Conv2d(20,64,5),
          nn.ReLU()
        )

# Example of using Sequential with OrderedDict
model = nn.Sequential(OrderedDict([
          ('conv1', nn.Conv2d(1,20,5)),
          ('relu1', nn.ReLU()),
          ('conv2', nn.Conv2d(20,64,5)),
          ('relu2', nn.ReLU())
        ]))

示例代码1
 

import torch
import torch.nn as nn
import torch.nn.functional as F

class Net(nn.Module):

    def __init__(self):
        super(Net, self).__init__()
        
        self.model = nn.Sequential(
          nn.Conv2d(1,20,5),
          nn.ReLU(),
          nn.Conv2d(20,64,5),
          nn.ReLU()
        )



output=Net()
print(output) 

# =============================================================================
# Net(
#   (model): Sequential(
#     (0): Conv2d(1, 20, kernel_size=(5, 5), stride=(1, 1))
#     (1): ReLU()
#     (2): Conv2d(20, 64, kernel_size=(5, 5), stride=(1, 1))
#     (3): ReLU()
#   )
# )
# =============================================================================

示例代码2
 

# 每一层都有名字
import torch
import torch.nn as nn
import torch.nn.functional as F
from collections import OrderedDict

class Net(nn.Module):

    def __init__(self):
        super(Net, self).__init__()
        
        self.model = nn.Sequential(OrderedDict([
                  ('conv1', nn.Conv2d(1,20,5)),
                  ('relu1', nn.ReLU()),
                  ('conv2', nn.Conv2d(20,64,5)),
                  ('relu2', nn.ReLU())
                ]))



output=Net()
print(output) 


# =============================================================================
# Net(
#   (model): Sequential(
#     (conv1): Conv2d(1, 20, kernel_size=(5, 5), stride=(1, 1))
#     (relu1): ReLU()
#     (conv2): Conv2d(20, 64, kernel_size=(5, 5), stride=(1, 1))
#     (relu2): ReLU()
#   )
# )
# =============================================================================

示例代码3
 

import torch
import torch.nn as nn
import torch.nn.functional as F
from collections import OrderedDict

class Net(nn.Module):

    def __init__(self):
        super(Net, self).__init__()
        self.model=nn.Sequential()
        self.model.add_module('conv1', nn.Conv2d(1,20,5))
        self.model.add_module('relu1', nn.ReLU())
        self.model.add_module('conv2', nn.Conv2d(20,64,5))
        self.model.add_module('relu2', nn.ReLU())


output=Net()
print(output) 


# =============================================================================
# Net(
#   (model): Sequential(
#     (conv1): Conv2d(1, 20, kernel_size=(5, 5), stride=(1, 1))
#     (relu1): ReLU()
#     (conv2): Conv2d(20, 64, kernel_size=(5, 5), stride=(1, 1))
#     (relu2): ReLU()
#   )
# )
# 
# =============================================================================

 

nn.Conv2d

PyTorch---(EGNet开小灶)(1)---nn.Module, nn.Sequential, nn.Conv2d_第1张图片

 

 

 

 

 

 

 

 

你可能感兴趣的:(EGNet,PyTorch)