1. 上采样
在深度学习中,有很多涉及到图像大小调整的操作。前面我们讲过的下采样,用于将图像缩小,下面我们来看一下上采样。
在PyTorch中,可以通过 nn.Upsample 类来进行上采样,也可以通过 nn.functional.interpolate 函数来进行上采样。这两种方式的参数类似,有些参数只适用于其中一种方法。
1.1 nn.Upsample
nn.Upsample 类是 PyTorch 中提供的上采样类,可以将输入的高、宽放大一定倍数。nn.Upsample 中可以指定输出大小或倍数,同时还可以指定插值方法。
import torch.nn as nn
import torch
# 输入 2x3x4x4
inputs = torch.randn(2, 3, 4, 4)
# 通过 nn.Upsample 类对输入进行上采样
# scale_factor —— 上采样的倍数
# mode——上采样时的插值方式, 默认为 'nearest'
upsample = nn.Upsample(scale_factor=2, mode='bilinear')
# 上采样后的大小 2x3x8x8
outputs = upsample(inputs)
print(outputs.shape)
nn.Upsample 还可以通过指定固定大小来进行上采样,将输入的大小调整为指定的输出大小。
import torch.nn as nn
import torch
# 输入 2x3x4x4
inputs = torch.randn(2, 3, 4, 4)
# 通过 nn.Upsample 类对输入进行上采样
# size——上采样后的大小,格式为 (H_out, W_out)
# mode——上采样时的插值方式, 默认为 'nearest'
upsample = nn.Upsample(size=(8, 8), mode='bilinear')
# 上采样后的大小 2x3x8x8
outputs = upsample(inputs)
print(outputs.shape)
1.2 nn.functional.interpolate
nn.functional.interpolate 函数是 PyTorch 中提供的另一种上采样方法,与 nn.Upsample 类似,可以将输入的高、宽放大一定倍数,也可以指定插值方式,同时还可以指定输出大小。
import torch.nn.functional as F
import torch
# 输入 2x3x4x4
inputs = torch.randn(2, 3, 4, 4)
# 通过 nn.functional.interpolate 函数对输入进行上采样
# scale_factor —— 上采样的倍数
# mode——上采样时的插值方式, 默认为 'nearest'
outputs = F.interpolate(inputs, scale_factor=2, mode='bilinear')
print(outputs.shape)
通过 nn.functional.interpolate 函数还可以指定固定大小进行上采样。
import torch.nn.functional as F
import torch
# 输入 2x3x4x4
inputs = torch.randn(2, 3, 4, 4)
# 通过 nn.functional.interpolate 函数对输入进行上采样
# size——上采样后的大小,格式为 (H_out, W_out)
# mode——上采样时的插值方式, 默认为 'nearest'
outputs = F.interpolate(inputs, size=(8, 8), mode='bilinear')
print(outputs.shape)
2. 反卷积
在 CNN 中,反卷积也叫转置卷积(transpose convolution),在图像处理方面有较多应用,可以将输入大小转换为目标大小。
在 PyTorch 中,可以使用 nn.ConvTranspose2d 类进行反卷积操作,同时也可以同时也可以通过 nn.functional.conv_transpose2d 函数进行反卷积操作,这两种方式的参数类似,有些参数只适用于其中一种方式。
2.1 nn.ConvTranspose2d
nn.ConvTranspose2d 类是 PyTorch 中提供的反卷积类,可以将输入大小转换为目标大小。nn.ConvTranspose2d 中通过 stride 与 padding 来指定输入、输出大小,通过 kernel_size 来指定卷积核大小。
import torch.nn as nn
import torch
# 输入 2x3x4x4
inputs = torch.randn(2, 3, 4, 4)
# 通过 nn.ConvTranspose2d 类对输入进行反卷积
# in_channels —— 输入通道数目
# out_channels —— 输出通道数目
# kernel_size —— 卷积内核大小
# stride —— 步长,默认为 1
# padding —— 填充大小,默认为 0
# output_padding —— 输出填充大小,默认为 0
conv_transpose = nn.ConvTranspose2d(in_channels=3, out_channels=6, kernel_size=3, stride=2, padding=1, output_padding=1)
# 反卷积后的大小 2x6x8x8
outputs = conv_transpose(inputs)
print(outputs.shape)
2.2 nn.functional.conv_transpose2d
nn.functional.conv_transpose2d 函数是 PyTorch 中提供的另一种反卷积方法,与 nn.ConvTranspose2d 类似,可以将输入大小转换为目标大小,通过指定 kernel_size, stride, padding, 输出大小等参数来实现。
import torch.nn.functional as F
import torch
# 输入 2x3x4x4
inputs = torch.randn(2, 3, 4, 4)
# 通过 nn.functional.conv_transpose2d 函数对输入进行反卷积
# in_channels —— 输入通道数目
# out_channels —— 输出通道数目
# kernel_size —— 卷积内核大小
# stride —— 步长,默认为 1
# padding —— 填充大小,默认为 0
# output_padding —— 输出填充大小,默认为 0
outputs = F.conv_transpose2d(inputs, in_channels=3, out_channels=6, kernel_size=3, stride=2, padding=1, output_padding=1)
print(outputs.shape)
3. 反池化
池化操作是一种无法恢复输入大小的操作,因此需要有一种反操作来恢复输入大小。在 PyTorch 中,可以使用 nn.MaxUnpool2d 类来进行反池化操作,同时也可以通过 nn.functional.max_unpool2d 函数进行反池化操作,这两种方式的参数类似,有些参数只适用于其中一种方式。
3.1 nn.MaxUnpool2d
nn.MaxUnpool2d 类是 PyTorch 中提供的反池化类,可以将池化后的输出恢复到原始大小和形状,与池化时指定的参数相应。
import torch.nn as nn
import torch
# 输入 1x1x4x4
inputs = torch.Tensor([[[[1, 2, 3, 8],
[4, 5, 6, 8],
[7, 8, 9, 8],
[8, 8, 8, 8]]]])
# 通过 nn.MaxPool2d 类进行池化操作
max_pool = nn.MaxPool2d(kernel_size=2, stride=2, return_indices=True)
# 进行池化操作
pooled, indices = max_pool(inputs)
# 获取池化后的输出和蓝色部分对应的下标
unpool = nn.MaxUnpool2d(kernel_size=2, stride=2)
# 将池化后的输出恢复到原始大小和形状
outputs = unpool(pooled, indices)
print(outputs.shape)
print(outputs)
3.2 nn.functional.max_unpool2d
nn.functional.max_unpool2d 函数是 PyTorch 中提供的另一种反池化方法,与 nn.MaxUnpool2d 类似,可以将池化后的输出恢复到原始大小和形状,与池化时指定的参数相应。
import torch.nn.functional as F
import torch
# 输入 1x1x4x4
inputs = torch.Tensor([[[[1, 2, 3, 8],
[4, 5, 6, 8],
[7, 8, 9, 8],
[8, 8, 8, 8]]]])
# 通过 nn.functional.max_pool2d 函数进行池化操作
pooled, indices = F.max_pool2d(inputs, kernel_size=2, stride=2, return_indices=True)
# 通过 nn.functional.max_unpool2d 函数将池化后的输出恢复到原始大小和形状
outputs = F.max_unpool2d(pooled, indices, kernel_size=2, stride=2)
print(outputs.shape)
print(outputs)