Gradient Vanish and
Explosion
CNN
图像可以看作是一个
的矩阵, 每个元素都是图像的一个像素, 表示图像上的一个点.
考虑到图像的通道, 是一个 的三维张量, 其中
为图片的长与宽, 为图像的通道数,
对于彩色图像而言, , 即 RGB
(红绿蓝), 每个像素的每个通道的数值都是 之间的一个整数.
灰度图像只有一个通道, 每个像素的值表示灰度级别, 也是 之间的一个整数.
图像的通道指的是图像中颜色信息的分量.
Convolution &
Convolutional Kernel
卷积核和图像的格式保持一致, 具有长,
宽和通道数 的概念, 且卷积核的通道数与输入数据的通道数需要相等.
常使用的卷积核的尺寸为 .
在将卷积核与图像做卷积操作之前, 需要确定两个参数:
1: padding (填充). 即在原始图像周围填充一圈 0,
得到一张尺寸更大的图片. 这样做是因为卷积操作会缩小原图尺寸,
进行填充后可以保证原图尺寸不变.
2: stride (步长).
步长表示卷积核在图像上滑动的过程中两个卷积核之间的距离,
同样会影响卷积后的图像大小, 上图是 stride=2的情形.
确定 padding 为 且 stride 为
后, 卷积核的尺寸为 , 卷积操作输出的图片的尺寸为 输出通道
取决于卷积核的个数 , 因为每一个 kernel
将图片的3个通道压缩为了一个通道 , 将做过卷积操作得到的图像称为
Feature Maps.
卷积核的三个通道分别与图像的三个通道做卷积,
得到三个矩阵(或者说得到一张通道数为3的新图片),
将三个矩阵对应位置的元素加起来 得到了通道数为1的feature
map, 除此之外, 卷积操作也会有 bias 的存在, 即最终结果再加上 bias.
How to Calculate Convolutional Layer
Size
kernel
相当于 fc, 可以在通道上进行降维.
为什么卷积操作可以提取特征?
卷积操作能够提取的特征包括 边缘/纹理/颜色/形状 等.
怎么做到的呢? 有没有什么本质上的原因?
Max Pooling
池化操作就是将卷积后的图的尺寸进一步缩小并保留原有特征. 思想很简单,
类似于卷积核的滑动, 将固定大小的池化窗口以一定的 stride 滑动,
每个窗口内取最大值作为输出, 得到一个新的图像.
除了 max pooling 还有 average pooling, 但是 max pooling
使用的更多.
Max Pooling
The Whole CNN
整个CNN的结构
原始图片可以经过多次卷积和池化, 当卷积和池化操作完成后,
图片的尺寸大幅度减小, 此时直接将图片 flatten
展平为向量作为全连接层的输入即可.
整个 CNN 在做的就是, 在尽可能保留图像的特征的前提下,
尽可能使图像的尺寸减少, 即特征提取 , 略去冗余无用的信息,
以减少网络的参数的数量, 减少训练时间并降低过拟合的程度.
CNN 学习的参数包括卷积核的权重和全连接层的权重, 除此之外可能还有一些
bias(也是卷积操作过程中或者全连接层的).
CNN with Pytorch
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class Net (nn.Module): def __init__ (self ): super (Net, self).__init__() self.conv1 = nn.Conv2d(3 , 32 , 3 , padding=1 ) self.conv2 = nn.Conv2d(32 , 32 , 3 , padding=1 ) self.conv3 = nn.Conv2d(32 , 64 , 3 , padding=1 ) self.conv4 = nn.Conv2d(64 , 64 , 3 , padding=1 ) self.conv5 = nn.Conv2d(64 , 128 , 3 , padding=1 ) self.conv6 = nn.Conv2d(128 , 128 , 3 , padding=1 ) self.pool = nn.MaxPool2d(2 , 2 ) self.fc1 = nn.Linear(128 * 4 * 4 , 512 ) self.fc2 = nn.Linear(512 , 256 ) self.fc3 = nn.Linear(256 , 10 ) def forward (self, x ): x = F.relu(self.conv1(x)) x = F.relu(self.conv2(x)) x = self.pool(x) x = F.relu(self.conv3(x)) x = F.relu(self.conv4(x)) x = self.pool(x) x = F.relu(self.conv5(x)) x = F.relu(self.conv6(x)) x = self.pool(x) x = x.view(-1 , 128 * 4 * 4 ) x = F.relu(self.fc1(x)) x = F.dropout(x, p=0.5 ) x = F.relu(self.fc2(x)) x = F.dropout(x, p=0.5 ) x = self.fc3(x) return x
ResNet
RNN
Recurrent Neural Network.
Why RNN?
考虑到语言中词汇序列的时序关系 以及上下文 ,
RNN 能够顾及到前面的输入和后面的输入的关系,
同时也能模拟人脑的记忆功能.
The Structure of RNN
RNN结构
本质上是一个简单的有一层隐藏层的全连接神经网络. 设输入向量为 , 隐藏层向量为 , 输出向量为 , 输入层和隐藏层的参数矩阵为 , 激活函数为 , 隐藏层和输出层的参数矩阵为 , 激活函数为 .
考虑到序列模型, 可以让
不只取决于 ,
还与上一个时刻 的
有关, 那么这样输入层/隐藏层/输出层都是时间的序列: ,
设两个时刻之间的隐藏层向量 的参数矩阵为 , 那么
未考虑 bias.
Different Types of RNN
根据输入与输出的数量不同,
RNN的不同种类
不同种类的 RNN 被设计来完成不同的任务:
one2one: 应该不能把这个看作 RNN, 就是普通的神经网络
one2many: 根据一个输入生成句子, 比如输入图片给图片做描述等.
many2one: 根据句子输出一个 label, 比如情感分析.
many2many 位置不对应: 翻译.
many2many 位置一一对应: 将视频的每个帧输出label.
LSTM
Long Short Term Memory.
Why LSTM?
因为 RNN 缺点: 梯度消失或梯度爆炸导致无法处理处理长序列,
或者是相距很远的上下文对应关系.
LSTM 的思想就是选择性记忆, 而不像 RNN 那样不论有没有用都去记忆.
The Structure of LSTM
RNN和LSTM的对比
LSTM 采用了门电路的思想, 设计了 forget gate, input gate 和 output
gate用来控制 input value, memory value 和 output value. 使用 sigmoid
将数值控制在 之间,
对应了门的开闭状态.
每个 cell 中,
表示将两个向量做 Hadamard
product , 用符号 表示,
表示将两个向量做相加操作.
LSTM cell 结构
根据数据的流向, 很容易就能够写出公式: 未考虑 bias.
GRU
Gate Recurrent Unit.
Why GRU?
LSTM 的 cell 引入了三个门, 参数量比较大, GRU 在 LSTM
的基础上进行了简化, 只设计了两个门, update gate 和 reset gate.
The Structure of GRU
LSTM 与 GRU 对比
The difference between LSTM and GRU:
GRU does not possess any internal memory, they don’t have an
output gate that is present in LSTM
In LSTM the input gate and target gate are coupled by an update
gate, and in GRU reset gate is applied directly to the previous hidden
state
In LSTM the responsibility of reset gate is taken by the two
gates i.e., input and target
下面是更清晰的结构:
根据数据流向写出下面的公式: 关于权重矩阵 , wiki
上的版本为 ,
还有版本是, 上文求 的过程中,
用的不是相加操作而是拼接操作, 如下所示:
为什么 RNN
及其变种中采用了激活函数
?
的二阶导不为零的区间较大,
改善了梯度消失的问题, 收敛快, 且计算开销小.
Ref machine
learning - What is the intuition of using tanh in LSTM? - Stack
Overflow
Transformer 是 encoder-decoder 架构, 包括 6个 encoding blocks 以及 6
个 decoder blocks.
每一个 encoder block 由 Multi-Head Attention 与 Feed Forward
(前馈神经网络) 模块组成, 即 其中 FFN 是一个两层的有 ReLU 激活函数的 MLP, 即 .
在 decoder block 中有两个 attention 模块, 分别为处理 target 的
Multi-Head Attention 以及共同处理 encoder 和 decoder 的 Encoder-Decoder
Attention, 如下图所示:
即先由
输入到 Multi-Head Attention 中得到的输出 作为 Encoder-Decoder Attention 的
Query 矩阵 , 再从经过 6 层 encoder
的输出 中得到
Encoder-Decoder Attention 输入需要的 Value 和 Key 矩阵 .
需要注意的是, 不论是 encoder 还是 decoder, 都有残差连接出现,
一般是在每个 MSA 块或者是 FFN 块后用残差连接, 从Transformer 中的 '&' can not be used here \boxed{\text{Add & Norm}}
中就能看出来.
Self-Attention and
Multi-head Attention
对于输入 , self-attention
模块首先需要三个权重参数(线性变换) , 作用在 上得到三个矩阵 为 作为 self-attention
模块的输入, 这一步可以看作是在捕捉 的全局信息. 设 self-attention
模块的输出为 ,
称为一个"头", 按照上图的流程, 则有
其中除以 就是图片中的
Scale 部分, Mask 部分是 optional 的.
Multi-Head Attention 就是将多个 self-attention 并行地组合在一起,
但是将 输入到每个
self-attention 模块之前需要先做一次线性变换, 然后得到多个输出 ,
然后 ,
注意该拼接是在空间上的拼接, 不是 channel 上的拼接,
拼接之后再做线性变换恢复 的形状, 那么 其中 ,
为输出时的权重矩阵.
Multi-Head-Self-Attention 简称 MSA.
神经网络的输入总是一个向量, 对于不同形式的“自然语言”,
可以通过如下处理来使其变为向量:
声音: 使用可重叠的滑窗 在一段声音中不断滑动,
获取若干元素形成一个向量, 比如可以让 25ms 为一个帧, 每两个帧的开始时间隔
10ms.
问题: 每个滑窗内的声音信号是如何变成向量的一个元素的?
文本数据.
使用 one-hot
encoding (独热编码) , 设有 个单词, 则用向量 第 个
表示第 个单词. 这种方法比较简单,
但是缺点很明显: 维度灾难 (当单词数目非常多的时候,
向量的维度就会非常大,
数据形成的矩阵相当稀疏)和语义鸿沟 (不同单词之间没有显著的差异,
无法进行相似度计算).
Word Embedding
(词嵌入) : 将每个单词或词组映射为低维空间上的向量,
对于语义相近的单词, 可以通过距离来衡量其相似程度, 两种主流的 word
embedding 算法是 word2vec 和 GloVe. 如下图所示:
使用滑窗的缺点是无法顾及整体, 也就是可能无法考虑到上下文的影响,
因此引入 self-attention.
Positional Embedding
这篇文章 对
ViT 介绍得十分详细. (好吧看评论区好像就是翻译了原文)
ViT 的结构如上, 只用了 Transformer 的 Encoder 部分,
主要需要设计的实际上是如何将图片编码为序列, 网络的核心部分与 Transformer
的 Encoder 部分并无大的改动.
设输入图片的尺寸为 ,
将其分成固定大小的 patch, 设每个 patch 的尺寸为 , 并将每个 patch 都展平, 得到形状为
的序列, 序列的长度为 , 是 ViT 的有效输入序列长度.
接着再进行 Linear Projection of Flattened Patches, 这一步是将维度为
的向量映射为更低的维度.
上面这一过程称为 Patch Embedding, 除此之外还需要 Positional
Embedding, 用来保留输入的图像的 patches 之间的空间位置信息. 上述公式中:
得到的
就是将图像分成 patch 展平进行 embedding 并且加上了 positional embedding
vector ,
对每个 patch
展平后的向量进行线性变换得到
维的向量.
经过嵌入后,
是依次对序列中的每个向量进行自注意力, 同时加上残差连接, 且要先对 进行 Layer
Normalization.
经过自注意力后, 再输入到 MLP 中 (两层加激活函数 GELU),
同时也要加上残差连接.
最后进行Layer Normalization得到最终的输出.
Restromer
Architecture of Restormer
Swin Transformer 是一种包含滑窗操作, 具有层级设计的架构.
如上图所示, Swin T 包括 4 个 stage, 除了第一个 stage 是由 Linear
Embedding 和 Swin-T Block 组成的之外, 后三个 stage 都是由
组成的.
最初, 形状为
的图片输入后先经过 Patch Partition 分窗(以分成 16
个窗口为例)在通道上拼接得到形状为 的 feature map. 在 stage 1
通过 Linear Embedding 做线性变换调整通道数为 , 此后每通过一个 stage, Patch Merging
起到下采样的作用使得 feature map
的通道数加倍而图像尺寸缩小为原来的一半.
Swin Tansformer 的核心设计就是 Swin-T Block, 而每一个这样的 Block
中的核心设计是 W-MSA 和 SW-MSA. Swin-T Block 的计算如下: 其中
表示第 个块的 (S)W-MSA
模块的输出的 feature,
表示第 个块的 MLP 模块的输出的
feature, 其中仍然有跳跃连接.
W-MSA 指 Window-based Multi-head Self Attention.
不同于标准Transformer的全局自注意力,我们在非重叠局部窗口执行自注意力,这种方式可以有效降低计算量.
对于形状为 的输入 , 将其分为 个大小为 的互不重叠的 window,
并对其进行展平得到形状为 的
, 第 个头的自注意力就是分别对每一个 window
展平后的向量进行 self-attention 再 concat 在一起, 即 SW-MSA 在 W-MSA 分窗的基础之上对窗口进行了左右和上下平移,
如下图所示:
此时总的 window 数目大小实际上会增多, 增加了计算成本, 在实际代码中,
是通过对 feature map 移位, 并给 Attention 设置 mask 来间接实现的,
这时移位后 window 数和未 shift 时的窗口数相等且计算结果等价,
如下图所示:
Uformer 是形如 UNet 的结构 (U-shaped Structures),
即将输入的图片不断地进行下采样得到比较小的 feature map,
再不断地进行上采样恢复到原图尺寸的网络架构,
上采样阶段和下采样阶段分别包括 个
encoder stage 和 个 decoder
stage.
对于 Uformer 而言, 给定形状为 的输入的退化图像 , 首先进行 Input Projection,
这一步时使用 卷积外加
Leaky ReLU 激活函数提取底层特征 且形状不变. 每一个 encoder
stage 都是形如下面的结构: Down-Sampling 部分首先展平得到 2D 格式的 feature map, 接着用
且步长为 2
的卷积层对通道加倍. 经过第 个
stage 得到的 feature map 的形状为 .
encoder 的末尾也即 decoder 的开始部分是若干 LeWin Blocks, 称之为
bottleneck stage, 接着是 个
decoder stage, 每一个 decoder stage 都是形如下面的结构: 其中 Up-Sampling 使用了 步长为 2 的反卷积缩小通道放大 feature map 的尺寸. 经过 个 decoder stage 之后, 展平特征 reshape
成 2D 的 feature map, 再通过 Output Projection 即 卷积得到形状为 的残差卷积 .
最终图像的重建通过
得到, 训练过程通过 Charbonnier 损失函数 ,
其中
在整个训练过程为常数.
LeWin Blocks 是由若干个
LeWin(L ocally-e nhanced
Win dow) Transformer block 组成的, LeWin Transformer
Block 的计算表示为 其中
表示第 个 LeWin Transformer
Block 输出的 feature map. LeWin Transformer Block 包括了两个核心的设计
W-MSA 和 LeFF, 且
在经过这 W-MSA 和 LeFF 时都引入了跳跃连接.
Uformer 中的 W-MSA 与 Swin Transformer 的计算如出一辙,
同时这里的注意力计算仍然采用了 Swin Tansformer 中的相对位置编码,
增加了一个偏置矩阵 , 即
LeFF 指 Locally-enhanced Feed-Forward NetWork,
结构如下图所示:
首先采用线性投影层即
卷积提升每个 token 的维度(即增加通道数), 然后通过 Token2Img 将每个 token
reshape 为 2D 图片进行
深度卷积捕捉局部信息, 再通过 Img2Token 展平为 token, 最后再用一个 卷积减小通道数,
整个流程使用的激活函数都是 GELU.
在每个 decoder-stage 中的 LeWin Blocks 中增加了 Multi-Scale
Restoration Modulator, 每一个 Modulator 都是可学习的参数, 充当每个形状为
的 window
在做自注意力之前的一个偏置项, 也就是说 Modulator 是一个形状为 的张量.
Markov Chain
Hidden Markov Model
GCN
DGI(Deep Graph Infomax)
.