Resnet的有趣变种:WRN

介绍

深度学习发展至今,通过增加模型深度来加强模型的表达能力已经成为行业共识。Resnet网络是眼下最为成功,应用最为广泛的一种深度学习模型。Residual block中identity mapping的引入,使得模型可以将深度恣意扩展到很深,它直接将原来的数十层网络伸展到了数百乃至上千层。

不过深度Resnet网络也有潜在的隐忧。虽然说它的模型可通过不断增加深度来获得能力提升(即分类准备性能提高),但愈到后期,靠单纯增加模型层数换来的边际性能提升愈低。

来自巴黎大学的作者试图对Residual learning进行一番透彻的再思考,他们对Residual block的组成,里面的层结构,层数,层宽等进行了广泛的实验,最终他们表明加宽Resnet有时候比加深它带来的边际性能提升要更多。

当然加宽Residual block意味着会带来训练参数数目平方级数目的增加,同时训练参数数目过多也会导致模型易陷入overfitting的陷阱。作者通过在加宽后的Residual block里面插入Dropout层有效地避免了overfitting问题。最后多个数据集上的实验表明他们提出的Wide Residual network (WRN)可取得比那些细高的original Residual network更高的分类精度,同时也拥有着更快的训练速度。

WRN所设计的一些实验

作者试图对Residual block的功能进行透彻的了解以寻找出一种具有更优表达能力的block。而如果要扩展Residual block的能力一般会从以下三个方面着手。

  • 在block里使用更多的Conv层,即enhance 整体网络模型里面的sub-network,局部加深block;
  • 增加Conv的Output channels数目即使用更多的conv filters进行计算,所谓的增宽block;
  • 使用更大的Conv filter size;(因为3x3的filter size已在诸多研究中被证明极其有效,因此作者打算继续使用3x3的conv,并不对这一问题进行更多尝试。)
Residual_block的各种类型表示

Residual block里面使用的conv层次结构

以B(M)来表示Residual block,其中M表示block里所含conv层的kernel size list;比如B(3,1)表示Block里先后包含两个分别为3x3与1x1大小的Conv层。作者不考虑bottleneck模块的使用,因此block里面所有的conv层有着相同的OC(output channels)输出。以下为实验中所考虑的几种block结构。

  • B(3;3) - original «basic» block
  • B(3;1;3) - with one extra 1×1 layer
  • B(1;3;1) - with the same dimensionality of all convolutions, «straightened» bottleneck
  • B(1;3) - the network has alternating 1×1 - 3×3 convolutions everywhere
  • B(3;1) - similar idea to the previous block
  • B(3;1;1) - Network-in-Network style block

下图为以上各个结构最终能够获得的分类结果比较(注意在实验时作者为保证训练所用参数相同,因此不同类型block构成的网络的深度会有不同)。可见B(3,3)能取得最好的结果,这也证明了常用Residual block的有效性。B(3,1,3)与B(3,1)性能略差,但速度却更快。接下来的实验中,作者保持了使用B(3,3)这种Residual block结构。

不同Residual_block内部表示所具有的结果对比

Residual block中的conv层数

以l表示单个Residual block里面conv层的数目,以d表示整体网络所具有的residual blocks的数目。通过保持整体训练所用参数不变,作者研究、分析了residual block内conv层数目不同所带来的性能结果差异。结果可见下图,从中我们能够看出residual block里面包含2个conv层可带来最优的分类结果性能。

单个Residual_block内不同conv层数对性能的影响

Residual block内宽度

以k来表示Residual block的宽度因子,并以k=1作为原始resnet网络中的宽度。通过增加k来加宽residual blocks,并保持整体可训练参数数目不变,作者进行了广泛的实验。结果表明加大Resnet的宽度可带来比加大其深度更大的边际性能提升。具体结果可见下图。

Residual_block宽度对模型性能的影响

Residual block中Dropout的引入

一味加宽Residual block势必会带来训练参数的激增,为了避免模型陷入过拟合的陷阱,作者试着在Residual block中引入了dropout。另外作者实验表明将Dropout加入在conv层之后比加入在identity mapping连接上可带来更好的效果。因此这里引入的Dropout被放在了Conv出来后的ReLu之后。下图中的结果反映出了Dropout带来的性能提升。

Dropout引入对性能的影响

实验结果

下图反映了与传统的细高Resnet相比,矮胖WRN可具有更好的精度,并且在训练的全程中保持着对Resnet的碾压态势。

深度Resnet与WRN之间的训练过程比较

下图则反映了WRN中所使用的大Tensor计算更有益于GPU计算能力的发挥。

WRN相对传统Resnet在计算速率上的优势

代码分析

以下为作者在Torch框架上实现的构建WRN的过程。我们可看到作者Residual block里面的基本结构是BN -> ReLU -> Conv. 而如果需要加入Dropout的话则是BN -> ReLU -> Dropout -> Conv.

local function createModel(opt)
   assert(opt and opt.depth)
   assert(opt and opt.num_classes)
   assert(opt and opt.widen_factor)

   local function Dropout()
      return nn.Dropout(opt and opt.dropout or 0,nil,true)
   end

   local depth = opt.depth

   local blocks = {}

   local function wide_basic(nInputPlane, nOutputPlane, stride)
      local conv_params = {
         {3,3,stride,stride,1,1},
         {3,3,1,1,1,1},
      }
      local nBottleneckPlane = nOutputPlane

      local block = nn.Sequential()
      local convs = nn.Sequential()

      for i,v in ipairs(conv_params) do
         if i == 1 then
            local module = nInputPlane == nOutputPlane and convs or block
            module:add(SBatchNorm(nInputPlane)):add(ReLU(true))
            convs:add(Convolution(nInputPlane,nBottleneckPlane,table.unpack(v)))
         else
            convs:add(SBatchNorm(nBottleneckPlane)):add(ReLU(true))
            if opt.dropout > 0 then
               convs:add(Dropout())
            end
            convs:add(Convolution(nBottleneckPlane,nBottleneckPlane,table.unpack(v)))
         end
      end
      local shortcut = nInputPlane == nOutputPlane and
         nn.Identity() or
         Convolution(nInputPlane,nOutputPlane,1,1,stride,stride,0,0)
      return block
         :add(nn.ConcatTable()
            :add(convs)
            :add(shortcut))
         :add(nn.CAddTable(true))
   end

   -- Stacking Residual Units on the same stage
   local function layer(block, nInputPlane, nOutputPlane, count, stride)
      local s = nn.Sequential()

      s:add(block(nInputPlane, nOutputPlane, stride))
      for i=2,count do
         s:add(block(nOutputPlane, nOutputPlane, 1))
      end
      return s
   end

   local model = nn.Sequential()
   do
      assert((depth - 4) % 6 == 0, 'depth should be 6n+4')
      local n = (depth - 4) / 6

      local k = opt.widen_factor
      local nStages = torch.Tensor{16, 16*k, 32*k, 64*k}

      model:add(Convolution(3,nStages[1],3,3,1,1,1,1)) -- one conv at the beginning (spatial size: 32x32)
      model:add(layer(wide_basic, nStages[1], nStages[2], n, 1)) -- Stage 1 (spatial size: 32x32)
      model:add(layer(wide_basic, nStages[2], nStages[3], n, 2)) -- Stage 2 (spatial size: 16x16)
      model:add(layer(wide_basic, nStages[3], nStages[4], n, 2)) -- Stage 3 (spatial size: 8x8)
      model:add(SBatchNorm(nStages[4]))
      model:add(ReLU(true))
      model:add(Avg(8, 8, 1, 1))
      model:add(nn.View(nStages[4]):setNumInputDims(3))
      model:add(nn.Linear(nStages[4], opt.num_classes))
   end

   utils.DisableBias(model)
   utils.testModel(model)
   utils.MSRinit(model)
   utils.FCinit(model)
   -- model:get(1).gradInput = nil

   return model
end

return createModel

参考文献

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容