卷积|深度学习:全卷积网络
全卷积网络(fully convolutional network , FCN)采用卷积神经网络实现了从图像像素到像素类别的变换[36] 。 与之前介绍的卷积神经网络有所不同 , 全卷积网络通过转置卷积(transposed convolution)层将中间层特征图的高和宽变换回输入图像的尺寸 , 从而令预测结果与输入图像在空间维(高和宽)上一一对应:给定空间维上的位置 , 通道维的输出即该位置对应像素的类别预测 。
我们先导入实验所需的包或模块 , 然后解释什么是转置卷积层 。
In [1]: %matplotlib inline import d2lzh as d2l from mxnet import gluon, image, init, nd from mxnet.gluon import data as gdata, loss as gloss, model_zoo, nn import numpy as np import sys
9.10.1转置卷积层
顾名思义 , 转置卷积层得名于矩阵的转置操作 。 事实上 , 卷积运算还可以通过矩阵乘法来实现 。 在下面的例子中 , 我们定义高和宽分别为 4 的输入X , 以及高和宽分别为3的卷积核K 。 打印二维卷积运算的输出以及卷积核 。 可以看到 , 输出的高和宽分别为 2 。
In [2]: X = nd.arange(1, 17).reshape((1, 1, 4, 4)) K = nd.arange(1, 10).reshape((1, 1, 3, 3)) conv = nn.Conv2D(channels=1, kernel_size=3) conv.initialize(init.Constant(K)) conv(X), KOut[2]: ( [[[[348. 393.] [528. 573.]]]] , [[[[1. 2. 3.] [4. 5. 6.] [7. 8. 9.]]]] )
下面我们将卷积核K改写成含有大量零元素的稀疏矩阵W , 即权重矩阵 。 权重矩阵的形状为(4, 16) , 其中的非零元素来自卷积核K中的元素 。 将输入X逐行连结 , 得到长度为 16 的向量 。 然后将W与向量化的X做矩阵乘法 , 得到长度为 4 的向量 。 对其变形后 , 我们可以得到和上面卷积运算相同的结果 。 可见 , 我们在这个例子中使用矩阵乘法实现了卷积运算 。
In [3]: W, k = nd.zeros((4, 16)), nd.zeros(11) k[:3], k[4:7], k[8:] = K[0, 0, 0, :], K[0, 0, 1, :], K[0, 0, 2, :] W[0, 0:11], W[1, 1:12], W[2, 4:15], W[3, 5:16] = k, k, k, k nd.dot(W, X.reshape(16)).reshape((1, 1, 2, 2)), WOut[3]: ( [[[[348. 393.] [528. 573.]]]] , [[1. 2. 3. 0. 4. 5. 6. 0. 7. 8. 9. 0. 0. 0. 0. 0.] [0. 1. 2. 3. 0. 4. 5. 6. 0. 7. 8. 9. 0. 0. 0. 0.] [0. 0. 0. 0. 1. 2. 3. 0. 4. 5. 6. 0. 7. 8. 9. 0.] [0. 0. 0. 0. 0. 1. 2. 3. 0. 4. 5. 6. 0. 7. 8. 9.]] )
现在我们从矩阵乘法的角度来描述卷积运算 。 设输入向量为x , 权重矩阵为W , 卷积的前向计算函数的实现可以看作将函数输入乘以权重矩阵 , 并输出向量
。 我们知道 , 反向传播需要依据链式法则 。 由于
, 卷积的反向传播函数的实现可以看作将函数输入乘以转置后的权重矩阵
。 而转置卷积层正好交换了卷积层的前向计算函数与反向传播函数:这两个函数可以看作将函数输入向量分别乘以
和W 。
不难想象 , 转置卷积层可以用来交换卷积层输入和输出的形状 。 让我们继续用矩阵乘法描述卷积 。 设权重矩阵是形状为
的矩阵 , 对于长度为16的输入向量 , 卷积前向计算输出长度为4的向量 。 假如输入向量的长度为4 , 转置权重矩阵的形状为
, 那么转置卷积层将输出长度为16的向量 。 在模型设计中 , 转置卷积层常用于将较小的特征图变换为更大的特征图 。 在全卷积网络中 , 当输入是高和宽较小的特征图时 , 转置卷积层可以用来将高和宽放大到输入图像的尺寸 。
我们来看一个例子 。 构造一个卷积层conv , 并设输入X的形状为 (1 , 3 , 64 , 64) 。 卷积输出Y的通道数增加到10 , 但高和宽分别缩小了一半 。
In [4]: conv = nn.Conv2D(10, kernel_size=4, padding=1, strides=2) conv.initialize() X = nd.random.uniform(shape=(1, 3, 64, 64)) Y = conv(X) Y.shapeOut[4]: (1, 10, 32, 32)
推荐阅读
- 蓝橡树|牛娃爸爸分享: 孩子如何通过学习编程, 激活大脑, 提升成绩, 逆袭名校?
- |更精确地预估到达时间,滴滴新研究提出异质时空图卷积网络
- 行业互联网,AI人工智能|苹果公布新的AI和机器学习培训计划
- 数据|同盾李晓林谈联邦学习实现数据安全共享
- 学习|敲黑板:刷课学习、提笔速记,华为MatePad 10.8值得拥有
- 科大讯飞|科大讯飞到底好不好?科大讯飞智能学习机告诉你!
- 青年|200824 可以与防弹少年团 一起学习韩国语的教材今日正式问世了
- |初学者友好,麦吉尔大学助理教授新书《图表示学习》开放下载
- 中年|俄罗斯为何从不担心芯片卡脖?美国拿它也没辙,方法值得中国学习
- 中年|拒绝学习美国,俄罗斯外长力挺中国华为,顺便还羞辱了一番美国