当前位置: 首页 > news >正文

动手学深度学习——转置卷积代码

这一篇要比上一节更偏“动手验证”,重点不是再空讲概念,而是通过代码把这几件事看清楚:

  • 转置卷积到底怎么计算

  • ConvTranspose2d怎么用

  • kernel_sizepaddingstride如何影响输出

  • 转置卷积和普通卷积在形状变化上有什么关系

1. 前言

上一篇我们已经学习了**转置卷积(Transposed Convolution)**的基本概念。

我们知道,转置卷积常用于:

  • 上采样

  • 恢复特征图空间分辨率

  • 语义分割、生成模型等任务

但如果只停留在概念层面,还是不够扎实。
真正要理解一个算子,最好的方法之一就是:

看代码、跑代码、验证输出。

因此,这一节我们就按照《动手学深度学习》的思路,用代码来具体观察:

  • 一个小输入矩阵经过转置卷积后变成什么样

  • 转置卷积的输出是如何形成的

  • 不同参数会怎样改变输出尺寸


2. 一个最基础的手写示例

李沐这里一开始通常不会直接上ConvTranspose2d
而是先写一个最小化版本的函数,帮助我们理解转置卷积的计算过程。

例如:

import torch from d2l import torch as d2l def trans_conv(X, K): h, w = K.shape Y = torch.zeros((X.shape[0] + h - 1, X.shape[1] + w - 1)) for i in range(X.shape[0]): for j in range(X.shape[1]): Y[i:i+h, j:j+w] += X[i, j] * K return Y

这段代码非常关键,因为它直接把转置卷积最核心的计算过程写出来了。


3. 这段代码在做什么

我们逐步拆解一下。

3.1 输入

X

表示输入矩阵。

K

表示卷积核。


3.2 输出大小

Y = torch.zeros((X.shape[0] + h - 1, X.shape[1] + w - 1))

如果输入大小是:

m × n

卷积核大小是:

h × w

那么这里先构造一个大小为:

(m + h - 1) × (n + w - 1)

的输出矩阵。

这正体现了转置卷积“让输出变大”的特点。


3.3 核心循环

for i in range(X.shape[0]): for j in range(X.shape[1]): Y[i:i+h, j:j+w] += X[i, j] * K

这就是转置卷积最本质的操作:

输入中的每个元素X[i, j],都会乘上整个卷积核K
然后加到输出矩阵Y的一个局部区域中。

而多个输入元素投影后的区域可能会重叠,
重叠部分就直接相加。

这正是转置卷积和普通卷积最大的直观区别。


4. 代入一个具体例子

接下来我们用一个最经典的例子:

X = torch.tensor([[0.0, 1.0], [2.0, 3.0]]) K = torch.tensor([[0.0, 1.0], [2.0, 3.0]]) trans_conv(X, K)

输出结果为:

tensor([[ 0., 0., 1.], [ 0., 4., 6.], [ 4., 12., 9.]])

5. 这个结果是怎么来的

这个地方非常适合博客里详细解释,因为它能让读者真正看懂转置卷积。

5.1 输入左上角元素0

0 * K = [[0, 0], [0, 0]]

加到输出左上角区域,不产生影响。


5.2 输入右上角元素1

1 * K = [[0, 1], [2, 3]]

加到输出中从(0,1)开始的区域。


5.3 输入左下角元素2

2 * K = [[0, 2], [4, 6]]

加到输出中从(1,0)开始的区域。


5.4 输入右下角元素3

3 * K = [[0, 3], [6, 9]]

加到输出中从(1,1)开始的区域。


5.5 重叠部分相加

最终把这些局部块叠加起来,就得到:

[[ 0., 0., 1.], [ 0., 4., 6.], [ 4., 12., 9.]]

这样一看,转置卷积的结果就不再神秘了。


6. 用 PyTorch 的ConvTranspose2d实现同样过程

手写代码只是为了理解原理。
真正做深度学习时,通常还是直接调用框架提供的算子。

对应代码如下:

X = torch.tensor([[[[0.0, 1.0], [2.0, 3.0]]]]) K = torch.tensor([[[[0.0, 1.0], [2.0, 3.0]]]]) tconv = torch.nn.ConvTranspose2d(1, 1, kernel_size=2, bias=False) tconv.weight.data = K tconv(X)

输出结果通常是:

tensor([[[[ 0., 0., 1.], [ 0., 4., 6.], [ 4., 12., 9.]]]], grad_fn=...)

可以看到,这和我们手写函数得到的结果是一致的。


7. 为什么这里输入要写成四维张量

很多初学者会被这里的形状绕住。

X.shape = (1, 1, 2, 2)

这四个维度分别表示:

  • 批量大小batch_size = 1

  • 输入通道数in_channels = 1

  • height = 2

  • width = 2

这是 PyTorch 卷积层统一使用的输入格式。

所以虽然我们直观看到的是一个2 × 2矩阵,
但喂给网络层时,必须补成四维张量。


8.padding对转置卷积输出有什么影响

接下来就进入参数观察部分。

先看代码:

tconv = torch.nn.ConvTranspose2d(1, 1, kernel_size=2, padding=1, bias=False) tconv.weight.data = K tconv(X)

这时输出尺寸会变小。

这说明什么?

在转置卷积中,padding会影响输出边缘,通常可以理解为对输出做裁剪。

这和普通卷积里“给输入补零”的直觉不太一样,所以特别容易混。


9.stride对输出大小的影响

再看步幅。

tconv = torch.nn.ConvTranspose2d(1, 1, kernel_size=2, stride=2, bias=False) tconv.weight.data = K tconv(X)

stride=2时,输出尺寸会明显变大。

这说明:

转置卷积中的步幅越大,输出通常越大。

直观上可以理解为:
输入元素在投影到输出时,间隔被拉开了,于是整体输出范围增大。


10. 用公式验证输出大小

二维转置卷积的输出大小常用公式为:

输出大小 = (输入大小 - 1) * stride - 2 * padding + kernel_size

例如:

  • 输入大小:2

  • stride = 1

  • padding = 0

  • kernel_size = 2

那么输出大小为:

(2 - 1) * 1 - 0 + 2 = 3

所以输出是3 × 3

如果改成:

  • 输入大小:2

  • stride = 2

  • padding = 0

  • kernel_size = 2

则输出大小为:

(2 - 1) * 2 - 0 + 2 = 4

所以输出会变成4 × 4

这和代码实验是对应的。


11. 转置卷积可以实现“放大特征图”

通过上面的代码,我们可以非常清楚地看到:

  • 普通卷积常常把图变小

  • 转置卷积常常把图变大

因此,在语义分割中,当我们有一个较小的特征图,
希望把它恢复到更高分辨率时,就可以考虑使用转置卷积。

也就是说,这一节代码不是孤立的,
它是在为后面的 FCN 做技术准备。


12. 卷积和转置卷积在形状变化上的对照

这个点李沐也会特别强调。

假设一个普通卷积层:

conv = nn.Conv2d(10, 20, kernel_size=5, padding=2, stride=3)

输入形状是:

X = torch.rand(size=(1, 10, 16, 16))

那么输出形状可能会变成:

Y = conv(X) Y.shape

如果我们再构造一个“对应参数”的转置卷积层:

tconv = nn.ConvTranspose2d(20, 10, kernel_size=5, padding=2, stride=3)

然后把刚才卷积得到的Y输入进去:

tconv(Y).shape

最终会发现输出形状回到了:

(1, 10, 16, 16)

13. 这说明了什么

这说明转置卷积在形状变换关系上,确实和普通卷积密切相关。

也就是说:

  • 普通卷积把16 × 16变成更小

  • 对应的转置卷积可以把这个更小的结果变回16 × 16

注意,这里说的是:

形状可以恢复

但并不意味着:

数值内容一定恢复成原来那个输入

这两点一定要区分开。


14. 为什么叫“转置卷积”

从代码实验中,我们已经能感觉到,
转置卷积并不是普通卷积的简单反向播放。

它之所以叫“转置卷积”,是因为从矩阵表示角度看:

普通卷积可以写成一个线性变换矩阵乘法
而转置卷积对应的是这个矩阵的转置形式

所以这里的“转置”,本质上是线性代数意义上的转置,
不是说它一定能把原输入精确还原回来。


15. 这节代码最该掌握什么

如果从“考试/面试/博客总结”角度看,这一节最重要的是以下几点:

15.1 手写版计算过程

要知道转置卷积是:

  • 输入元素乘卷积核

  • 投影到输出局部区域

  • 重叠部分相加


15.2ConvTranspose2d的基本使用方式

至少要知道:

  • 输入是四维张量

  • 可以手动设置权重核

  • 可以通过stridepadding控制输出形状


15.3 输出尺寸公式

这一点非常常用:

输出大小 = (输入大小 - 1) * stride - 2 * padding + kernel_size

15.4 它和普通卷积的关系

要知道它和卷积有密切联系,
但它不是严格意义上的“逆卷积”。


16. 本节总结

这一节我们通过代码具体验证了转置卷积,核心内容可以总结为以下几点。

16.1 手写实现帮助理解原理

输入中的每个元素都会乘上卷积核并加到输出局部区域中。

16.2ConvTranspose2d可以直接实现转置卷积

PyTorch 中已经提供了标准接口。

16.3paddingstride都会影响输出尺寸

其中stride增大时,输出通常也会增大。

16.4 转置卷积能恢复空间尺寸

因此非常适合语义分割等需要上采样的任务。

16.5 它和普通卷积在形状变化上密切相关

但不是严格意义上的可逆还原。


17. 学习感悟

这一节最大的价值在于:
它把“转置卷积”从一个抽象概念,变成了一个你能亲手验证的运算过程。

很多深度学习知识,一旦能用一个小矩阵例子跑通,理解就会扎实很多。
转置卷积就是典型代表。

前面只说它“能上采样”,可能还比较模糊;
但通过这节代码我们就能真正看到:

它为什么能放大输出,参数又是如何控制这个放大过程的。

http://www.cnnetsun.cn/news/1848333.html

相关文章:

  • 3步诊断法:彻底解决ESP32开发板安装失败的终极指南
  • Nacos启动报错:深入解析Unable to start embedded Tomcat的根源与解决方案
  • LangGraph Agent架构实战:构建一个具备自我修正能力的规划智能体
  • 三步掌握微信聊天记录永久保存:你的数字记忆守护者
  • Transformer剪枝到底该剪Attention还是FFN?Meta/DeepMind/阿里联合实验数据首次公开(含HuggingFace一键工具链)
  • OpenClaw+优云智算Coding Plan:从灵感到成文,再到发布的全流程AI自动化霞
  • 仅限头部AI平台内部流出的配额审计清单:覆盖Token级计量、跨模型共享配额、突发流量信用额度等8项稀缺机制
  • MiniMax M. 发布!Redis 故障排查 + 跨语言重构场景实测,表现如何?焉
  • 别再硬编码了!用LVGL的页面栈管理器实现优雅的界面切换(附智能健康助手项目源码分析)
  • Maxwell涡流热损计算:铜导体在50Hz交流下的仿真实践
  • libcrypt-dev安装指南:解决crypt.h缺失报错
  • ESP8266 OTA升级实战:基于巴法云的极简实现方案
  • 高性能客服系统技术内幕:通过 SpinWait 自旋等待结构体提升高频消息分发性能坦
  • 5步彻底解决显卡驱动残留问题:DDU深度使用终极指南
  • 终极缠论分析插件:3分钟让你的通达信拥有专业缠论分析能力
  • Cadence Virtuoso 字体大小调整全攻略:从基础设置到高级优化
  • 如何在 Ubuntu 22.04 LTS 上部署 Jenkins 自动化服务器?
  • Gemm4安卓手机运行
  • 如何快速掌握PS4游戏修改:专业级GoldHEN作弊管理器完全指南
  • 写段代码教会你什么是HOOK技术?HOOK技术能干什么?屑
  • 从零上手:基于MRS与WCH-Link的ARM/RISC-V单片机一站式烧录实战
  • EF Core 原生 SQL 实战:FromSql、SqlQuery 与对象映射边界兔
  • DanmakuFactory:解决弹幕格式兼容性难题的专业转换工具
  • 如何用WebPlotDigitizer在6分钟内完成45分钟的科研数据提取工作?终极指南
  • 从V8引擎的垃圾回收(GC)机制入手,聊聊CVE-2020-6507漏洞利用中的那些“内存魔术”
  • Phi-4-reasoning-vision-15B惊艳效果:多页PDF扫描件→表格重建+语义对齐
  • clangd配置与优化:从入门到精通
  • ComfyUI节点开发实战:从零构建自定义AI图像处理模块
  • 终极LRC歌词批量下载方案:告别手动搜索,让离线音乐库焕发新生
  • OpCore Simplify终极指南:3大核心功能让黑苹果配置效率提升80%