转置卷积解释与示例计算

文章目录

  • 转置卷积的三种等价实现方法:原理、公式与等价性分析
    • 数学定义与核心公式
    • 方法一:零填充+翻转核卷积(数学定义方法)
      • 原理与公式
      • 等价性说明
    • 方法二:直接位置映射(pytorch框架高效实现)
      • 原理与公式
      • 等价性说明
    • 方法三:矩阵转置法(数学本质实现)
      • 原理与公式
      • 等价性说明
  • 转置卷积三种方法详细计算过程(使用输入X和卷积核K)
    • 输入参数
    • 方法一:零填充+翻转核卷积(数学定义方法)
      • 计算步骤:
    • 方法二:直接位置映射(框架高效实现)
      • 计算步骤:
    • 方法三:矩阵转置法(数学本质实现)
      • 计算步骤:
    • 三种方法统一结果
    • code

转置卷积的三种等价实现方法:原理、公式与等价性分析

数学定义与核心公式

转置卷积的数学本质是卷积运算的伴随算子(adjoint operator)。给定输入 X∈RHin×WinX \in \mathbb{R}^{H_{in} \times W_{in}}XRHin×Win 和卷积核 K∈RHk×WkK \in \mathbb{R}^{H_k \times W_k}KRHk×Wk,输出 Y∈RHout×WoutY \in \mathbb{R}^{H_{out} \times W_{out}}YRHout×Wout 满足:

Hout=(Hin−1)×stride+Hk−2×paddingH_{out} = (H_{in} - 1) \times \text{stride} + H_k - 2 \times \text{padding}Hout=(Hin1)×stride+Hk2×padding
Wout=(Win−1)×stride+Wk−2×paddingW_{out} = (W_{in} - 1) \times \text{stride} + W_k - 2 \times \text{padding}Wout=(Win1)×stride+Wk2×padding

三种方法都实现了相同的线性变换:
Y=T(X;K,stride,padding)Y = \mathcal{T}(X; K, \text{stride}, \text{padding})Y=T(X;K,stride,padding)

其中 T\mathcal{T}T 表示转置卷积操作。

方法一:零填充+翻转核卷积(数学定义方法)

原理与公式

  1. 输入扩展
    Xexpanded[i,j×s]=X[i,j]X_{\text{expanded}}[i, j \times s] = X[i, j]Xexpanded[i,j×s]=X[i,j]
    其中 sss 为步长,元素间插入 (s−1)(s-1)(s1) 个零值

  2. 边界填充
    Xpadded=pad(Xexpanded,p)X_{\text{padded}} = \text{pad}(X_{\text{expanded}}, p)Xpadded=pad(Xexpanded,p)
    p=max⁡(padding,k−1)p = \max(\text{padding}, k-1)p=max(padding,k1)

  3. 核翻转
    Kflipped[i,j]=K[Hk−1−i,Wk−1−j]K_{\text{flipped}}[i,j] = K[H_k-1-i, W_k-1-j]Kflipped[i,j]=K[Hk1i,Wk1j]

  4. 互相关运算
    Y[m,n]=∑i=0Hk−1∑j=0Wk−1Xpadded[m+i,n+j]⋅Kflipped[i,j]Y[m,n] = \sum_{i=0}^{H_k-1} \sum_{j=0}^{W_k-1} X_{\text{padded}}[m+i, n+j] \cdot K_{\text{flipped}}[i,j]Y[m,n]=i=0Hk1j=0Wk1Xpadded[m+i,n+j]Kflipped[i,j]

等价性说明

此方法直接实现数学定义:转置卷积 = 翻转核 + 扩展输入 + 互相关

方法二:直接位置映射(pytorch框架高效实现)

原理与公式

  1. 位置映射
    For each (i,j)∈X:\text{For each } (i,j) \in X:For each (i,j)X:
    Y[i⋅s+k,j⋅s+l]+=X[i,j]⋅K[k,l]Y[i \cdot s + k, j \cdot s + l] \mathrel{+}= X[i,j] \cdot K[k,l]Y[is+k,js+l]+=X[i,j]K[k,l]
    k∈[0,Hk−1],l∈[0,Wk−1]k \in [0, H_k-1], l \in [0, W_k-1]k[0,Hk1],l[0,Wk1]

  2. 边界处理
    仅当 i⋅s+k−p≥0i \cdot s + k - p \geq 0is+kp0j⋅s+l−p<Woutj \cdot s + l - p < W_{out}js+lp<Wout 时累加

等价性说明

此方法通过散射(scatter)操作实现:

  • 每个输入元素将核权重"放置"到输出空间
  • 重叠区域的值自动累加
  • 数学上等价于方法一,但避免了显式扩展

方法三:矩阵转置法(数学本质实现)

原理与公式

  1. 构建卷积矩阵
    定义常规卷积算子 CCC,满足:
    vec(Yconv)=C⋅vec(X)\text{vec}(Y_{\text{conv}}) = C \cdot \text{vec}(X)vec(Yconv)=Cvec(X)

  2. 转置卷积
    vec(Y)=CT⋅vec(X)\text{vec}(Y) = C^T \cdot \text{vec}(X)vec(Y)=CTvec(X)

  3. 矩阵元素
    C(m,n),(i,j)=K[k,l]if{i=⌊m/s⌋+kj=⌊n/s⌋+lC_{(m,n),(i,j)} = K[k,l] \quad \text{if} \quad \begin{cases} i = \lfloor m/s \rfloor + k \\ j = \lfloor n/s \rfloor + l \end{cases}C(m,n),(i,j)=K[k,l]if{i=m/s+kj=n/s+l

等价性说明

此方法直接实现线性代数的伴随算子定义:

  • CCC 是卷积的矩阵表示
  • CTC^TCT 是转置卷积的精确数学实现

转置卷积三种方法详细计算过程(使用输入X和卷积核K)

输入参数

  • 输入矩阵 X
    [[1, 2],[3, 4]]
    
  • 卷积核 K
    [[5, 6],[7, 8]]
    
  • 步长 stride:2
  • 填充 padding:0
  • 输出尺寸:4×4(根据公式:(2-1)×2 + 2 - 0 = 4

方法一:零填充+翻转核卷积(数学定义方法)

计算步骤:

  1. 输入矩阵 X零填充扩展输入

    • 在元素间插入 (stride-1)=1 个零值
    • 在行间插入 (stride-1)=1 行零行
    [[1, 0, 2],[0, 0, 0],[3, 0, 4]]
    
  2. 输入矩阵 X边界填充

    • 添加 (kernel_size-p-1)=1 圈零值
    [[0, 0, 0, 0, 0],[0, 1, 0, 2, 0],[0, 0, 0, 0, 0],[0, 3, 0, 4, 0],[0, 0, 0, 0, 0]]
    
  3. 核翻转

    • 180度旋转卷积核
    原始核:[[5, 6],[7, 8]]翻转核:[[8, 7],[6, 5]]
    
  4. 互相关计算

    • 使用翻转后的核在填充矩阵上滑动计算
    • 位置(0,0)
      窗口:[[0,0],[0,1]]
      计算:0×8 + 0×7 + 0×6 + 1×5 = 5
      
    • 位置(0,1)
      窗口:[[0,0],[1,0]]
      计算:0×8 + 0×7 + 1×6 + 0×5 = 6
      
    • 位置(0,2)
      窗口:[[0,0],[0,2]]
      计算:0×8 + 0×7 + 0×6 + 2×5 = 10
      
    • 位置(0,3)
      窗口:[[0,0],[2,0]]
      计算:0×8 + 0×7 + 2×6 + 0×5 = 12
      
    • 位置(1,0)
      窗口:[[0,1],[0,0]]
      计算:0×8 + 1×7 + 0×6 + 0×5 = 7
      
    • 位置(1,1)
      窗口:[[1,0],[0,0]]
      计算:1×8 + 0×7 + 0×6 + 0×5 = 8
      
    • 位置(1,2)
      窗口:[[0,2],[0,0]]
      计算:0×8 + 2×7 + 0×6 + 0×5 = 14
      
    • 位置(1,3)
      窗口:[[2,0],[0,0]]
      计算:2×8 + 0×7 + 0×6 + 0×5 = 16
      
    • 位置(2,0)
      窗口:[[0,0],[0,3]]
      计算:0×8 + 0×7 + 0×6 + 3×5 = 15
      
    • 位置(2,1)
      窗口:[[0,0],[3,0]]
      计算:0×8 + 0×7 + 3×6 + 0×5 = 18
      
    • 位置(2,2)
      窗口:[[0,0],[0,4]]
      计算:0×8 + 0×7 + 0×6 + 4×5 = 20
      
    • 位置(2,3)
      窗口:[[0,0],[4,0]]
      计算:0×8 + 0×7 + 4×6 + 0×5 = 24
      
    • 位置(3,0)
      窗口:[[0,3],[0,0]]
      计算:0×8 + 3×7 + 0×6 + 0×5 = 21
      
    • 位置(3,1)
      窗口:[[3,0],[0,0]]
      计算:3×8 + 0×7 + 0×6 + 0×5 = 24
      
    • 位置(3,2)
      窗口:[[0,4],[0,0]]
      计算:0×8 + 4×7 + 0×6 + 0×5 = 28
      
    • 位置(3,3)
      窗口:[[4,0],[0,0]]
      计算:4×8 + 0×7 + 0×6 + 0×5 = 32
      
  5. 最终输出

    [[ 5,  6, 10, 12],[ 7,  8, 14, 16],[15, 18, 20, 24],[21, 24, 28, 32]]
    

方法二:直接位置映射(框架高效实现)

计算步骤:

  1. 位置映射关系

    • 输入元素位置 → 输出起始位置
    (0,0) → (0,0)
    (0,1) → (0,2)
    (1,0) → (2,0)
    (1,1) → (2,2)
    
  2. 核权重分配

    • 元素(0,0)=1 的贡献:
      [1×5, 1×6] → 位置(0,0)和(0,1)
      [1×7, 1×8] → 位置(1,0)和(1,1)
      
    • 元素(0,1)=2 的贡献:
      [2×5, 2×6] → 位置(0,2)和(0,3)
      [2×7, 2×8] → 位置(1,2)和(1,3)
      
    • 元素(1,0)=3 的贡献:
      [3×5, 3×6] → 位置(2,0)和(2,1)
      [3×7, 3×8] → 位置(3,0)和(3,1)
      
    • 元素(1,1)=4 的贡献:
      [4×5, 4×6] → 位置(2,2)和(2,3)
      [4×7, 4×8] → 位置(3,2)和(3,3)
      
  3. 输出矩阵构建

    (0,0): 1×5 = 5
    (0,1): 1×6 = 6
    (0,2): 2×5 = 10
    (0,3): 2×6 = 12(1,0): 1×7 = 7
    (1,1): 1×8 = 8
    (1,2): 2×7 = 14
    (1,3): 2×8 = 16(2,0): 3×5 = 15
    (2,1): 3×6 = 18
    (2,2): 4×5 = 20
    (2,3): 4×6 = 24(3,0): 3×7 = 21
    (3,1): 3×8 = 24
    (3,2): 4×7 = 28
    (3,3): 4×8 = 32
    
  4. 完整输出

    [[ 5,  6, 10, 12],[ 7,  8, 14, 16],[15, 18, 20, 24],[21, 24, 28, 32]]
    

方法三:矩阵转置法(数学本质实现)

计算步骤:

  1. 构建卷积矩阵 C

    • 常规卷积:从4×4输入 → 2×2输出
    • 矩阵维度:4行(输出元素) × 16列(输入元素)
  2. 填充卷积矩阵

    • 输出位置(0,0)对应输入位置:
      [0,0]:5, [0,1]:6
      [1,0]:7, [1,1]:8
      
    • 矩阵行(0,0):[5,6,0,0,7,8,0,0,0,0,0,0,0,0,0,0]
    • 输出位置(0,1)对应输入位置:
      [0,2]:5, [0,3]:6
      [1,2]:7, [1,3]:8
      
    • 矩阵行(0,1):[0,0,5,6,0,0,7,8,0,0,0,0,0,0,0,0]
    • 输出位置(1,0)对应输入位置:
      [2,0]:5, [2,1]:6
      [3,0]:7, [3,1]:8
      
    • 矩阵行(1,0):[0,0,0,0,0,0,0,0,5,6,0,0,7,8,0,0]
    • 输出位置(1,1)对应输入位置:
      [2,2]:5, [2,3]:6
      [3,2]:7, [3,3]:8
      
    • 矩阵行(1,1):[0,0,0,0,0,0,0,0,0,0,5,6,0,0,7,8]
  3. 转置矩阵 CTC^TCT

    • 尺寸:16×4
    • 每列对应一个输出位置的影响
  4. 矩阵乘法

    • 输入展平:[1,2,3,4]
    • 计算:Y_flat = C^T × [1,2,3,4]^T
    • 结果:
      [5,6,10,12,7,8,14,16,15,18,20,24,21,24,28,32]
      
  5. 重塑为4×4矩阵

    [[ 5,  6, 10, 12],[ 7,  8, 14, 16],[15, 18, 20, 24],[21, 24, 28, 32]]
    

三种方法统一结果

[[ 5,  6, 10, 12],[ 7,  8, 14, 16],[15, 18, 20, 24],[21, 24, 28, 32]]

code

import torch
import torch.nn as nn# 定义输入张量和卷积核
input_tensor = torch.tensor([[[[1, 2],[3, 4]]]], dtype=torch.float32)  # 形状(1,1,2,2)
kernel = torch.tensor([[[[5, 6],[7, 8]]]], dtype=torch.float32)       # 形状(1,1,2,2)# 方法1:使用nn.ConvTranspose2d模块(推荐)
def method_conv_transpose2d(input, kernel):# 创建转置卷积层conv_trans = nn.ConvTranspose2d(in_channels=1,      # 输入通道数out_channels=1,     # 输出通道数kernel_size=2,      # 卷积核尺寸stride=2,           # 步长padding=0,          # 输入填充bias=False          # 禁用偏置)# 手动注入卷积核权重with torch.no_grad():conv_trans.weight = nn.Parameter(kernel)# 执行计算return conv_trans(input)# 方法2:使用functional.conv_transpose2d函数
def method_functional(input, kernel):return torch.nn.functional.conv_transpose2d(input=input,weight=kernel,bias=None,stride=2,padding=0)# 方法3:手动实现转置卷积(验证原理)
def manual_transposed_conv(input, kernel):"""根据和的数学原理实现:1. 输入插值:步长2需插入1行/列零2. 外部填充:卷积核2x2需在边缘补1圈零3. 用旋转180°的核执行普通卷积(步长1)"""# 输入插值(插入行列零)interpolated = torch.zeros(1, 1, 3, 3)interpolated[0, 0, ::2, ::2] = input.squeeze()# 外部填充(四周各补1圈零)padded = torch.nn.functional.pad(interpolated, [1, 1, 1, 1])# 卷积核旋转180°rotated_kernel = torch.rot90(kernel.squeeze(), 2, dims=(0, 1)).unsqueeze(0).unsqueeze(0)print("旋转后的卷积核:\n", rotated_kernel.squeeze())# 执行普通卷积(步长1,无填充)return torch.nn.functional.conv2d(padded, rotated_kernel, padding=0)# 计算并验证结果
output_module = method_conv_transpose2d(input_tensor, kernel)
output_functional = method_functional(input_tensor, kernel)
output_manual = manual_transposed_conv(input_tensor, kernel)print("nn.ConvTranspose2d 输出:\n", output_module.squeeze())
print("F.conv_transpose2d 输出:\n", output_functional.squeeze())
print("手动实现转置卷积输出:\n", output_manual.squeeze())

结果:

旋转后的卷积核:tensor([[8., 7.],[6., 5.]])
nn.ConvTranspose2d 输出:tensor([[ 5.,  6., 10., 12.],[ 7.,  8., 14., 16.],[15., 18., 20., 24.],[21., 24., 28., 32.]], grad_fn=<SqueezeBackward0>)
F.conv_transpose2d 输出:tensor([[ 5.,  6., 10., 12.],[ 7.,  8., 14., 16.],[15., 18., 20., 24.],[21., 24., 28., 32.]])
手动实现转置卷积输出:tensor([[ 5.,  6., 10., 12.],[ 7.,  8., 14., 16.],[15., 18., 20., 24.],[21., 24., 28., 32.]])

参考:
00
0
1
2
3

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/91800.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/91800.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关于车位引导及汽车乘梯解决方案的专业性、系统性、可落地性强的综合设计方案与技术实现说明,旨在为现代智慧停车楼提供高效、安全、智能的停车体验。

一、系统概述随着城市土地资源日益紧张&#xff0c;立体停车、自动化停车成为发展趋势。本方案围绕“车位引导系统 汽车乘梯系统”构建智慧停车核心体系&#xff0c;结合地磁/视频/超声波检测、AI识别、语音交互、电梯自动调度等先进技术&#xff0c;实现车辆入场、引导、停泊…

【相机】曝光时间长-->拖影

曝光时间长 → 运动目标在快门开启期间持续移动 → 同一像素记录多个位置的能量 → 图像出现“拖影”&#xff08;运动模糊&#xff09;。&#x1f50d; 具体原因卷帘快门&#xff08;Rolling Shutter&#xff09;效应 RealSense 的 RGB 传感器&#xff08;如 IMX 系列&#xf…

day36 力扣1049.最后一块石头的重量II 力扣494.目标和 力扣474.一和零

最后一块石头的重量II有一堆石头&#xff0c;用整数数组 stones 表示。其中 stones[i] 表示第 i 块石头的重量。每一回合&#xff0c;从中选出任意两块石头&#xff0c;然后将它们一起粉碎。假设石头的重量分别为 x 和 y&#xff0c;且 x < y。那么粉碎的可能结果如下&#…

Java内存模型(Java Memory Model,JMM)

​​ JMM​​ 是Java虚拟机&#xff08;JVM&#xff09;规范中定义的一组规则和规范&#xff0c;用于描述多线程环境下&#xff0c;Java程序中变量的访问和修改行为&#xff0c;尤其是在并发编程中如何保证内存可见性、原子性和有序性。JMM 是 Java 并发编程的基石&…

【swoole Windows 开发(swoole-cli 开发 hyperf)】

先前swoole在Windows平台的开发体验极差&#xff0c;如果在Windows开发swoole的东西可以用docker或者虚拟机&#xff0c;远程开发&#xff0c;体验比较好的是直接Mac或者Linux系统开发。但是作为window平台的钉子户表示我穷。swoole之前已经推出了cygwin64编译成winwods版本的方…

兴达餐饮 酒店 进销存管理系统软件

兴达餐饮 酒店 进销存管理系统软件

Seal Report:一款免费开源的报表工具

Seal Report 是一款基于 C# 语言开发的开源报表工具&#xff0c;可以从各种数据库或 NoSQL 数据源中生成日常报告&#xff0c;并且执行复杂的计划任务。 功能特性 免费开源&#xff1a;源代码托管在 GitHub 上&#xff0c;用户可以自由使用、修改、甚至集成到自己的系统中&…

WebRTC 多媒体 SDP 示例与解析

webRTC中的SDP的Bundlle可能包含一个或者多个媒体块&#xff08;媒体描述, 源码对应类ContentInfo&#xff09;&#xff0c;从 m 开始到下一个 m 行&#xff08;或 SDP 结束&#xff09;之间的所有属性&#xff08;包括 a&#xff09;都属于同一个媒体块&#xff08;media sect…

SpringBoot 启动富文本文字更改

正常来说 SpringBoot启动时候&#xff0c;展示的文字是这个 、 主播这边想要换一个样式&#xff0c;换一个自己自定义的文字 这边换成了自己的博客名字 具体实现操作如下 在项目目录 resources下创建一个名字为banner.txt的文本&#xff0c;这是SpringBoot启动的时候寻找的…

基于结构熵权-云模型的铸铁浴缸生产工艺安全评价

一、评价模型核心思想 结构熵权法 解决传统熵权法忽略指标间结构关系的问题,通过指标层次网络计算权重。 步骤: 构建工艺安全评价指标体系(树状/网络结构) 计算同级指标间的影响度矩阵 引入修正熵权:wj=1−Ej∑(1−Ek)结构影响因子w_j = \frac{1 - E_j}{\sum (1 - E_k)} \…

[Linux]从零开始的vs code交叉调试arm Linux程序教程

一、前言 最近的项目中需要集成rknn的视觉识别&#xff0c;在这之前我并且没有将rknn集成到自己项目的经验。这里我需要在rknn原本demo的基础上我还需要集成自己的业务代码。但是又有一个问题&#xff0c;原本rknn我们都是使用交叉编译编译到开发板上的&#xff0c;并且我们还要…

视频号私信自动化回复插件

给自己的浏览器插件又增加了视频号斯信的自动化回复搜索&#xff1a;程序员老狼主体逻辑就是&#xff0c;不停的点击打招呼和斯信那个tab切换查看有无小红点&#xff0c;有小红点的会话&#xff0c;就点击。查看有无打招呼&#xff0c;有打招呼就点击&#xff0c;抓取昵称和内容…

Web前端实现银河粒子流动特效的3种技术方案对比与实践

文章目录 前端实现银河粒子流动特效的技术原理与实践 引言:银河粒子特效的技术背景与现状 技术发展历史 当前技术现状 技术原理与实现方案 思维导图:银河粒子特效技术架构 1. CSS3实现方案 基础实现代码 性能优化技巧 2. Canvas 2D实现方案 基础实现代码 Canvas高级优化技术 …

Linux:告别Jammy,拥抱Noble!WSL Ubuntu 22.04 到 24.04 LTS 终极升级指南

大家好&#xff01;如果大家和我一样&#xff0c;是Windows Subsystem for Linux (WSL) 的忠实用户&#xff0c;那么大家一定对Ubuntu在其中的表现印象深刻。我们中的许多人可能还在使用稳定可靠的Ubuntu 22.04 LTS (Jammy Jellyfish)。但现在&#xff0c;一个更令人兴奋的时代…

江协科技STM32 11-1 SPI通信协议

本节课我们将继续学习下一个通信协议&#xff0c;SPI。SPI通信和我们刚刚学习过的I2C通信差不多。两个协议的设计目的都一样都是实现主控芯片和各种外挂芯片之间的数据交流&#xff0c;有了数据交流的能力&#xff0c;我们的主控芯片就可以挂载并操纵各式各样的外部芯片&#x…

预过滤环境光贴图制作教程:第一步 - HDR 转立方体贴图

在基于物理的渲染(PBR)中,环境光贴图是实现真实光照效果的核心组件之一。而将 HDR 全景图转换为立方体贴图,是制作预过滤环境光贴图的基础步骤。本教程将详细讲解如何实现这一转换过程。 什么是 HDR 转立方体贴图? HDR(高动态范围)全景图通常以等矩形投影(Equirectan…

02 深度学习介绍【动手学深度学习v2】| 学习笔记

1、intro自然语言处理虽然我们过去取得了很大的进展&#xff0c;但是实际上还是停留在感知层面。计算机视觉领域&#xff0c;因为图片里面都是像素&#xff0c;像素很难用符号学来解释&#xff0c;所以计算机视觉大部分是用概率模型或机器学习来做。深度学习它是机器学习的一种…

智能学号抽取系统V5.6.4重磅发布

告别随机数&#xff0c;拥抱智能点名&#xff01;—— 全新升级的“智能学号抽取系统V5.6.4”重磅发布&#xff01; 摘要&#xff1a; 还在为课堂随机提问、活动抽奖而手动翻名单、查表格而烦恼吗&#xff1f;还在忍受传统点名工具的简陋和不智能吗&#xff1f;今天&#xff0…

Leetcode-141.环形链表

dict和set 1. 结构上的区别&#xff1a;类型键&#xff08;Key&#xff09;值&#xff08;Value&#xff09;示例dict有有{a: 1, b: 2}set有没有{a, b} dict 是**键值对&#xff08;key-value&#xff09;**的集合。set 是只有键&#xff08;key&#xff09;没有值的一组唯一元…

调节步进电机速度时调PSC和调ARR的区别

在步进电机控制中&#xff0c;调节速度通常是通过改变脉冲频率实现的。代码中选择调节ARR&#xff08;Auto-Reload Register&#xff09;而非PSC&#xff08;Prescaler&#xff09;的原因如下&#xff1a; 1. ARR 与 PSC 的核心区别 • ARR&#xff08;自动重载寄存器&#xff…