我是靠谱客的博主 凶狠胡萝卜,最近开发中收集的这篇文章主要介绍PyTorch笔记 - Convolution卷积运算的原理 (4),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

ConvTranspose2d

unfold操作,torch.nn.Unfold

unfold = nn.Unfold(kernel_size=(2, 3))  # 6维,2x3
input = torch.randn(2, 5, 3, 4)  # 2是batch,5是input_channel,
output = unfold(input)
output.size()  # [2, 30, 4],2x3x5=30,kernel是2x3,feature_map是3x4,(I-K+2P)/S+1 = (3-2+0)/1+1 = 2,输出是2x2的blocks=4

matrix_multiplication_for_conv2d_flatten版本,可以通过unfold实现

nn.ConvTranspose2d转置卷积

  • torch.nn.ConvTranspose2d
  • torch.nn.functional.conv_transpose2d

把5x5的Input转换为25x1,将3x3的kernel,也转换为25x1的kernel,其他位置进行填充0,通过kernel matrix,提升特征图尺寸

  • 转置卷积用在上采样
  • 后向传播实现转置卷积,或者,填充input实现转置卷积

通过对kernel进行展开,来实现二维卷积,并推导出转置卷积,不考虑batch和channel

  • 可以实现卷积,降低特征图的尺寸
  • 也可以实现转置卷积(ConvTranspose2d),提升特征图的尺寸
# step4:通过对kernel进行展开,来实现二维卷积,并推导出转置卷积,不考虑batch和channel
def get_kernel_matrix(kernel, input_size, stride=1):
    """
    基于kernel和输入特征图的大小,来得到填充拉直后的kernel堆叠后的矩阵
    """
    kernel_h, kernel_w = kernel.shape
    input_h, input_w = input_size  # 元组
    output_h, output_w = int((input_h-kernel_h)/stride + 1), int((input_w-kernel_w)/stride+1)
    num_out_feat_map = output_h * output_w
    result = torch.zeros((num_out_feat_map, input_h*input_w))  # 初始化结果矩阵,输出特征图元素个数*输入特征图元素个数
    for i in range(0, output_h, stride):
        for j in range(0, output_w, stride):
            # 左右上下,填充成跟输入特征图一样的大小
            padded_kernel = F.pad(kernel, (j, input_w-kernel_w-j, i, input_h-kernel_h-i))
            result[i*output_h + j] = padded_kernel.flatten()
    return result

# 测试1:验证卷积
kernel = torch.randn(3, 3)
input = torch.randn(4, 4)
kernel_matrix = get_kernel_matrix(kernel, input.shape)  # 4x16
print(f"[Info] kernel: n{kernel}")
print(f"[Info] kernel_matrix: n{kernel_matrix}")
mm_conv2d_output = kernel_matrix @ input.reshape((-1, 1))   # 通过矩阵相乘的方式,算出卷积
mm_conv2d_output_ = mm_conv2d_output.reshape(1, 1, 2, 2)  # 对齐
print(f"[Info] mm_conv2d_output_.shape: {mm_conv2d_output_.shape}")
print(f"[Info] mm_conv2d_output_: n{mm_conv2d_output_}")
# PyTorch conv2d api
pytorch_conv2d_output = F.conv2d(input.reshape(1, 1, *input.shape), kernel.reshape(1, 1, *kernel.shape))
print(f"[Info] pytorch_conv2d_output: n{pytorch_conv2d_output}")

# 测试2:验证二维转置卷积,将输入卷积由input 2x2,ouput上升为4x4
# 通过kernel matrix,提升特征图尺寸,TransposedConv,转置卷积用在上采样
mm_transposed_conv2d_output = kernel_matrix.transpose(-1, -2) @ mm_conv2d_output
mm_transposed_conv2d_output = mm_transposed_conv2d_output.reshape(1, 1, 4, 4)
print(f"[Info] mm_transposed_conv2d_output: n{mm_transposed_conv2d_output}")

pytorch_transposed_conv2d_output = F.conv_transpose2d(pytorch_conv2d_output, kernel.reshape(1, 1, *kernel.shape))
print(f"[Info] pytorch_transposed_conv2d_output: n{pytorch_transposed_conv2d_output}")

最后

以上就是凶狠胡萝卜为你收集整理的PyTorch笔记 - Convolution卷积运算的原理 (4)的全部内容,希望文章能够帮你解决PyTorch笔记 - Convolution卷积运算的原理 (4)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(31)

评论列表共有 0 条评论

立即
投稿
返回
顶部