提交 430c6f9c 编写于 作者: W wizardforcel

2021-01-18 17:41:10

上级 6ae00503
......@@ -161,7 +161,7 @@ for epoch in range(25):
训练使用具有默认动量速率的`Adam`优化器。 另外,损失函数是从 PyTorch 的`Functional`模块创建的。 除了创建`target`变量以外,其他所有操作均与常规训练操作相同。
到目前为止,我们一直在有监督的学习中工作,其中明确给出了标签,但是在这种情况下,目标与输入相同,因为我们试图重新创建相同的输出。 `torchvision`包对像素应用了转换和归一化,并将像素值范围从 0 到 255 转换为-1 到 1。我们需要转换回 0 到 255 的范围,因为我们在最后一层使用了 softmax,并且 会在 0 到 255 之间生成概率分布。
到目前为止,我们一直在有监督的学习中工作,其中明确给出了标签,但是在这种情况下,目标与输入相同,因为我们试图重新创建相同的输出。 `torchvision`包对像素应用了转换和归一化,并将像素值范围从 0 到 255 转换为 -1 到 1。我们需要转换回 0 到 255 的范围,因为我们在最后一层使用了 softmax,并且 会在 0 到 255 之间生成概率分布。
##### 门控 PixelCNN
......@@ -262,7 +262,7 @@ causalconv = torch.nn.Conv1d(
bias=False)
```
WaveNet 的完整架构建立在膨胀卷积网络和卷积后门控激活的基础之上。 WaveNet 中的数据流从因果卷积运算开始,这是一种正常的一维卷积,然后传递到膨胀的卷积节点。 WaveNet 图片中的每个白色圆圈(“图 6.9”)是一个扩展的卷积节点。 然后,将正常卷积的数据点传递到膨胀的卷积节点,然后将其独立地通过 Sigmoid门和 tanh 激活。 然后,两个运算的输出通过逐点乘法运算符和 1x1 卷积进行。 WaveNet 使用剩余连接和跳过连接来平滑数据流。 与主流程并行运行的剩余线程通过加法运算与 1x1 卷积的输出合并。
WaveNet 的完整架构建立在膨胀卷积网络和卷积后门控激活的基础之上。 WaveNet 中的数据流从因果卷积运算开始,这是一种正常的一维卷积,然后传递到膨胀的卷积节点。 WaveNet 图片中的每个白色圆圈(“图 6.9”)是一个扩展的卷积节点。 然后,将正常卷积的数据点传递到膨胀的卷积节点,然后将其独立地通过 Sigmoid门和 tanh 激活。 然后,两个运算的输出通过逐点乘法运算符和`1x1`卷积进行。 WaveNet 使用剩余连接和跳过连接来平滑数据流。 与主流程并行运行的剩余线程通过加法运算与`1x1`卷积的输出合并。
![WaveNet](img/B09475_06_13.jpg)
......@@ -270,7 +270,7 @@ WaveNet 的完整架构建立在膨胀卷积网络和卷积后门控激活的基
来源: 《WaveNet:原始音频的生成模型》,Aaron van den Oord 等
“图 6.12”中提供的 WaveNet 的结构图显示了所有这些小组件以及它们如何连接在一起。 跳过连接之后的部分在程序中称为密集层,尽管它不是上一章介绍的密集层。 通常,密集层表示全连接层,以将非线性引入网络并获得所有数据的概览。 但是 WaveNet 的作者发现,正常的致密层可以由一串 ReLU 代替,并且 1x1 卷积可以通过最后的 softmax 层实现更高的精度,该层可以展开为 256 个单位(巨大扇出的 8 位µ律量化) 音频)。
“图 6.12”中提供的 WaveNet 的结构图显示了所有这些小组件以及它们如何连接在一起。 跳过连接之后的部分在程序中称为密集层,尽管它不是上一章介绍的密集层。 通常,密集层表示全连接层,以将非线性引入网络并获得所有数据的概览。 但是 WaveNet 的作者发现,正常的致密层可以由一串 ReLU 代替,并且`1x1`卷积可以通过最后的 softmax 层实现更高的精度,该层可以展开为 256 个单位(巨大扇出的 8 位`µ`律量化) 音频)。
```py
class WaveNetModule(torch.nn.Module):
......@@ -292,7 +292,7 @@ class WaveNetModule(torch.nn.Module):
return output.contiguous()
```
前面的代码块中给出的程序是主要的父 WaveNet 模块,该模块使用所有子组件来创建图形。 `init`定义了三个主要成分,其中是第一个普通卷积,然后是`res_stack`(它是由所有膨胀卷积和 Sigmoid正切门组成的残差连接块)。 然后,最后的`convdensnet` 1x1 卷积的顶部进行。 `forward`引入一个求和节点,依次执行这些模块。 然后,将`convdensnet`创建的输出通过`contiguous()`移动到存储器的单个块。 这是其余网络所必需的。
前面的代码块中给出的程序是主要的父 WaveNet 模块,该模块使用所有子组件来创建图形。 `init`定义了三个主要成分,其中是第一个普通卷积,然后是`res_stack`(它是由所有膨胀卷积和 Sigmoid正切门组成的残差连接块)。 然后,最后的`convdensnet``1x1`卷积的顶部进行。 `forward`引入一个求和节点,依次执行这些模块。 然后,将`convdensnet`创建的输出通过`contiguous()`移动到存储器的单个块。 这是其余网络所必需的。
`ResidualStack`是需要更多说明的模块,它是 WaveNet 架构的核心。 `ResidualStack``ResidualBlock`的层的堆栈。 WaveNet 图片中的每个小圆圈都是一个残差块。 在正常卷积之后,数据到达`ResidualBlock`,如前所述。 `ResidualBlock`从膨胀的卷积开始,并且期望得到膨胀。 因此,`ResidualBlock`决定了架构中每个小圆节点的膨胀因子。 如前所述,膨胀卷积的输出然后通过类似于我们在 PixelCNN 中看到的门的门。
......@@ -465,9 +465,9 @@ def noise(size):
return n.to(device)
```
可以定义一个噪声生成函数,该函数可以生成随机样本(事实证明,这种采样在高斯分布而非随机分布下是有效的,但为简单起见,此处使用随机分布)。 如果 CUDA 可用,我们会将随机产生的噪声从 CPU 内存传输到 GPU 内存,并返回张量,其输出大小为`100`。 因此,生成网络期望输入噪声的特征数量为 100,而我们知道 MNIST 数据集中有 784 个数据点(28x28)。
可以定义一个噪声生成函数,该函数可以生成随机样本(事实证明,这种采样在高斯分布而非随机分布下是有效的,但为简单起见,此处使用随机分布)。 如果 CUDA 可用,我们会将随机产生的噪声从 CPU 内存传输到 GPU 内存,并返回张量,其输出大小为`100`。 因此,生成网络期望输入噪声的特征数量为 100,而我们知道 MNIST 数据集中有 784 个数据点(`28x28`)。
对于生成器,我们具有与判别器类似的结构,但是在最后一层具有 tanh 层,而不是 Sigmoid。 进行此更改是为了与我们对 MNIST 数据进行的归一化同步,以将其转换为-1 到 1 的范围,以便判别器始终获得具有相同范围内数据点的数据集。 生成器中的三层中的每一层都将输入噪声上采样到 784 的输出大小,就像我们在判别器中下采样以进行分类一样。
对于生成器,我们具有与判别器类似的结构,但是在最后一层具有 tanh 层,而不是 Sigmoid。 进行此更改是为了与我们对 MNIST 数据进行的归一化同步,以将其转换为 -1 到 1 的范围,以便判别器始终获得具有相同范围内数据点的数据集。 生成器中的三层中的每一层都将输入噪声上采样到 784 的输出大小,就像我们在判别器中下采样以进行分类一样。
```py
class GeneratorNet(torch.nn.Module):
......@@ -547,7 +547,7 @@ CycleGAN 学习每种分布的模式,并尝试将图像从一种分布映射
在 CycleGAN 中,我们不是从分布中随机采样的数据开始,而是使用来自集合 A(在本例中为一组马)的真实图像。 委托生成器 A 到 B(我们称为 A2B)将同一匹马转换为斑马,但没有将成对的马匹转换为斑马的配对图像。 训练开始时,A2B 会生成无意义的图像。 判别器 B 从 A2B 生成的图像或从集合 B(斑马的集合)中获取真实图像。 与其他任何判别器一样,它负责预测图像是生成的还是真实的。 这个过程是正常的 GAN,它永远不能保证同一匹马转换为斑马。 而是将马的图像转换为斑马的任何图像,因为损失只是为了确保图像看起来像集合 B 的分布; 它不需要与集合 A 相关。为了强加这种相关性,CycleGAN 引入了循环。
然后,从 A2B 生成的图像会通过另一个生成器 B2A,以获得 Cyclic_A。 施加到 Cyclic_A 的损耗是 CycleGAN 的关键部分。 在这里,我们尝试减小 Cyclic_A 和 Input_A 之间的距离。 第二个损失背后的想法是,第二个生成器必须能够生成马,因为我们开始时的分布是马。 如果 A2B 知道如何将马匹映射到斑马而不改变图片中的任何其他内容,并且如果 B2A 知道如何将斑马线映射到匹马而不改变图片中的其他任何东西,那么我们对损失所做的假设应该是正确的。
然后,从 A2B 生成的图像会通过另一个生成器 B2A,以获得`Cyclic_A`。 施加到`Cyclic_A`的损耗是 CycleGAN 的关键部分。 在这里,我们尝试减小`Cyclic_A``Input_A`之间的距离。 第二个损失背后的想法是,第二个生成器必须能够生成马,因为我们开始时的分布是马。 如果 A2B 知道如何将马匹映射到斑马而不改变图片中的任何其他内容,并且如果 B2A 知道如何将斑马线映射到匹马而不改变图片中的其他任何东西,那么我们对损失所做的假设应该是正确的。
![CycleGAN](img/B09475_06_20.jpg)
......@@ -600,7 +600,7 @@ PyTorch 为用户提供了进入网络并进行操作的完全灵活性。 其
实例归一化分别对每个输出批量进行归一化,而不是像“批量归一化”中那样对整个集合进行归一化。 二维实例归一化确实在 4D 输入上实例化归一化,且批量尺寸和通道尺寸为第一维和第二维。 PyTorch 通过传递`affine=True`允许实例规范化层可训练。 参数`track_running_stats`决定是否存储训练循环的运行平均值和方差,以用于评估模式(例如归一化)。 默认情况下,它设置为`False`; 也就是说,它在训练和评估模式下都使用从输入中收集的统计信息。
下图给出了批量规范化和实例规范化的直观比较。 在图像中,数据表示为三维张量,其中 C 是通道,N 是批量,D 是其他维,为简单起见,在一个维中表示。 如图中所示,批量归一化对整个批量中的数据进行归一化,而实例归一化则在两个维度上对一个数据实例进行归一化,从而使批量之间的差异保持完整。
下图给出了批量规范化和实例规范化的直观比较。 在图像中,数据表示为三维张量,其中`C`是通道,`N`是批量,`D`是其他维,为简单起见,在一个维中表示。 如图中所示,批量归一化对整个批量中的数据进行归一化,而实例归一化则在两个维度上对一个数据实例进行归一化,从而使批量之间的差异保持完整。
![CycleGAN](img/B09475_06_21.jpg)
......@@ -608,7 +608,7 @@ PyTorch 为用户提供了进入网络并进行操作的完全灵活性。 其
Source: Group Normalization, Yuxin Wu and Kaiming He
原始 CycleGAN 的生成器在三个卷积块之后使用九个残差块,其中每个卷积块由卷积层,归一化层和激活层组成。 残差块之后是几个转置卷积,然后是最后一层具有 tanh 函数的一个卷积层。 如简单 GAN 中所述,tanh 输出的范围是-1 至 1,这是所有图像的归一化值范围。
原始 CycleGAN 的生成器在三个卷积块之后使用九个残差块,其中每个卷积块由卷积层,归一化层和激活层组成。 残差块之后是几个转置卷积,然后是最后一层具有 tanh 函数的一个卷积层。 如简单 GAN 中所述,tanh 输出的范围是 -1 至 1,这是所有图像的归一化值范围。
残余块的内部是按顺序排列的另一组填充,卷积,归一化和激活单元。 但是`forward`方法与`residueNet`中的求和操作建立了残余连接。 在以下示例中,所有内部块的顺序包装都保存到变量`conv_block`中。 然后,将经过此块的数据与加法运算符一起输入到网络`x`。 此残留连接通过允许信息更容易地双向流动来帮助网络变得稳定:
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册