PyTorch学习笔记之模型构建和模型初始化

PyTorch学习笔记之模型构建和模型初始化

2.3 模型构建

2.3.1 构造神经网络

  • Module类是nn模块里提供的一个模型构造类,是所有神经网络模块的基类,可以继承它来定义模型
  1. 举例继承Module类构造多层感知机
  • 这里定义的MLP类重载了Module类的init函数(用于创建模型参数)和forward函数(用于定义前向计算,即正向传播)
import torch
from torch import nn

class MLP(nn.Module):
    #声明带有模型参数的层,这里声明了两个全连接层
    def __init__(self, **kwargs):
        #调用MLP父类Block的构造函数来进行必要的初始化,这样在构造实例时还可以指定其他函数
        super(MLP, self).__init__(**kwargs)
        self.hidden = nn.Linear(784, 256)
        self.act = nn.ReLU()
        self.output = nn.Linear(256,10)
        
	#定义模型的前向计算,即如何根据输入x计算返回所需要的模型输出
    def forward(self, x):
        o = self.act(self.hidden(x))
        return self.output(o)
  • 以上的MLP类无需定义反向传播函数,系统将通过自动求梯度而自动生成反向传播所需的backward函数
  1. 实例化MLP类得到模型变量net
  • 代码初始化net并传入输入数据 X 做一次前向运算
  • 其中net(X)会调用MLP集成自Module类的call函数,这个函数将调用MLP类定义的forward函数来完成前向计算
X = torch.rand(2, 784)
net = MLP()
print(net)
net(X)
MLP(
	(hidden): Linear(in_features=784, out_features=256, bias=True)
    (act): ReLU()
    (output): Linear(in_features=256, out_features=10, bias=True)
)
tensor([[ 0.0149, -0.2641, -0.0040,  0.0945, -0.1277, -0.0092,  0.0343,  0.0627,
         -0.1742,  0.1866],
        [ 0.0738, -0.1409,  0.0790,  0.0597, -0.1572,  0.0479, -0.0519,  0.0211,
         -0.1435,  0.1958]], grad_fn=<AddmmBackward>)
  • 注意:这里并未将Module类命名为层或者模型之类的名字,因为该类是一个可自由组建的部件,子类既可以是一个层(如PyTorch提供的Linear类),又可以是一个模型(如这里定义的 MLP 类),或者是模型的⼀个部分

2.3.2 层结构基本介绍

  • 可以使用torch.nn包来构建神经网络。nn包依赖autograd包来定义模型并对它们求导。一个nn.Module包含各个层和一个forward(input)方法,该方法返回output
1)不含模型参数的层
  1. 下面构造的MyLayer类通过继承Module类自定义一个将输入减掉均值后输出的层,并将层的计算定义在forward函数里,这个层不含模型参数
import torch
from torch import nn

class MyLayer(nn.Module):
    def __init__(self, **kwargs):
        super(MyLayer, self).__init__(**kwargs)
    def forward(self, x):
        return x - x.mean()  
  1. 测试,实例化该层,然后做前向计算
layer = MyLayer()
layer(torch.tensor([1, 2, 3, 4, 5]))
  • 输出
tensor([-2., -1., 0., 1., 2.])
2)含模型参数的层
  1. 如果一个 Tensor 是 Parameter ,会自动被添加到模型的参数列表里。所以在自定义含模型参数的层时,我们应该将参数定义成 Parameter ,除了直接定义成 Parameter 类外,还可以使用 ParameterList 和 ParameterDict 分别定义参数的列表和字典
class MyListDense(nn.Module):
    def __init__(self):
        super(MyListDense, self).__init__()
        self.params = nn.ParameterList([nn.Parameter(torch.randn(4, 4)) for i in range(3)])
        self.params.append(nn.Parameter(torch.randn(4, 1)))

    def forward(self, x):
        for i in range(len(self.params)):
            x = torch.mm(x, self.params[i])
        return x
net = MyListDense()
print(net)
class MyDictDense(nn.Module):
    def __init__(self):
        super(MyDictDense, self).__init__()
        self.params = nn.ParameterDict({
   
                'linear1': nn.Parameter(torch.randn(4, 4)),
                'linear2': nn.Parameter(torch.randn(4, 1))
        })
        self.params.update({
   'linear3': nn.Parameter(torch.randn(4, 2))}) #新增

    def forward(self, x, choice='linear1'):
        return torch.mm(x, self.params[choice])

net = MyDictDense()
print(net)
3)卷积层
  • 二维卷积层将输入和卷积核做互相关运算,并加上一个标量偏差来得到输出。模型参数包括卷积核和标量偏差。在训练模型时,通常先对卷积核随机初始化,然后不断迭代卷积核和偏差。

​ (1)注意卷积的计算方式方法,如何设置相应的参数

​ (2)步长和填充会影响最终输出特征图的尺寸

​ (3)特征图的计算公式:包含/不包含膨胀率

a. 原理
  1. 分类
  • 离散
  • 连续
  1. 实例
    在这里插入图片描述
  • 卷积核在数字图像上依次由左至右、由上至下滑动,将每次滑动的行数和列数称为步幅
  • 取与卷积核大小相等的区域
  • 逐像素相乘后再做加法运算
b. 代码
  1. 示例
#—————— 创建一个高和宽为3的二维卷积层,然后设输⼊高和宽两侧的填充数分别为1。给定一个高和宽为8的输入,我们发现输出的高和宽也是8 ——————#
import torch
from torch import nn

#定义一个函数来计算卷积层。它对输入和输出做相应的升维和降维
def comp_conv2d(conv2d, X):
    # (1, 1)代表批量大小和通道数
    X = X.view((1, 1) + X.shape)
    Y = conv2d(X)
    return Y.view(Y.shape[2:])  #排除不关心的前两维:批量和通道

# 注意这里是两侧分别填充1行或列,所以在两侧一共填充2行或列
conv2d = nn.Conv2d(in_channels=1, out_channels=1, kernel_size=3,padding=1)

X = torch.rand(8, 8)
comp_conv2d(conv2d, X).shape


#—————— 更常见的卷积层写法 ——————#
import torch.nn as nn
conv_layer = nn.Conv2d(in_channels, out_channels,
                       kernel_size, stride=1,
                       padding=0, dilation=1,
                       groups=1, bias=True)
  • 最基本的层结构指令:nn.Conv2d
  • 具体参数包括输入通道、输出通道、卷积核、步长、膨胀率、组卷积、偏置
  1. 当卷积核的高和宽不同时,可以通过设置高和宽上不同的填充数使输出和输入具有相同的高和宽
# 使用高为5、宽为3的卷积核。在高和宽两侧的填充数分别为2和1
conv2d = nn.Conv2d(in_channels=1, out_channels=1, kernel_size=(5, 3), padding=(2, 1))
comp_conv2d(conv2d, X).shape
c. 如何计算输出特征图的大小
  1. 假设当前图像的大小为:Hin,Win
  2. 假设卷积核大小为FH、FW、个数为FN
  3. 填充数(padding)为P,可以增加输出的高和宽,常用来使输出与输入具有相同的高和宽
  4. 步距(stride)为S,可以减小输出的高和宽
  5. 输出图像的大小为:Hout,Wout
  6. 输出图像的维度为:(FN,Hout,Wout)
  7. 其中Paddding如果取VALID模式,则p=0;如果取SAME,则p>0
  8. 不带有扩充卷积的公式1: H o u t = H i n + 2 P − F h S + 1 H_{out}=\frac{H_{in}+2P-Fh}{S}+1 Hout=SHin+2PFh+1
  9. 带有扩充卷积D(膨胀率≠0): H o = H i + 2 P − D ( F h − 1 ) − 1 S + 1 Ho=\frac{Hi+2P-D(Fh-1)-1}{S}+1 Ho=SHi+2PD(Fh1)1+1
4)反卷积

​ 反卷积是卷积的反向操作,pytorch中有两种反卷积方法
在这里插入图片描述

a. 双线性插值上采样

​ 先获知四个顶点,再根据计算公式进行插值处理

  1. 公式

Q 11 = ( x 1 , y 1 ) , Q 12 = ( x 1 , y 2 ) Q_{11}=\left(x_{1}, y_{1}\right), \quad Q_{12}=\left(x_{1}, y_{2}\right)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值