资源 | 对比ResNet: 超深层网络DiracNet的PyTorch实现

选自GitHub

机器之心编译

参与:蒋思源

本文介绍了最近更新的 DiracNet 实现项目,该项目实现了不带跳过连接的超深层网络,并且是对应论文的官方实现。机器之心简要介绍了该项目和论文。

如 ResNet 这样采取了跳过连接(skip-connections)的网络在图像识别基准上实现了非常优秀的性能,但这种网络并体会不到更深层级所带来的优势。因此我们可能会比较感兴趣如何学习非常深的表征,并挖掘深层网络所带来的优势。我们提出了一个简单的权重参数化(weight parameterization)方法,该方法将提升不带跳过连接的深层网络性能,且允许我们训练数百层的深度网络。我们提出来的 DiracNet 非常接近于宽 ResNet 的准确度,但也需要更多的参数。此外,我们发现只有 34 层的 DiracNet 在性能上要优于 ResNet-1000。我们提出的 Dirac 权重参数化在推断时能折叠进一个卷积核,因此它可以轻易地解释为类 VGG 的网络。

下图展示了随层级和宽度的变化,CIFAR-10 准确度的变化。

简介

简而言之,Dirac 参数化就是卷积核权重的求和并通过 Dirac delta 函数缩放:

conv2d(x, alpha * delta + W)

以下是简化后的 PyTorch 伪代码,其展示了我们用于训练 plain DiracNets(带有权重归一化)的函数:

def dirac_conv2d(input, W, alpha, beta)    
    return F.conv2d(input, alpha * dirac(W) + beta * normalize(W))

其中 alpha 和 beta 为缩放标量,normalize 为每一个特征图上的 L2 归一化。此外,我们还使用了 NCReLU(负的 CReLU)非线性激活函数:

def ncrelu(x):    
   return torch.cat([x.clamp(min=0), x.clamp(max=0)], dim=1)

代码

在本项目中,diracconv.py 文件为模块化的 DiracConv 定义、test.py 为单位测试文件、 diracnet-export.ipynb 文件为 ImageNet 预训练模型、 diracnet.py 文件为函数化的模型定义,最后的 train.py 为 ImageNet 训练代码。

依赖库的安装

首先实现本项目的模型需要已安装 PyTorch,但这里并不会详细解释如何安装这个模块。随后我们可以使用 pip 安装 torchnet:

pip install git+https://github.com/pytorch/tnt.git@master

使用 Python 捆绑包安装 OpenCV,即执行命令 conda install -c menpo opencv3(前提已安装 Anaconda),然后使用 OpenCV 转换 torchvision:

pip install git+https://github.com/szagoruyko/vision.git@opencv

最后,安装其它的 Python 包:

pip install -r requirements.txt

在 CIFAR 上训练 DiracNet-34-2 请运行以下命令:

python train.py --save ./logs/diracnets_$RANDOM$RANDOM --depth 34 --width 2

在 ImageNet 上训练 DiracNet-18 请运行以下命令:

python train.py --dataroot ~/ILSVRC2012/ --dataset ImageNet --depth 18 --save ./logs/diracnet_$RANDOM$RANDOM \
                --batchSize 256 --epoch_step [30,60,90] --epochs 100 --weightDecay 0.0001 --lr_decay_ratio 0.1

nn.Module 代码

我们还提供了 DiracConv1d、DiracConv2d 和 DiracConv3d 等 API,它们使用的方法就像 nn.Conv1d、nn.Conv2d 和 nn.Conv3d,只不过我们提供的 API 使用的是 Dirac-parametrization。我们的训练代码并没有使用这些模块,但它十分有助于各位读者快速地实现 Dirac 层级。

预训练模型

我们将批量归一化和 Dirac 参数层级放入了 F.conv2d 的 weight 和 bias 张量中,因此我们的模型就像 VGG 或 AlexNet 那样简单方便地调用,它们都只调用了最基本的非线性和 conv2d 模块。diracnets.ipynb 文件中可以查看模型定义的函数与模块。

下面我们提供了 DiracNet-18-0.75 序列模型的打印输出结果,可作为读者的参考:

Sequential (
  (conv): Conv2d(3, 48, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3))
  (max_pool0): MaxPool2d (size=(3, 3), stride=(2, 2), padding=(1, 1), dilation=(1, 1))
  (group0.block0.ncrelu): NCReLU()
  (group0.block0.conv): Conv2d(96, 48, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (group0.block1.ncrelu): NCReLU()
  (group0.block1.conv): Conv2d(96, 48, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (group0.block2.ncrelu): NCReLU()
  (group0.block2.conv): Conv2d(96, 48, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (group0.block3.ncrelu): NCReLU()
  (group0.block3.conv): Conv2d(96, 48, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (max_pool1): MaxPool2d (size=(2, 2), stride=(2, 2), dilation=(1, 1))
  (group1.block0.ncrelu): NCReLU()
  (group1.block0.conv): Conv2d(96, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (group1.block1.ncrelu): NCReLU()
  (group1.block1.conv): Conv2d(192, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (group1.block2.ncrelu): NCReLU()
  (group1.block2.conv): Conv2d(192, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (group1.block3.ncrelu): NCReLU()
  (group1.block3.conv): Conv2d(192, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (max_pool2): MaxPool2d (size=(2, 2), stride=(2, 2), dilation=(1, 1))
  (group2.block0.ncrelu): NCReLU()
  (group2.block0.conv): Conv2d(192, 192, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (group2.block1.ncrelu): NCReLU()
  (group2.block1.conv): Conv2d(384, 192, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (group2.block2.ncrelu): NCReLU()
  (group2.block2.conv): Conv2d(384, 192, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (group2.block3.ncrelu): NCReLU()
  (group2.block3.conv): Conv2d(384, 192, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (max_pool3): MaxPool2d (size=(2, 2), stride=(2, 2), dilation=(1, 1))
  (group3.block0.ncrelu): NCReLU()
  (group3.block0.conv): Conv2d(384, 384, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (group3.block1.ncrelu): NCReLU()
  (group3.block1.conv): Conv2d(768, 384, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (group3.block2.ncrelu): NCReLU()
  (group3.block2.conv): Conv2d(768, 384,kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (group3.block3.ncrelu): NCReLU()
  (group3.block3.conv): Conv2d(768, 384, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
  (relu): ReLU ()
  (avg_pool): AvgPool2d ()
  (view): Flatten()
  (fc): Linear (384 -> 1000)
)

论文:DiracNets: Training Very Deep Neural Networks Without Skip-Connections

论文地址:https://arxiv.org/abs/1706.00388

我们为神经网络提出了一种新的权重参数化(weight parameterization)方法,这种方法可称之为 Dirac 参数化,它适用于广泛的网络架构。此外,通过使用上面的参数化方法,我们提出了一种新的 plain VGG-like 和 ResNet-like 架构。该架构没有使用任何跳过连接(skip-connections),我们称之为 DiracNet。这些网络可以训练数百层,且在 34 层的时候就超过了 1001 层的 ResNet 性能,且十分接近宽 ResNet(WRN)的准确度。我们应该注意训练 DiracNets 是一种端到端的方法,并不需要任何层级的预训练方法。我们相信该研究是迈向更简单和高效深度神经网络的重要方向。

图 3:a 为带有 Dirac 参数化的 plain 网络收敛情况。b 为带有 ReLU 和 NCReLU 激活函数的 plain Dirac 参数化网络的归一化直方图。

图 6:DiracNet 和 ResNet 在 ImageNet 上的收敛情况。

本文为机器之心编译,转载请联系本公众号获得授权。

原文发布于微信公众号 - 机器之心(almosthuman2014)

原文发表时间:2017-11-14

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏YoungGy

从马尔科夫链到吉布斯采样与PageRank

马尔科夫链表示state的链式关系,下一个state只跟上一个state有关。 吉布斯采样通过采样条件概率分布得到的样本点,近似估计概率分布P(z)P(z)...

74160
来自专栏王小雷

基于Python3 神经网络的实现

基于Python3 神经网络的实现(下载源码) 本次学习是Denny Britz(作者)的Python2神经网络项目修改为基于Python3实现的神经网络(本篇...

291100
来自专栏人工智能LeadAI

卷积神经网络实现多个数字识别

数据集:MNIST 框架:Keras 显卡:NVIDIA GEFORCE 750M 参考:Keras中文文档(http://keras-cn.readthedo...

17520
来自专栏新智元

【深度学习自动上色,数月工作几秒完成】开源神经网络图片上色技术解析

【新智元导读】本文是作者对Reddit社区用户Amir Avni深度学习上色机器人的实现,看完本文后,你也能打造媲美大师级着色效果的自动上色神经网络应用。此外,...

65470
来自专栏ATYUN订阅号

【技术】使用深度学习自动为图像添加字幕(PyTorch)

深度学习现在发展十分迅猛,每天都会出现多种应用程序。而想要了解深度学习的最好方法就是亲自动手。尽可能尝试自己做项目。这将帮助你更深入地了解它们,并帮助你成为更好...

14050
来自专栏ATYUN订阅号

使用Keras的Python深度学习模型的学习率方案

训练神经网络或大型深度学习模型是一项很难的优化任务。传统的训练神经网络的算法称为随机梯度下降。你可以通过在训练中改变学习率来提高性能和提高训练速度。 在这篇文章...

80850
来自专栏非著名程序员

Android二维码扫描开发(二):YUV图像格式详解

? 前一篇提到了,相机返回的是YUV格式的图像数据,那么YUV到底是怎样一种格式呢?本篇将对YUV图像格式进行详细的解释。 上一篇中,我们了解了Android...

481100
来自专栏Small Code

【Python | TensorBoard】用 PCA 可视化 MNIST 手写数字识别数据集

Principal component analysis (PCA) is a statistical procedure that uses an orth...

66780
来自专栏ATYUN订阅号

Python机器学习的练习七:K-Means聚类和主成分分析

这部分练习涵盖两个吸引人的话题:K-Means聚类和主成分分析(PCA),K-Means和PCA都是无监督学习技术的例子,无监督学习问题没有为我们提供任何标签或...

63170
来自专栏ATYUN订阅号

评估Keras深度学习模型的性能

Keras是Python中一个的强大而易用的库,主要用于深度学习。在设计和配置你的深度学习模型时,需要做很多决策。大多数决定必须通过反复试错的方法来解决,并在真...

58880

扫码关注云+社区

领取腾讯云代金券