【Python/Pytorch - 网络模型】-- 手把手搭建Swin-Transformer模型 - MLP模型

在这里插入图片描述
文章目录

写在前面

根据博主文章,学习Transformer、Vit、SwinTransformer、SwinUnetr原理,原理博主文章已讲解较为详细,本文主要从代码角度学习各个模块的原理。

图解Vit 1:Vision Transformer——图像与Transformer基础 - 知乎
图解Vit 2:Vision Transformer——视觉问题中的注意力机制 - 知乎
图解Vit 3:Vision Transformer——ViT模型全流程拆解(Layer Normalization, Position Embedding) - 知乎
图解+代码 Swin Transformer 1: W-MSA和Patch Merging - 知乎
图解+代码 Swin Transformer 2: SW-MSA(Shifted Window Multi-head Self Attention) - 知乎

MLP模块

# Copyright (c) MONAI Consortium
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#     http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

from __future__ import annotations

import torch.nn as nn

from monai.networks.layers import get_act_layer
from monai.utils import look_up_option

SUPPORTED_DROPOUT_MODE = {"vit", "swin"}


class MLPBlock(nn.Module):
    """
    A multi-layer perceptron block, based on: "Dosovitskiy et al.,
    An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale <https://arxiv.org/abs/2010.11929>"
    """

    def __init__(
        self, hidden_size: int, mlp_dim: int, dropout_rate: float = 0.0, act: tuple | str = "GELU", dropout_mode="vit"
    ) -> None:
        """
        Args:
            hidden_size: dimension of hidden layer.
            mlp_dim: dimension of feedforward layer. If 0, `hidden_size` will be used.
            dropout_rate: fraction of the input units to drop.
            act: activation type and arguments. Defaults to GELU. Also supports "GEGLU" and others.
            dropout_mode: dropout mode, can be "vit" or "swin".
                "vit" mode uses two dropout instances as implemented in
                https://github.com/google-research/vision_transformer/blob/main/vit_jax/models.py#L87
                "swin" corresponds to one instance as implemented in
                https://github.com/microsoft/Swin-Transformer/blob/main/models/swin_mlp.py#L23


        """

        super().__init__()

        if not (0 <= dropout_rate <= 1):
            raise ValueError("dropout_rate should be between 0 and 1.")
        mlp_dim = mlp_dim or hidden_size
        self.linear1 = nn.Linear(hidden_size, mlp_dim) if act != "GEGLU" else nn.Linear(hidden_size, mlp_dim * 2)
        self.linear2 = nn.Linear(mlp_dim, hidden_size)
        self.fn = get_act_layer(act)
        self.drop1 = nn.Dropout(dropout_rate)
        dropout_opt = look_up_option(dropout_mode, SUPPORTED_DROPOUT_MODE)
        if dropout_opt == "vit":
            self.drop2 = nn.Dropout(dropout_rate)
        elif dropout_opt == "swin":
            self.drop2 = self.drop1
        else:
            raise ValueError(f"dropout_mode should be one of {SUPPORTED_DROPOUT_MODE}")

    def forward(self, x):
        x = self.fn(self.linear1(x))
        x = self.drop1(x)
        x = self.linear2(x)
        x = self.drop2(x)
        return x

第一点

class  MLPBlock(nn.Module):
def __init__( ):
super().__init__()

def forward(self, x):
return x

定义了一个MLPBlock类,该类继承父类nn.Module。def init():该函数是该类的构造函数,用于初始化实例。super().init():调用了父类nn.Module的构造函数,确保父类的初始化逻辑被执行。
def forward(self, x) 是该类的核心函数,定义了输入数据如何通过该层进行前向传播。

第二点

self.linear1 = nn.Linear(hidden_size, mlp_dim) if act != "GEGLU" else nn.Linear(hidden_size, mlp_dim * 2)

nn.Linear() 是一个线性层(全连接层),用于将输入张量从一个维度映射到另一个维度。
它有两个参数 in_features:输入张量的特征维度(hidden_size)。out_features:输出张量的特征维度(mlp_dim 或 mlp_dim * 2)。

第三点

self.drop1 = nn.Dropout(dropout_rate)

Dropout 是一种常用的正则化技术,用于防止神经网络的过拟合。其工作原理是:在训练过程中,随机将输入张量中的某些元素设置为零(即“丢弃”这些元素),同时按照比例缩放剩余元素的值。Dropout 能够减少神经元之间的共适应现象,从而提高模型的泛化能力。
nn.Dropout(dropout_rate)是 PyTorch 中的一个类,用于实现 Dropout 层。dropout_rate 是一个浮点数,表示丢弃概率。例如,如果 dropout_rate 设为 0.5,意味着在训练过程中,每个元素有 50% 的概率被丢弃。

更详细的理解:
在训练过程中,Dropout 会随机将输入张量中的某些元素设置为零(即“丢弃”这些元素),同时按照比例缩放剩余元素的值。这有助于减少过拟合,提高模型的泛化能力。以下是对这一过程的更详细解释:

  1. 工作原理
  • 丢弃元素:
  • 在训练时,Dropout 层会随机选择输入张量中的一部分元素,并将它们设置为零。这个过程模拟了神经元的随机失活。
  • 丢弃的概率由 dropout_rate 参数控制。例如,如果 dropout_rate 设为 0.5,则每个元素有 50% 的概率被丢弃。
  • 缩放剩余元素:
  • 被保留下来的元素的值会被放大(缩放),以保持张量的整体期望值不变。缩放因子为 1/(1 - dropout_rate)。
  • 例如,如果 dropout_rate 为 0.5,每个被保留的元素会乘以 2,以补偿丢弃元素所导致的和的减少。
  1. 数学表示假设输入张量为
    x,形状为 [batch_size, num_features],dropout_rate 为 p。Dropout 的输出 y 可以表示为:
    Python复制
    mask = (torch.rand_like(x) > p).float() # 随机生成掩码
    y = x * mask / (1 - p) # 丢弃并缩放
  2. 训练与推理阶段的行为差异
  • 训练阶段:
  • 使用 Dropout,随机丢弃元素,以防止过拟合。
  • 梯度仅通过未被丢弃的元素传播。
  • 推理阶段:
  • Dropout 被关闭,所有元素都被保留,不进行缩放。
  • 这样可以确保输出是稳定的,并且不会丢失信息。
  1. 示例代码以下代码展示了如何在 PyTorch 中使用 Dropout 层:
import torch
import torch.nn as nn

# 创建一个 Dropout 层,丢弃概率为 0.5
dropout = nn.Dropout(p=0.5)

# 输入张量
input_tensor = torch.randn(2, 4)  # 形状为 (2, 4)

# 在训练模式下应用 Dropout
output_tensor = dropout(input_tensor)

print("Input Tensor:")
print(input_tensor)
print("\nOutput Tensor:")
print(output_tensor)
输出示例
Input Tensor:
tensor([[-0.2419,  0.6929,  1.4928, -0.6680],
        [-0.4224, -0.8534, -0.2863,  0.9220]])

Output Tensor:
tensor([[ 0.0000,  1.3858,  2.9856, -0.0000],
        [-0.8448, -0.0000, -0.0000,  1.8440]])
在输出张量中,一些元素被设置为零,而被保留的元素被放大了两倍(因为 p=0.5)。
  1. 作用
  • 减少过拟合:通过随机丢弃神经元,模型无法完全依赖某些特定的神经元,从而提高泛化能力。
  • 增强鲁棒性:模型能够更好地处理输入数据中的噪声和不确定性。

第四点

激活层:激活层是神经网络中不可或缺的组成部分,其主要作用是为神经网络引入非线性。在没有激活层的情况下,神经网络仅由线性变换组成,无论网络有多深,其整体函数仍是一个线性函数。激活层的存在使得神经网络能够学习和表示复杂的非线性模式,从而能够解决复杂的分类和回归问题。
1.ReLU (Rectified Linear Unit)

  • 表达式:f(x)=max(0,x)
  • 作用:将输入张量中的负值置零,保留正值。
  • 优点:计算简单且高效,有助于缓解梯度消失问题,在现代神经网络中广泛应用。
  • 缺点:可能导致一部分神经元“死亡”(即输出始终为零),特别是在训练初期使用较大的学习率时。
  • 适用场景:通常用于卷积神经网络(CNN)和多层感知机(MLP)的隐藏层。

2.Sigmoid

  • 表达式:f(x)=1+e−x1

  • 作用:将输入值压缩到0到1之间,通常用于二分类问题的输出层。

  • 优点:输出具有概率解释性。

  • 缺点:容易导致梯度消失,特别是在深度网络中。

  • 适用场景:主要在输出层用于概率预测。

3.Tanh (Hyperbolic Tangent)

  • 表达式:f(x)=ex+e−xex−e−x

  • 作用:将输入值压缩到-1到1之间。

  • 优点:输出为零均值,有助于中心化数据。

  • 缺点:同样容易导致梯度消失。

  • 适用场景:可用于某些隐藏层或输出需要正负对称的情况。

4.Leaky ReLU

  • 表达式:f(x)=max(αx,x)
  • 作用:解决了ReLU导致的“死亡”神经元问题,通过引入一个小的负斜率。
  • 优点:保留了大部分ReLU的优点,同时避免神经元死亡。
  • 缺点:α的取值需要调整,选择不当可能影响性能。
  • 适用场景:适用于需要避免ReLU问题但仍想保持ReLU高效性的场景。

5.GELU (Gaussian Error Linear Unit)

  • 表达式:f(x)=x⋅Φ(x),其中Φ(x)是高斯分布的累积分布函数。
  • 作用:平滑的激活函数,结合了ReLU的优点,同时减小了梯度波动。
  • 优点:收敛性能较好,能够提供更稳定的学习过程。
  • 缺点:计算量相对较大。
  • 适用场景:适用于各种类型的神经网络,尤其是对稳定性要求较高的场景。

6.Swish

  • 表达式:f(x)=x⋅σ(βx),其中σ是sigmoid函数。
  • 作用:自门控激活函数,非线性且平滑。
  • 优点:提高了模型的泛化能力,表现通常优于ReLU。
  • 缺点:计算量相对较大。
  • 适用场景:在需要更好泛化性能的神经网络中使用。

论文下载

Attention Is All You Need
An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale
Swin Transformer: Hierarchical Vision Transformer using Shifted Windows
Swin UNETR: Swin Transformers for Semantic Segmentation of Brain Tumors in MRI Images
SwinUNETR-V2: Stronger Swin Transformers with Stagewise Convolutions for 3D Medical Image Segmentation

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

电科_银尘

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

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

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

打赏作者

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

抵扣说明:

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

余额充值