在阅读YOLO模型和DenseNet网络模型的时候,对“上采样”和“反卷积”的概念不甚理解,查阅了一些资料,整理如下。并附上pytorch实现上采样的源码。
在阅读本文前,默认读者已经了解了深度学习中的卷积操作。
声明:本文用到的部分资料来自简书作者@乔大叶_803e和知乎作者@幽并游侠儿_1425上采样(Upsample)
在介绍上采样前,还有一个概念叫做下采样。下采样简单来讲,就是在卷积时,通过设置步长的方式,达到将输出缩小的目的。例如,通过设置步长为2的方式,可以将输出缩减为输入的一半,这也是经常使用的下采样方式。
而上采样达到的效果,则和下采样相反。上采样可以扩大输入图像的尺寸,将一个小分辨率的图像扩展成一个高分辨率的图像。在YOLOv4模型中,上采样被加入卷积网络中,作为中间层使用,扩展特征图尺寸,便于张量拼接。
![](https://i-blog.csdnimg.cn/blog_migrate/89abdf8cfc89a443fe31e0462c0ccdba.png)
上采样常用的方法有双线性插值法,反卷积(也称转置卷积)法和上池化法。这里主要介绍反卷积。
反卷积(Transposed Convolution)
在理解反卷积前,我们先回顾一下正向的卷积操作。
![](https://i-blog.csdnimg.cn/blog_migrate/f5d0ab2373b682089d14f99cd48b7c54.png)
而反卷积,顾名思义,是反向的卷积操作,如下图。
![](https://i-blog.csdnimg.cn/blog_migrate/a681a182a9d66cc6011b61d196b6d077.png)
假设我们有一个3×3的卷积核,
![](https://i-blog.csdnimg.cn/blog_migrate/c3da8cf03e3de72ac99e90faf49810c1.png)
将其按照行重新排列:
![](https://i-blog.csdnimg.cn/blog_migrate/cdfa34ca0c32bf23739806115d020057.png)
得到了一个4×16的矩阵,记为C
![](https://i-blog.csdnimg.cn/blog_migrate/0cdd2d16ed6091474579c54dfe605dbd.png)
将原始的4×4的输入矩阵扁平化为一个16×1的列向量,记为A。
记输出矩阵为B,可以得到
C
A
=
B
CA=B
CA=B
即
![](https://i-blog.csdnimg.cn/blog_migrate/de7d342488bd4eb0246d126f84f096f9.png)
我们现在要进行的是反卷积,即通过B得到A,按照线性代数,
A
=
C
T
B
A=C^{T}B
A=CTB
即
![](https://i-blog.csdnimg.cn/blog_migrate/e7a248beb536a9a3328b75801c4acc9a.png)
然后将输出reshape就可以得到4×4的特征矩阵了。
![](https://i-blog.csdnimg.cn/blog_migrate/5e94673aaba252a14df754d1042ad74a.png)
pytorch实现上采样
pytorch提供了上采样的实现,其源码如下
from .module import Module
from .. import functional as F
from torch import Tensor
class Upsample(Module):
__constants__ = ['size', 'scale_factor', 'mode', 'align_corners', 'name']
name: str
size: Optional[_size_any_t]
scale_factor: Optional[_ratio_any_t]
mode: str
align_corners: Optional[bool]
def __init__(self, size: Optional[_size_any_t] = None, scale_factor: Optional[_ratio_any_t] = None,
mode: str = 'nearest', align_corners: Optional[bool] = None) -> None:
super(Upsample, self).__init__()
self.name = type(self).__name__
self.size = size
if isinstance(scale_factor, tuple):
self.scale_factor = tuple(float(factor) for factor in scale_factor)
else:
self.scale_factor = float(scale_factor) if scale_factor else None
self.mode = mode
self.align_corners = align_corners
def forward(self, input: Tensor) -> Tensor:
return F.interpolate(input, self.size, self.scale_factor, self.mode, self.align_corners)
def extra_repr(self) -> str:
if self.scale_factor is not None:
info = 'scale_factor=' + str(self.scale_factor)
else:
info = 'size=' + str(self.size)
info += ', mode=' + self.mode
return info
对函数调用的实例如下:
import torch.nn as nn
x = nn.Upsample(scale_factor=2, mode='nearest')
如果觉得有帮助,欢迎点赞+收藏,笔芯~