1. 卷积网络的基本组件(卷积网络、BatchNorm、ReLU、卷积三兄弟、线性层、Dropout)

1. 卷积网络

import torch
from torch import nn
# 二维卷积
'''
    [N,C,H,W] :批量数,通道数,高度,宽度
    in_channels: int,输入图像的通道数
    out_channels: int,输出图像的通道数
    kernel_size: Union[int, Tuple[int, int]],卷积核
    stride: Union[int, Tuple[int, int]] = 1,步长
    padding: Union[str, int, Tuple[int, int]] = 0,补零
    dilation: Union[int, Tuple[int, int]] = 1,膨胀卷积/空洞卷积
    groups: int = 1,分组卷积
    bias: bool = True,偏置
    padding_mode: str = 'zeros',填充模式
    device=None,设备
    dtype=None,数据类型 默认:torch.float32
'''
conv1 = nn.Conv2d(in_channels=3, out_channels=16,kernel_size=3, stride=1,padding=1)
X = torch.randn(1,3,64,64)
print(conv1(X).shape)  # :   torch.Size([1, 16, 64, 64])

2. BatchNorm组件

  • Batch:批量
  • Norm:规范化
  • x ˉ = ( x − μ ) / σ \bar x = (x - \mu) / \sigma xˉ=(xμ)/σ
  • BatchNorm 中的均值和标准差都是当前批的,所以一批样本的个数不能为1,否则计算均值和标准差就没有意义了。
  • 按照常理来讲,推理的数据要和训练数据做一模一样的处理,BatchNorm 训练时使用的是当前批样本的均值和标准差进行计算,但是推理时样本数量为1,这要怎样来处理呢?
  • 实际上,BatchNorm 内部做了如下处理:在训练时,默默记录每一批样本的均值和标准差,最终估算一个合适的值给推理使用。
  • 我们不得不承认这是一个天才的想法,但是这个做法也给我们带来了麻烦,那就是它直接导致了训练和推理的行为不一致而层产生的两种模式:train模式eval模式
    在这里插入图片描述
# 每一层看作一个特征
bn = nn.BatchNorm2d(num_features=16)
print(bn.weight.shape,bn.bias.shape)  # : torch.Size([16]) torch.Size([16])

3. ReLU层

def relu(x):
    """
        修正线性激活单元
    """
    x[x<0]=0
    return x
X= torch.randn(2,6)
print(X)
print(relu(X))  # 自己写的ReLU
print(torch.relu(X))  # torch自带的ReLU

tensor([[-0.1721, -1.8191, -1.1624, 0.6398, 1.6384, -1.0803],
[-0.9440, -2.1701, -1.5298, -0.5117, -0.8510, -0.8240]])

tensor([[0.0000, 0.0000, 0.0000, 0.6398, 1.6384, 0.0000],
[0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000]])

tensor([[0.0000, 0.0000, 0.0000, 0.6398, 1.6384, 0.0000],
[0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 0.0000]])

4. 卷积三兄弟

  • 卷积三兄弟:
    • 卷积层
    • 批规范化层
    • 激活层
class ConvBlock(nn.Module):
    """
        一层卷积:
            - 卷积层
            - 批规范化层
            - 激活层
    """
    def __init__(self,in_channels,out_channels,
                kernel_size=3,stride=1,padding=1):
        # 初始化子类之前要先初始化父类
        super().__init__()
        self.conv = nn.Conv2d(in_channels=in_channels,out_channels=out_channels,
                             kernel_size=kernel_size,stride=stride,padding=padding)
        self.bn = nn.BatchNorm2d(num_features=out_channels)
        self.relu = nn.ReLU()

    def forward(self, x):
        x = self.conv(x)
        x = self.bn(x)
        x = self.relu(x)
        return x
convblock1  = ConvBlock(in_channels=3, out_channels=16)
X = torch.randn(1,3,64,64)
convblock1(X).shape   # torch.Size([1, 16, 64, 64])

5. 线性层

linear = nn.Linear(in_features=1024,out_features=16)

6. Dropout

  • Dropout 就是让神经元随机失活,从而降低全连接神经网络过拟合的风险。
  • 那么随机失活会导致全连接神经网络层发生质的改变吗?并不会,请看下面的公式:
    y = f ( x ) = { 0 p 1 1 − p 1 − p y= f(x) = \left\{ \begin{array}{ll} 0 & \text p \\ \frac{1}{1-p} & \text 1-p \end{array} \right. y=f(x)={01p1p1p
  • p 是概率,通过计算 Dropout 的期望发现,期望与之前一致,所以本质上这个处理不会对结果产生很大影响。
    在这里插入图片描述
dp = nn.Dropout(p=0.5)
X = torch.randn(10)
print('原始数据:',X)
print('默认模式:',dp(X))
dp.eval()
print('eval模式:',dp(X))
dp.train()
print('train模式:',dp(X))

原始数据: tensor([-1.2073, 0.3764, 0.9974, -0.9199, 0.4409, 0.2878, 0.9389, -0.0928, 0.7844, 1.0739])
默认模式: tensor([-0.0000, 0.7528, 0.0000, -0.0000, 0.0000, 0.0000, 1.8777, -0.0000, 1.5689, 0.0000])
eval模式: tensor([-1.2073, 0.3764, 0.9974, -0.9199, 0.4409, 0.2878, 0.9389, -0.0928, 0.7844, 1.0739])
train模式: tensor([-2.4146, 0.7528, 0.0000, -1.8399, 0.8819, 0.5756, 0.0000, -0.0000, 0.0000, 0.0000])

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MechMaster

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值