深度学习中的上采样技术及其实现

一、反卷积(转置卷积)

反卷积通常用于将低维特征映射成高维输入,与卷积操作的作用相反。一般反卷积只能还原图片的大小,不能将图片还原为原来的图片。反卷积操作的时候有两种情况,分为步长为1和步长大于1。

1. stride = 1
  1. stride=1时,反卷积操作时在特征图周围填充0,至于添加多少padding,就要看原图和特征图的大小关系。比如原图大小为4 * 4 ,卷积核大小为3 * 3,步长为1,卷积后的特征图大小为:2 * 2,那么现在要将这个尺寸的特征图反卷积成4 * 4 大小,那么先填充padding=2的0,也即添加两圈。然后用3 * 3 卷积核进行卷积,得到了5 * 5 大小的图片。如图所示:

卷积操作:
在这里插入图片描述
反卷积操作:
在这里插入图片描述

2.stride > 1
  1. 当步长大于1时,先在周围添加0, 然后按照步长等于1时的操作进行,如下图所示的操作:
    在这里插入图片描述
  2. 步长大于2时的反卷积操作:

在这里插入图片描述

3. 反卷积操作实现

在这里插入图片描述

from torchvision.transforms import ToTensor, ToPILImage
import torch.nn as nn
import matplotlib.pyplot as plt
from PIL import Image
# 显示原始图像
orginal_img = Image.open("yellow/dog.jpg")
plt.subplot(1, 3, 1)
plt.axis('off')
plt.title("orginal pic")
plt.imshow(orginal_img)

# 显示卷积后的图像
img = ToTensor()(orginal_img)
conv = nn.Conv2d(3, 3, 3, 1)
y = conv(img.unsqueeze(0))
conv_img = ToPILImage("RGB")(y.squeeze(0))
plt.subplot(1, 3, 2)
plt.axis('off')
plt.title("conv pic")
plt.imshow(conv_img)

#显示反卷积后的图像
transconv = nn.ConvTranspose2d(3, 3, 3, 1)
trans_img = transconv(y)
trans_img = ToPILImage("RGB")(trans_img.squeeze(0))
plt.subplot(1, 3, 3)
plt.axis('off')
plt.title("transconv pic")
plt.imshow(trans_img)
plt.show()

上述代码只是简单的展示了反卷积如何实现,它与卷积的实现方法很相似。

二、反池化

1. 反池化操作

反池化过程主要介绍两种池化:最大池化的反池化和平均池化的反池化。
其中最大池化在反池化时要记录最大值所在的位置,然后其余位置用0补充,平均池化一般用邻近元素作填充。如下图所示:
在这里插入图片描述

3. 反池化操作的实现

在这里插入图片描述

from torchvision.transforms import ToTensor, ToPILImage
import torch.nn as nn
import matplotlib.pyplot as plt
from PIL import Image
# 显示原始图像
orginal_img = Image.open("yellow/dog.jpg")
plt.subplot(1, 3, 1)
plt.axis('off')
plt.title("orginal pic")
plt.imshow(orginal_img)

# 卷积层
img = ToTensor()(orginal_img)
conv = nn.Conv2d(3, 3, 3, 1)
y = conv(img.unsqueeze(0))

# 池化层,显示池化后的图片
"""
参数return_indices:表示返回最大值所在的位置,最大池化在进行反池化操作哦时要记录最大值所在的位置。
"""
pool = nn.MaxPool2d(2, 2, return_indices=True)
pool_y, index = pool(y)
pool_img = ToPILImage("RGB")(pool_y.squeeze())
plt.subplot(1, 3, 2)
plt.axis('off')
plt.title("pool pic")
plt.imshow(pool_img)

# 反池化操作并显示反池化后的图片
unpool = nn.MaxUnpool2d(2, 2)
y = unpool(pool_y, index)

# 对比池化操作输出的值和反池化操作输出值的大小
print("池化后的值:", pool_y)
print("反池化后的值:", y)
unpool_img = ToPILImage("RGB")(y.squeeze())
plt.subplot(1, 3, 3)
plt.axis('off')
plt.title("unpool pic")
plt.imshow(unpool_img)
plt.show()
池化的作用:
  1. 减小特征图大小
  2. 降低过拟合,降低过拟合是减小输出大小的结果,它同样也减少了后续层中的参数的数量。
  3. 池化操作很暴力的丢弃了一些图片的特征,可以用大步长的卷积代替池化操作,这样就可以保证图片特征不丢失。

三、普通上采样

(1)最邻近插值

最邻近插值算法的原理:在原图像中找到最邻近的一个点,然后把这个点的像素值插入到目标图像中,最近临插值算法优点是算法简单易于实现,但是缺点是由于相邻像素点的像素值相同,容易出现色块现象。

(2)双线性插值
  1. 双线性插值原理解释

首先在Q11Q21、Q12Q22方向上进行两次线性插值,得到R1、R2;然后在R1R2方向再做一次线性插值得到P点,这就是双线性插值。
在这里插入图片描述

双线性插值原理动图:
图片来源:https://www.cnblogs.com/SpiritAmos/p/11991528.html
在这里插入图片描述

(3) 最邻近插值和双线性插值的实现:

在这里插入图片描述

from torchvision.transforms import ToTensor, ToPILImage
import torch.nn as nn
import matplotlib.pyplot as plt
from PIL import Image
import torch.nn.functional as F
orginal_img = Image.open("yellow/dog.jpg")
plt.subplot(1, 3, 1)
plt.axis('off')
plt.title("orginal pic")
plt.imshow(orginal_img)

img = ToTensor()(orginal_img)
conv = nn.Conv2d(3, 3, 3, 1)
y = conv(img.unsqueeze(0))
trans_conv = nn.ConvTranspose2d(3, 3, 3, 1)
y = trans_conv(y)
# pool = nn.MaxPool2d(2, 2)
# pool_y = pool(y)

# 最邻近插值,参数scale_factor 表示放大或缩小倍数
"""
以下两种写法都可以用F.interpolate()函数代替
upsample = nn.UpsamplingNearest2d(scale_factor=2)
upsample = nn.Upsample(scale_factor=2, mode='nearest') 
"""
z1 = F.interpolate(y, scale_factor=2, mode='nearest')
near_conv_img = ToPILImage("RGB")(z1.squeeze(0))
plt.subplot(1, 3, 2)
plt.axis('off')
plt.title("nearest")
plt.imshow(near_conv_img)

# 双线性插值,双线性插值中参数align_corners是对齐角的意思
"""
以下两种写法都可以用F.interpolate()函数代替
upsample = nn.UpsamplingBilinear2d(scale_factor=2)
upsample = nn.Upsample(scale_factor=2, mode='bilinear', align_corners=True) 
"""
z2 = F.interpolate(y, scale_factor=2, mode='bilinear', align_corners=True)
linear_conv_img = ToPILImage("RGB")(z2.squeeze(0))
plt.subplot(1, 3, 3)
plt.axis('off')
plt.title("bilinear")
plt.imshow(linear_conv_img)
plt.show()
  • 9
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值