一文解答Swin Transformer + 代码【详解】
文章目录
- 1、Swin Transformer的介绍
- 1.1 Swin Transformer解决图像问题的挑战
- 1.2 Swin Transformer解决图像问题的方法
- 2、Swin Transformer的具体过程
- 2.1 Patch Partition 和 Linear Embedding
- 2.2 W-MSA、SW-MSA
- 2.3 Swin Transformer代码解析
- 2.3.1 代码解释
- 2.4 W-MSA和SW-MSA的softmax计算
- 2.4.1 代码实现
- 2.5 patch merging 实现过程
- 3、不同Swin Transformer版本的区别
1、Swin Transformer的介绍
下面是Swin Transformer论文的Abstract,
1.1 Swin Transformer解决图像问题的挑战
原论文中的Abstract讲到:Challenges in adapting Transformer from language to vision arise from differences between the two domains, such as large variations in the scale of visual entities and the high resolution of pixels in images compared to words in text。 也就是说在一张图片中,不同的object有不同的尺度,以及与NLP相比,图像处理需要更多的token,下面来看在CNN中是如何解决不同的object有不同的尺度这个问题的,CNN是通过Conv和Pool对特征图中像素的不同感受野来检测不同尺度的物体,如下图所示,
为什么多尺度检测对于Swin Transformer是有挑战性的,请看下图最左边的Transformer结构,当图片的宽高像素是 h × w \sf{h} \times \sf{w} h×w,所以一共有 h × w \sf{h} \times \sf{w} h×w 个token,输入给Transformer时,输出也是 h × w \sf{h} \times \sf{w} h×w ,所以Transformer并没有做下采样操作,下图中间的是ViT的结构,下图最右边的是Swin Transformer结构,MSA是multi-head self-attention的缩写,
1.2 Swin Transformer解决图像问题的方法
Swin Transformer如何解决相比NLP中更多的token呢,Swin Transformer提出了hierarchical Transformer,hierarchical Transformer是由shifted windows计算出来的,
下面是MSA,W-MSA,SW-MSA的示意图, 如果对于MSA处理56x56个像素的图片,需要计算 313 6 2 3136^2 31362次的相似度,计算量较大;W-MSA将56x56个像素分割成8x8个windows,每个windows由7x7个像素组成,每个windows单独计算MSA,作用是减少计算量,缺点是windows之间没有信息交互,计算相似度为;SW-MSA可以解决windows之间没有信息交互的问题,例如下图最右边的示例,把一个8x8的图片的分成4个windows,然后分割grid向右下角移动 window // 2,这样分割的windows就可以包含多个windows之间的信息,
如下图中最左边部分的1,2,3包含多个windows的信息,
下图黄色虚线框标记的是Swin Transformer处理模块,每次经过Swin Transformer模块,patch Merging使特征层减少一半,通道数增加一倍,
与ViT特征层不变不同,每次经过Swin Transformer模块,特征层减少一半,通道数增加一倍,
2、Swin Transformer的具体过程
2.1 Patch Partition 和 Linear Embedding
如下图,黄色虚线框的作用是下采样,
将224x224x3的特征图中的4x4x3的像素patch成1个token,然后通过concat操作,就得到了4x4x3=48个特征维度,把这个48个维度的向量看成一个token,所以224x224x3的特征图有56x56个token,每个token的特征维度是48,再经过一个映射把48个维度映射成96个维度,如下图所示,
Patch Partition 和 Linear Embedding在上面的示意图上是2个步骤,但是在代码中却是一步完成的,如下代码中的self.proj,
2.2 W-MSA、SW-MSA
如下图,2个连续的swin transformer结构与ViT的结构只有W-MSA、SW-MSA和MSA的区别,其他的MLP、Norm结构都相同,
下面是MSA和W-MSA的示意图,相较于MSA,W-MSA计算量较小,但是windows之间没有信息交互,
下面是SW-MSA的示意图,SW-MSA采用新的 window 划分方式,将 windows 向右下角移动 window size // 2,移动之后会发现windows的大小不一样,先把A+B向右移动,然后A+C再向下移动就解决了windows的大小不一样的问题,这样就可以并行地计算SW-MSA了,
需要注意到,移动之后每个window的像素并不是连续的,如何解决这个问题,请看下面的解释,
如下图,0作为query,其本身和其他window内的数字作为k,示意图中矩形框表示0和移动的像素的乘积,这个乘积再作 − 100 -100 −100计算,取softmax之后,值就接近于0了,
计算完成之后,再把移动之后的像素还原,
W-MSA、SW-MSA与MSA的不同还在于softmax的计算方式,W-MSA、SW-MSA与MSA的不同有W-MSA、SW-MSA是在softmax里面加入相对位置偏置,MSA是在输入加入位置编码,
2.3 Swin Transformer代码解析
代码:
class SwinTransformerBlock(nn.Module):r""" Swin Transformer Block.Args:dim (int): Number of input channels.num_heads (int): Number of attention heads.window_size (int): Window size.shift_size (int): Shift size for SW-MSA.mlp_ratio (float): Ratio of mlp hidden dim to embedding dim.qkv_bias (bool, optional): If True, add a learnable bias to query, key, value. Default: Truedrop (float, optional): Dropout rate. Default: 0.0attn_drop (float, optional): Attention dropout rate. Default: 0.0drop_path (float, optional): Stochastic depth rate. Default: 0.0act_layer (nn.Module, optional): Activation layer. Default: nn.GELUnorm_layer (nn.Module, optional): Normalization layer. Default: nn.LayerNorm"""def __init__(self, dim, input_resolution, num_heads, window_size=7, shift_size=0,mlp_ratio=4., qkv_bias=True, drop=0., attn_drop=0., drop_path=0.,act_layer=nn.GELU, norm_layer=nn.LayerNorm):super().__init__()self.dim = dimself.input_resolution = input_resolutionself.num_heads = num_headsself.window_size = window_sizeself.shift_size = shift_sizeself.mlp_ratio = mlp_ratioassert 0 <= self.shift_size < self.window_size, "shift_size must in 0-window_size"self.norm1 = norm_layer(dim)self.attn = WindowAttention(dim, window_size=(self.window_size, self.window_size), num_heads=num_heads,qkv_bias=qkv_bias, attn_drop=attn_drop, proj_drop=drop)self.drop_path = DropPath(drop_path) if drop_path > 0. else nn.Identity()self.norm2 = norm_layer(dim)mlp_hidden_dim = int(dim * mlp_ratio)self.mlp = Mlp(in_features=dim, hidden_features=mlp_hidden_dim, act_layer=act_layer, drop=drop)if self.shift_size > 0:# calculate attention mask for SW-MSAH, W = self.input_resolutionimg_mask = torch.zeros((1, H, W, 1)) # 1 H W 1h_slices = (slice(0, -self.window_size),slice(-self.window_size, -self.shift_size),slice(-self.shift_size, None))w_slices = (slice(0, -self.window_size),slice(-self.window_size, -self.shift_size),slice(-self.shift_size, None))cnt = 0for h in h_slices:for w in w_slices:img_mask[:, h, w, :] = cntcnt += 1mask_windows = window_partition(img_mask, self.window_size) # nW, window_size, window_size, 1mask_windows = mask_windows.view(-1, self.window_size * self.window_size)attn_mask = mask_windows.unsqueeze(1) - mask_windows.unsqueeze(2)attn_mask = attn_mask.masked_fill(attn_mask != 0, float(-100.0)).masked_fill(attn_mask == 0, float(0.0))else:attn_mask = Noneself.register_buffer("attn_mask", attn_mask)def forward(self, x):H, W = self.input_resolutionB, L, C = x.shapeassert L == H * W, "input feature has wrong size"shortcut = xx = self.norm1(x)x = x.view(B, H, W, C)# cyclic shiftif self.shift_size > 0:shifted_x = torch.roll(x, shifts=(-self.shift_size, -self.shift_size), dims=(1, 2))else:shifted_x = x# partition windowsx_windows = window_partition(shifted_x, self.window_size) # [nW*B, Mh, Mw, C]x_windows = x_windows.view(-1, self.window_size * self.window_size, C) # [nW*B, Mh*Mw, C]# W-MSA/SW-MSAattn_windows = self.attn(x_windows, mask=self.attn_mask) # [nW*B, Mh*Mw, C]# merge windowsattn_windows = attn_windows.view(-1, self.window_size, self.window_size, C) # [nW*B, Mh, Mw, C]shifted_x = window_reverse(attn_windows, self.window_size, H, W) # [B, H', W', C]# reverse cyclic shiftif self.shift_size > 0:x = torch.roll(shifted_x, shifts=(self.shift_size, self.shift_size), dims=(1, 2))else:x = shifted_xx = x.view(B, H * W, C)x = shortcut + self.drop_path(x)# FFNx = x + self.drop_path(self.mlp(self.norm2(x)))return x
2.3.1 代码解释
代码解释:
接上面的代码:
window_partition函数:
window_reverse函数:
MLP函数:
2.4 W-MSA和SW-MSA的softmax计算
W-MSA和SW-MSA的softmax计算分为2个步骤,
对于window size为2的矩阵,计算其relative position index矩阵,矩阵大小为 w i n d o w s i z e 2 \sf{windowsize}^2 windowsize2 x w i n d o w s i z e 2 \sf{windowsize}^2 windowsize2,relative position index矩阵的size和相似度矩阵的size一致,计算结果不用赘述,很容易看出来,相对位置的矩阵size是 2 M − 1 \sf{2M-1} 2M−1 x 2 M − 1 \sf{2M-1} 2M−1
relative position bias matrix是一个可学习的参数,是依照相对位置的所有组合方式而来, relative position bias B 的值来自 relative position bias matrix B ^ \sf{\hat{B}} B^ 的值,
2.4.1 代码实现
因为2维矩阵需要考虑2个维度的值,不方便计算,所以把2维坐标转为1维坐标,计算过程如下,
代码以及代码解释:
下图右边的代码假设window size为7,
2.5 patch merging 实现过程
patch merging在swin transformer中的位置如下,
patch merging的实现过程如下图,原来的像素在每隔1个像素组合,经过concat和LayerNorm以及Linear层之后size减倍,channel数加倍,
代码:
3、不同Swin Transformer版本的区别
区别在于stage1的channel数,stage3的Swin Transformer计算的次数,
参考:
1、原论文:https://arxiv.org/pdf/2103.14030
2、哔哩哔哩:https://www.bilibili.com/video/BV1xF41197E4/?p=6&spm_id_from=pageDriver
相关文章:

一文解答Swin Transformer + 代码【详解】
文章目录 1、Swin Transformer的介绍1.1 Swin Transformer解决图像问题的挑战1.2 Swin Transformer解决图像问题的方法 2、Swin Transformer的具体过程2.1 Patch Partition 和 Linear Embedding2.2 W-MSA、SW-MSA2.3 Swin Transformer代码解析2.3.1 代码解释 2.4 W-MSA和SW-MSA…...

Vue3:<Teleport>传送门组件的使用和注意事项
你好,我是沐爸,欢迎点赞、收藏、评论和关注。 Vue3 引入了一个新的内置组件 <Teleport>,它允许你将子组件树渲染到 DOM 中的另一个位置,而不是在父组件的模板中直接渲染。这对于需要跳出当前组件的 DOM 层级结构进行渲染的…...

项目之家:又一家项目信息发布合作对接及一手接单平台
这几天“小三劝退师时薪700”的消息甚嚣尘上,只能说从某一侧面来看心理咨询师这个职业的前景还是可以的,有兴趣的朋友可以关注下。话说上一篇文章给大家介绍了U客直谈,今天趁热打铁再给大家分享一个地推拉新项目合作平台~项目之家:…...

02-java实习工作一个多月-经历分享
一、描述一下最近不写博客的原因 离我发java实习的工作的第一天的博客已经过去了一个多月了,本来还没入职的情况是打算每天工作都要写一份博客来记录一下的(最坏的情况也是每周至少总结一下的),其实这个第一天的博客都是在公司快…...

JVM 调优篇2 jvm的内存结构以及堆栈参数设置与查看
一 jvm的内存模型 2.1 jvm内存模型概览 二 实操案例 2.1 设置和查看栈大小 1.代码 /*** 演示栈中的异常:StackOverflowError** author shkstart* create 2020 下午 9:08** 设置栈的大小: -Xss (-XX:ThreadStackSize)** -XX:PrintFlagsFinal*/ public class S…...

微信可以设置自动回复吗?
在日常的微信聊天中,我们或许会频繁地遭遇客户提出的相同问题,尤其是对于从事销售工作的朋友们来说,客户在添加好友后的第一句话往往是“在吗”或者“你好”。当我们的好友数量众多时,手动逐个回复可能会耗费大量的时间。因此&…...

同样数据源走RTMP播放延迟低还是RTSP低?
背景 在比较同一个数据源,是RTMP播放延迟低还是RTSP延迟低之前,我们先看看RTMP和RTSP的区别,我们知道,RTMP(Real-Time Messaging Protocol)和RTSP(Real Time Streaming Protocol)是…...

@开发者极客们,网易2024低代码大赛来啦
极客们,网易云信拍了拍你 9月6日起,2024网易低代码大赛正式开启啦! 低代码大赛是由网易主办的权威赛事,鼓励开发者们用低代码开发的方式快速搭建应用,并最终以作品决出优胜。 从2022年11月起,网易低代码大赛…...

数据分析-16-时间序列分析的常用模型
1 什么是时间序列 时间序列是一组按时间顺序排列的数据点的集合,通常以固定的时间间隔进行观测。这些数据点可以是按小时、天、月甚至年进行采样的。时间序列在许多领域中都有广泛应用,例如金融、经济学、气象学和工程等。 时间序列的分析可以帮助我们理解和预测未来的趋势和…...

SpringMVC使用:类型转换数据格式化数据验证
01-类型转换器 先在pom.xml里面导入依赖,一个是mvc框架的依赖,一个是junit依赖 然后在web.xml里面导入以下配置(配置的详细说明和用法我在前面文章中有写到) 创建此测试类的方法用于测试springmvc是具备自动类型转换功能的 user属…...

多语言ASO – 本地化的10个技巧
ASO优化是一个复杂的领域,即使你只关注讲英语的用户。如果您想面向国际受众并在全球范围内发展您的应用程序业务,您必须在App Store和Google Play Store上本地化应用程序的产品页面。不过,应用程序商店本地化的过程也有很多陷阱。 应用商店本…...

C程序设计——函数0
函数定义 前面说过C语言是结构化的程序设计语言,他把所有问题抽象为数据和对数据的操作,前面讲的变量、常量,都是数据。现在开始讲对数据操作——函数。 C语言的函数,定义方式如下: 返回值类型 函数名(参数列表) {…...

第二十一章 rust与动静态库的结合使用
注意 本系列文章已升级、转移至我的自建站点中,本章原文为:rust与动静态库的结合使用 目录 注意一、前言二、库生成三、库使用四、总结一、前言 rust中多了很多类型的库,比如前面章节中我们提到基本的bin与lib这两种crate类型库。 如果你在命令行执行下列语句: rustc -…...

修改服务器DNS解析及修改自动对时时区
修改服务器DNS解析: 1、搜索一下当地的DNS服务器的地址 2、登录服务器,执行 vim /etc/resolv.conf文件,在nameserver字段后填写DNS服务的地址 3、chattr i /etc/resolv.conf 加上不可修改权限,防止重启DNS被修改 修改自动对时…...

中科院TOP“灌水神刊”合集!盘点那些“又牛又水”的国人友好SCI
【SciencePub学术】本期,小编给大家推荐几本“又牛又水”的期刊,并且都是清一色的国人友好刊,涵盖各领域,以供各位学者参考! NO.1 Nature Communications IF:14.7 分区:JCR1区中科院1区TOP 年…...

Python列表浅拷贝的陷阱与破解之道
引言 在Python编程世界中,列表的拷贝操作看似简单,却常常隐藏着一些令人意想不到的陷阱,尤其是当涉及到浅拷贝时。今天,我们将深入探讨Python列表浅拷贝现象及产生原因,并提供有效的解决方案,帮助你写出更…...

开放式系统互连(OSI)模型的实际意义
0 前言 开放式系统互连(OSI,Open Systems Interconnection)模型,由国际标准化组织(ISO)在1984年提出,目的是为了促进不同厂商生产的网络设备之间的互操作性。 定义了一种在层之间进行协议实现…...

回溯——10.全排列 II
力扣题目链接 给定一个可包含重复数字的序列 nums ,按任意顺序 返回所有不重复的全排列。 示例 1: 输入:nums [1,1,2]输出: [[1,1,2], [1,2,1], [2,1,1]] 解题思路: 排序:首先对数组进行排序…...

基于百度AIStudio飞桨paddleRS-develop版道路模型开发训练
基于百度AIStudio飞桨paddleRS-develop版道路模型开发训练 参考地址:https://aistudio.baidu.com/projectdetail/8271882 基于python35paddle120env环境 预测可视化结果: (一)安装环境: 先上传本地下载的源代码Pad…...

【 C++ 】C/C++内存管理
前言: 😘我的主页:OMGmyhair-CSDN博客 目录 一、C/C内存分布 二、C语言中动态内存管理方式:malloc/calloc/realloc/free malloc: calloc: realloc: free: 三、C内存管理方式…...

智能客服的演变:从传统到向量数据库的新时代
国产数据库的发展在21世纪初取得了显著的进展。根据不完全统计,目前在国内已有超过300种不同的数据库在案。这一现象在40年前几乎是不可想象的,标志着中国在数据库领域取得了巨大的突破和多样化选择。对于对老一辈的故事或数据库发展史充满兴趣的朋友们&…...

python使用超级鹰识别验证码
1.超级鹰注册 超级鹰: https://www.chaojiying.com/ 注册后购买题分 2.获取要识别的图片 我们以这个附件下载的网页为例: https://gh.lnut.edu.cn/system/_content/download.jsp?urltypenews.DownloadAttachUrl&owner1224556702&wbfileid1504223 点开f12然后刷新几…...

基于YOLO目标检测实现表情识别(结合计算机视觉与深度学习的创新应用)
基于YOLO(You Only Look Once)的目标检测技术实现的表情识别项目是一个结合了计算机视觉与深度学习的创新应用。该项目旨在通过分析人脸图像或视频流中的面部特征来识别七种基本人类情感表达:愤怒(Angry)、厌恶&#x…...

Keil导入包出错
1.菜单栏找不到GD系列? 随便新建一个工程,将project用记事本打开后如图2所示。再将别人给的代码工程用记事本打开,发现别人给的工程少了这两行,所以复制粘贴到别人给的工程记事本中,保存刷新后重新打开,就…...

超声波自动气象站
超声波自动气象站的功能优势可以包括以下几个方面: 高精度测量:超声波自动气象站采用超声波技术进行测量,可以实现高精度的测量结果,能够准确地测量气温、湿度、风速、风向等气象参数。 高可靠性:超声波自动气象站采用…...

Mysql事件操作
查看是否开启事件 SELECT event_scheduler; SHOW VARIABLES LIKE %event_scheduler%; 开启或关闭事件 SET GLOBAL event_scheduler 1; SET GLOBAL event_scheduler on; SET GLOBAL event_scheduler 0; SET GLOBAL event_scheduler off; 创建事件sql CREATE EVENT IF…...

Python必知必会:程序员必须知道的22个Python单行代码!
今天给大家分享24个每个Python程序员都必须知道的单行代码,帮你写出更简洁、更优雅、更高效的代码。 1. 列表推导式 列表推导式(List Comprehensions)可以提供一种简洁的方式创建列表。相较于传统的循环,列表推导式更高效、可读…...

MongoDB 的适用场景
MongoDB 的适用场景 MongoDB 是一种基于文档存储的 NoSQL 数据库,与传统的关系型数据库不同,它使用 JSON 类似的二进制文档格式(BSON)来存储数据,并且具备灵活的文档模型、强大的查询能力和水平扩展性。这些特性使得 …...

汽车EDI:montaplast EDI对接
Montaplast 是一家总部位于德国的全球知名汽车零部件供应商,专注于高精度塑料部件的设计、开发和生产。公司成立于1958年,主要为汽车行业提供轻量化、高性能的塑料解决方案。Montaplast 以其在注塑成型技术、表面处理和装配技术方面的专业能力而著称&…...

【idea】设置文件模板
搜索 File and Code Templates 。 添加模板。 在任意文件目录下右键,new->找到添加的模板。 参考链接: IDEA创建模板文件_edit file templates-CSDN博客...