首页 > 其他分享 >动手学深度学习6.4 多输入多输出通道-笔记&练习(PyTorch)

动手学深度学习6.4 多输入多输出通道-笔记&练习(PyTorch)

时间:2024-07-16 11:29:41浏览次数:19  
标签:输出 卷积 张量 笔记 PyTorch 6.4 True 输入 通道

以下内容为结合李沐老师的课程和教材补充的学习笔记,以及对课后练习的一些思考,自留回顾,也供同学之人交流参考。

本节课程地址:21 卷积层里的多输入多输出通道【动手学深度学习v2】_哔哩哔哩_bilibili

本节教材地址:6.4. 多输入多输出通道 — 动手学深度学习 2.0.0 documentation (d2l.ai)

本节开源代码:...>d2l-zh>pytorch>chapter_multilayer-perceptrons>channels.ipynb


多输入多输出通道

虽然我们在 6.1.4.1节 中描述了构成每个图像的多个通道和多层卷积层。例如彩色图像具有标准的RGB通道来代表红、绿和蓝。 但是到目前为止,我们仅展示了单个输入和单个输出通道的简化例子。 这使得我们可以将输入、卷积核和输出看作二维张量。

当我们添加通道时,我们的输入和隐藏的表示都变成了三维张量。例如,每个RGB输入图像具有 3\times h\times w 的形状。我们将这个大小为3的轴称为通道(channel)维度。本节将更深入地研究具有多输入和多输出通道的卷积核。

多输入通道

当输入包含多个通道时,需要构造一个与输入数据具有相同输入通道数的卷积核,以便与输入数据进行互相关运算。假设输入的通道数为 c_i ,那么卷积核的输入通道数也需要为 c_i 。如果卷积核的窗口形状是 k_h\times k_w ,那么当 c_i=1 时,我们可以把卷积核看作形状为 k_h\times k_w 的二维张量。

然而,当 c_i>1 时,我们卷积核的每个输入通道将包含形状为 k_h\times k_w 的张量。将这些张量 c_i 连结在一起可以得到形状为 c_i\times k_h\times k_w 的卷积核。由于输入和卷积核都有 c_i 个通道,我们可以对每个通道输入的二维张量和卷积核的二维张量进行互相关运算,再对通道求和(将 c_i 的结果相加)得到二维张量。这是多通道输入和多输入通道卷积核之间进行二维互相关运算的结果。

在 图6.4.1 中,我们演示了一个具有两个输入通道的二维互相关运算的示例。阴影部分是第一个输出元素以及用于计算这个输出的输入和核张量元素: (1\times1+2\times2+4\times3+5\times4)+(0\times0+1\times1+3\times2+4\times3)=56

多个输入通道

  • 输入 \mathbf{X}: c_i \times n_h \times n_w
  • 核 \mathbf{W}: c_i \times k_h \times k_w
  • 输出 \mathbf{Y}: m_h \times m_w
  • \mathbf{Y} = \sum_{i=0}^{c_i} \mathbf{X}_{i,:,:} * \mathbf{W}_{i,:,:}

为了加深理解,我们(实现一下多输入通道互相关运算)。 简而言之,我们所做的就是对每个通道执行互相关操作,然后将结果相加。

import torch
from d2l import torch as d2l
def corr2d_multi_in(X, K):
    # 先遍历“X”和“K”的第0个维度(通道维度),再把它们加在一起
    return sum(d2l.corr2d(x, k) for x, k in zip(X, K))

我们可以构造与 :numref:fig_conv_multi_in中的值相对应的输入张量X和核张量K,以(验证互相关运算的输出)。

X = torch.tensor([[[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]],
               [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]]])
K = torch.tensor([[[0.0, 1.0], [2.0, 3.0]], [[1.0, 2.0], [3.0, 4.0]]])

corr2d_multi_in(X, K)

输出结果:
tensor([[ 56., 72.],
[104., 120.]])

多输出通道

到目前为止,不论有多少输入通道,我们还只有一个输出通道。然而,正如我们在 6.1.4.1节 中所讨论的,每一层有多个输出通道是至关重要的。在最流行的神经网络架构中,随着神经网络层数的加深,我们常会增加输出通道的维数,通过减少空间分辨率以获得更大的通道深度。直观地说,我们可以将每个通道看作对不同特征的响应。而现实可能更为复杂一些,因为每个通道不是独立学习的,而是为了共同使用而优化的。因此,多输出通道并不仅是学习多个单通道的检测器。

用 c_i 和 c_o 分别表示输入和输出通道的数目,并让 k_h 和 k_w 为卷积核的高度和宽度。为了获得多个通道的输出,我们可以为每个输出通道创建一个形状为 c_i\times k_h\times k_w 的卷积核张量,这样卷积核的形状是 c_o\times c_i\times k_h\times k_w 。在互相关运算中,每个输出通道先获取所有输入通道,再以对应该输出通道的卷积核计算出结果。

多个输出通道

  • 可以有多个三维卷积核,每个核生成一个输出通道
  • 输入 \mathbf{X}: c_i \times n_h \times n_w
  • 核 \mathbf{W}: c_o \times c_i \times k_h \times k_w
  • 输出 \mathbf{Y}: c_o \times m_h \times m_w
  • \mathbf{Y}_{i,:,:} = \mathbf{X} * \mathbf{W}_{i,:,:,:} \quad for \quad i = 1,\dots,c_o

如下所示,我们实现一个[计算多个通道的输出的互相关函数]。

def corr2d_multi_in_out(X, K):
    # 迭代“K”的第0个维度(输出通道),每次都对输入“X”执行互相关运算。
    # 最后将所有结果都叠加在一起
    return torch.stack([corr2d_multi_in(X, k) for k in K], 0)

通过将核张量KK+1K中每个元素加1)和K+2连接起来,构造了一个具有3个输出通道的卷积核。

K = torch.stack((K, K + 1, K + 2), 0)
K.shape

输出结果:
torch.Size([3, 2, 2, 2])

下面,我们对输入张量X与卷积核张量K执行互相关运算。现在的输出包含3个通道,第一个通道的结果与先前输入张量X和多输入单输出通道的结果一致。

corr2d_multi_in_out(X, K)

输出结果:
tensor([[[ 56., 72.],
[104., 120.]],

[[ 76., 100.],
[148., 172.]],

[[ 96., 128.],
[192., 224.]]])

多个输入和输出通道用途:

  • 每个输出通道可以识别特定模式
  • 输入通道核识别并组合输入中的模式

1 \times 1 卷积层

1 \times 1 卷积,即 k_h = k_w = 1 ,看起来似乎没有多大意义。 毕竟,卷积的本质是有效提取相邻像素间的相关特征,而 1 \times 1 卷积显然没有此作用。 尽管如此,1 \times 1 仍然十分流行,经常包含在复杂深层网络的设计中。下面,让我们详细地解读一下它的实际作用。

因为使用了最小窗口,1 \times 1 卷积失去了卷积层的特有能力——在高度和宽度维度上,识别相邻元素间相互作用的能力。 其实 1 \times 1 卷积的唯一计算发生在通道上。

图6.4.2 展示了使用 1 \times 1 卷积核与3个输入通道和2个输出通道的互相关计算。 这里输入和输出具有相同的高度和宽度,输出中的每个元素都是从输入图像中同一位置的元素的线性组合。 我们可以将 1 \times 1 卷积层看作在每个像素位置应用的全连接层,以 c_i 个输入值转换为 c_o 个输出值。 因为这仍然是一个卷积层,所以跨像素的权重是一致的。 同时,1 \times 1 卷积层需要的权重维度为 c_o \times c_i ,再额外加上一个偏置。

1 \times 1 卷积层
k_h = k_w = 1 ,不识别空间模式,只是融合通道。 相当于输入形状为 n_hn_w \times c_i ,权重为 c_o \times c_i 的全连接层。

下面,我们使用全连接层实现 1×1 卷积。 请注意,我们需要对输入和输出的数据形状进行调整。

def corr2d_multi_in_out_1x1(X, K):
    c_i, h, w = X.shape
    c_o = K.shape[0]
    X = X.reshape((c_i, h * w))
    K = K.reshape((c_o, c_i))
    # 全连接层中的矩阵乘法
    Y = torch.matmul(K, X)
    return Y.reshape((c_o, h, w))

当执行 1×1 卷积运算时,上述函数相当于先前实现的互相关函数corr2d_multi_in_out。让我们用一些样本数据来验证这一点。

X = torch.normal(0, 1, (3, 3, 3))
K = torch.normal(0, 1, (2, 3, 1, 1))
Y1 = corr2d_multi_in_out_1x1(X, K)
Y2 = corr2d_multi_in_out(X, K)
assert float(torch.abs(Y1 - Y2).sum()) < 1e-6
# 意味着1×1的卷积层相当于输入形状为c_i × n_hn_w,权重为c_o × c_i的全连接层

二维卷积层

  • 输入 \mathbf{X}: c_i \times n_h \times n_w
  • 核 \mathbf{W}: c_o \times c_i \times k_h \times k_w
  • 偏差 \mathbf{B}: c_o \times c_i
  • 输出 \mathbf{Y}: c_o \times m_h \times m_w
  • \mathbf{Y} = \mathbf{X} * \mathbf{W} + \mathbf{B}
  • 计算复杂度(浮点计算数FLOP) O(c_i c_o k_h k_w m_h m_w) (连乘)

c_i = c_o =100 \\ k_h = k_w = 5 \\ m_h = m_w = 64 

则计算量为 1GFLOP

  • 假设net有10层,1M样本,计算量为10PFlops
  • 相当于CPU(0.15 TF/s)计算18h,GPU(12 TF/s)计算14分钟

小结

  • 输出通道数是卷积层的超参数。
  • 多输入多输出通道可以用来扩展卷积层的模型。
  • 当以每像素为基础应用时, 1\times 1 卷积层相当于全连接层。
  • 1\times 1 卷积层通常用于调整网络层的通道数量和控制模型复杂性。

练习

1. 假设我们有两个卷积核,大小分别为 k_1 和 k_2 (中间没有非线性激活函数)。

1)证明运算可以用单次卷积来表示。

2)这个等效的单个卷积核的维数是多少呢?

3)反之亦然吗?

解:
1)不考虑通道、填充和步幅,证明如下:
输入
 \mathbf{X}: n_h \times n_w 
 k_1: k_{h1} \times k_{w1}, k_2: k_{h2} \times k_{w2}
第一次卷积后的输出 \mathbf{Y_1}: (n_h - k_{h1} + 1) \times (n_w - k_{w1} + 1) 
第二次卷积后的输出

 \mathbf{Y_2}: [(n_h - k_{h1} + 1) - k_{h2} + 1] \times [(n_w - k_{w1} + 1) - k_{w2} + 1] = [n_h - (k_{h1} + k_{h2} - 1) + 1] \times [n_w - (k_{w1} + k_{w2} - 1) + 1]
也即,将卷积核设为 (k_{h1} + k_{h2} - 1) \times (k_{w1} + k_{w2} - 1) 可以等价代替以上两个卷积核。

2)如上所述,等线的单个卷积核维数为 (k_{h1} + k_{h2} - 1) \times (k_{w1} + k_{w2} - 1)
3)反之亦然,单个卷积核也可拆成两个卷积核等价表示。

2. 假设输入为 c_i\times h\times w ,卷积核大小为 c_o\times c_i\times k_h\times k_w ,填充为 (p_h, p_w) ,步幅为 (s_h, s_w) 。

1)前向传播的计算成本(乘法和加法)是多少?

2)内存占用是多少?

3)反向传播的内存占用是多少?

4)反向传播的计算成本是多少?

解:
1) 一次卷积的乘法操作数量是
 c_i\times k_h\times k_w , 加法操作数量是 c_i\times k_h\times k_w - 1 
卷积操作数量为
 [(h-k_h+p_h+s_h)/s_h]\times [(w-k_w+p_w+s_w)/s_w]\times c_o 
因此,前向传播的计算成本(乘法和加法)为: 
(2\times c_i\times k_h\times k_w - 1)\times [(h-k_h+p_h+s_h)/s_h]\times [(w-k_w+p_w+s_w)/s_w]\times c_o
2) 前向传播的内存占用为输入、输出、权重和偏置参数量之和:
c_i\times h\times w + c_o\times c_i\times [(h-k_h+p_h+s_h)/s_h]\times [(w-k_w+p_w+s_w)/s_w] + c_o\times c_i\times k_h\times k_w + c_o\times c_i
3) 反向传播为对权重和偏置求偏导,内存占用为权重和偏置参数量之和:
c_o\times c_i\times k_h\times k_w + c_o\times c_i
4) 推荐先看图示卷积神经网络反向传播原理:https://www.bilibili.com/video/BV1eP411D77M/?spm_id_from=333.337.search-card.all.click&vd_source=8dd6bc62e96dda5b38e6bd4149b70687
仅考虑权重求导:
\mathbf{W^*{i,:,:,:}} = \mathbf{W{i,:,:,:}} - \eta \times \frac{\partial \mathbf{L}}{\partial \mathbf{W_{i,:,:,:}}}
一次偏导操作数量是 c_i\times k_h\times k_w , 加法操作数量是 c_i\times k_h\times k_w 
偏导操作数量为
 c_i\times k_h\times k_w 
权重更新的操作数量为
 c_o 
因此,反向传播的计算成本(乘法和加法)为: 
(2\times c_i\times k_h\times k_w - 1)\times [(h-k_h+p_h+s_h)/s_h]\times [(w-k_w+p_w+s_w)/s_w]\times c_o + c_o

3. 如果我们将输入通道 c_i 和输出通道 c_o 的数量加倍,计算数量会增加多少?如果我们把填充数量翻一番会怎么样?
解:
输入通道
 c_i 和输出通道 c_o 的数量加倍,计算数量会增加到之前的4倍;
填充数量翻一番,计算数量增加
 [(p_h)/s_h]\times [(p_w)/s_w]\times c_i \times c_o

4. 如果卷积核的高度和宽度是 k_h=k_w=1 ,前向传播的计算复杂度是多少?
解:
卷积核的高度和宽度是
 k_h=k_w=1 时,前向传播的计算复杂度是 c_o\times c_i\times h\times w\times [(h-1+p_h+s_h)/s_h]\times [(w-1+p_w+s_w)/s_w]

5. 本节最后一个示例中的变量Y1Y2是否完全相同?为什么?
解:
不完全相同,因为浮点数计算有误差,代码如下:

Y1 == Y2

输出结果:
tensor([[[False, True, False],
[ True, True, True],
[ True, True, True]],

[[ True, True, True],
[ True, True, True],
[ True, True, True]]])

6. 当卷积窗口不是 1×1 时,如何使用矩阵乘法实现卷积?

解:
方法与6.2练习第3题一样,代码如下:

def corr2d_matmul(X, K): 
    h, w = K.shape
    # 将输入X中每次与卷积核做互相关运算的元素展平成一行
    # X_reshaped的每一行元素均为与卷积核做互相关的元素
    X_reshaped = torch.zeros((X.shape[0] - h + 1)*(X.shape[1] - w + 1), h*w)
    k = 0
    for i in range(X.shape[0] - h + 1):
        for j in range(X.shape[1] - w + 1):
            X_reshaped[k,:] = X[i:i + h, j:j + w].reshape(1,-1)
            k += 1
    # 将卷积核K转为列向量,并与X_reshaped做矩阵乘法,再reshape成输出尺寸即可
    Y = [email protected](-1)
    return Y.reshape(X.shape[0] - h + 1, X.shape[1] - w + 1)
def corr2d_matmul_multi_in(X, K):
    return sum(d2l.corr2d(x, k) for x, k in zip(X, K))
X = torch.tensor([[[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0, 7.0, 8.0]],
               [[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0, 8.0, 9.0]]])
K = torch.tensor([[[0.0, 1.0], [2.0, 3.0]], [[1.0, 2.0], [3.0, 4.0]]])

corr2d_matmul_multi_in(X, K)

输出结果:
tensor([[ 56., 72.],
[104., 120.]])

标签:输出,卷积,张量,笔记,PyTorch,6.4,True,输入,通道
From: https://blog.csdn.net/scdifsn/article/details/140460941

相关文章

  • DIY系列——自制简易笔记本电脑散热器
    前言:为什么要自制笔记本电脑散热器?夏天到了,电脑的使用频率也在增加。尤其是笔记本电脑,长时间运行后很容易发热,影响性能和寿命。市场上有很多散热器产品,但价格不菲且效果参差不齐。如果你动手能力强,又想节省一笔开支,自制一个简易的笔记本电脑散热器是一个不错的选择。材料准备......
  • 信创学习笔记(三),信创之操作系统OS思维导图
    创作不易只因热爱!!热衷分享,一起成长!“你的鼓励就是我努力付出的动力”title!!#f1c232点击上方蓝色小字即可一键关注!!!!#f1c232创作不易只因热爱!!:::primary!18热衷分享,一起成长!:::^**你好呀,我是卫码士。一个医信行业工程师,喜欢学习,喜欢搞机,喜欢......
  • 杂乱无章的sql注入学习笔记(应该会持续更新)
    关于注入点:注入点不仅仅有.php?id=xxx只要是后端有交互的点都可能存在sql注入,黑盒情况下不知道后端,所以得fuzz,有的数据库会对你的cookieua进行查询操作,甚至是别的请求头,所以要都fuzz试试.甚至对图片的查询操作都可能存在注入点,思路要打开.学习sql语句:参考SQL通配符......
  • Java JNI 学习笔记
    JavaJNI学习笔记JNI(JavaNativeInterface)是Java提供的一种接口,使得java代码可以与其他语言(如C和C++)编写的代码进行交互。具体来说,JNI允许你在Java中调用本地(Native)代码,或者从本地代码调用Java方法。基本概念jni.h:这是JNI的头文件,使用javac生成,定义了JNI......
  • MongoDB自学笔记(二)
    一、前言接着上一篇文章,在上一篇文章中学习了如何使用数据库、如何创建集合、如何往集合里添加文档,今天我们继续学习一下更新文档,更新文档相对来说比较复杂笔者打算分多次来记录学习过程。二、文档操作1、更新文档基础语法:db.collection.updateOne(filter,update,opt......
  • LeetCode算法笔记5
    题目描述给你一个字符串 s,找到 s 中最长的 回文子串示例1:输入:s="babad"输出:"bab"解释:"aba"同样是符合题意的答案。示例2:输入:s="cbbd"输出:"bb"提示:1<=s.length<=1000s 仅由数字和英文字母组成解法:classSolution:deflongestPalindrome(sel......
  • LeetCode算法笔记2
    题目描述给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。请你将两个数相加,并以相同形式返回一个表示和的链表。你可以假设除了数字0之外,这两个数都不会以0 开头。示例1:输入:l1=[2,4,3],l......
  • 长链剖分笔记
    与轻重链剖分相似.dfs1:高度\(h\)、\(son\);dfs2:\(top\).性质1:到根最多\(O(\sqrtn)\)条轻边.(证明:长链长度最坏情况:1,2,3...)性质2:\(x\)的\(k\)级祖先\(y\)所在的长链长度\(\gek\).(证明:若非,则\(y-x\)是一条更长的链,矛盾.)树上\(k\)级祖先\(O(n\logn)-O(1)\):......
  • 最爽手撕算法个人笔记【第一周-数组】
    27.移除元素给你一个数组nums和一个值val,你需要原地移除所有数值等于val的元素。元素的顺序可能发生改变。然后返回nums中与val不同的元素的数量。假设nums中不等于val的元素数量为k,要通过此题,您需要执行以下操作:更改nums数组,使nums的前k个元素包含不......
  • 网络安全相关的一些学习笔记
    网络安全?本文主要为《计算机网络》网络安全章节的学习笔记,也包括部分来自其他博客与网站的段落。1.一些名词解释密码编码学(cryptography):密码体制的设计学密码分析学(cryptanalysis):在未知密钥的情况下从密文推演出明文或密钥的技术上述二者合称密码学(cryptology)无条件安全(理......