1. 程式人生 > >【深度學習-CNN】CNN中的引數與計算量

【深度學習-CNN】CNN中的引數與計算量

一個卷積神經網路的基本構成一般有卷積層(convolutional layer)、池化層(pooling layer)、全連線層(fully connection layer)。本文以caffe中的LeNet-5為例,分析卷積層和全連線層的引數數量和計算量情況。

卷積層的基本原理就是影象的二維卷積,即將一個二維卷積模板先翻轉(旋轉180°),再以步長stride進行滑動,滑動一次則進行一次模板內的對應相乘求和作為卷積後的值。在CNN的卷積層中,首先是卷積層維度提升到三維、四維,與二維圖分別進行卷積,然後合併,這裡的卷積一般是相關操作,即不做翻轉。具體如下圖所示:

.

上圖中左邊的一幅輸入圖的三個通道,中間是卷積層,尺寸為3*3*3*2,這裡就是三維卷積,得到的特徵圖還是一個通道,有兩個三維卷積得到兩個featuremap。

我們以caffe中的LeNet-5的lenet.prototxt為例。

一、卷積層

name: "LeNet"
layer {
  name: "data"
  type: "Input"
  top: "data"
  input_param { shape: { dim: 64 dim: 1 dim: 28 dim: 28 } }
}
layer {
  name: "conv1"
  type: "Convolution"
  bottom: "data"
  top: "conv1"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  convolution_param {
    num_output: 20
    kernel_size: 5
    stride: 1
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "pool1"
  type: "Pooling"
  bottom: "conv1"
  top: "pool1"
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}

可以看到整個CNN的輸入是28×28的灰度圖,batchsize是64。第一個卷積層是5×5×20的尺寸,即卷積核為5×5,有20個。第一個卷積層之後有一個max pooling 層。下面我們來看一下日誌檔案。
I0405 18:22:46.263157 13500 db_lmdb.cpp:40] Opened lmdb ./mnist_train_lmdb
I0405 18:22:46.366945 13112 data_layer.cpp:41] output data size: 64,1,28,28
I0405 18:22:46.369945 13112 net.cpp:150] Setting up mnist
I0405 18:22:46.369945 13112 net.cpp:157] Top shape: 64 1 28 28 (50176)
I0405 18:22:46.369945 13112 net.cpp:157] Top shape: 64 (64)
I0405 18:22:46.369945 13112 net.cpp:165] Memory required for data: 200960
I0405 18:22:46.369945 13112 layer_factory.hpp:77] Creating layer conv1
I0405 18:22:46.369945 13112 net.cpp:100] Creating Layer conv1
I0405 18:22:46.369945 13112 net.cpp:444] conv1 <- data
I0405 18:22:46.369945 13112 net.cpp:418] conv1 -> conv1
I0405 18:22:46.372946 11592 common.cpp:36] System entropy source not available, using fallback algorithm to generate seed instead.
I0405 18:22:48.350821 13112 net.cpp:150] Setting up conv1
I0405 18:22:48.351820 13112 net.cpp:157] Top shape: 64 20 24 24 (737280)
I0405 18:22:48.351820 13112 net.cpp:165] Memory required for data: 3150080
I0405 18:22:48.351820 13112 layer_factory.hpp:77] Creating layer pool1
I0405 18:22:48.351820 13112 net.cpp:100] Creating Layer pool1
I0405 18:22:48.351820 13112 net.cpp:444] pool1 <- conv1
I0405 18:22:48.351820 13112 net.cpp:418] pool1 -> pool1
I0405 18:22:48.351820 13112 net.cpp:150] Setting up pool1
I0405 18:22:48.351820 13112 net.cpp:157] Top shape: 64 20 12 12 (184320)
I0405 18:22:48.351820 13112 net.cpp:165] Memory required for data: 3887360
輸入為28×28的單通道圖,經過一層卷積以後輸出為24×24×20,因為邊界處理所以卷積完尺寸為28-5+1 = 24。卷積核的數量為20,所以conv-1的尺寸如上。再經過一層pooling層尺寸為12×12×20。則單樣本前向傳播計算量為:5×5×24×24×20 = 288 000,實際計算量還應乘以batchsize = 64。卷積層引數數量為:5×5×20 = 500。計算量和引數比為:288000/500 = 576.

下面看一下全連線層的情況。

二、全連線層

layer {
  name: "ip1"
  type: "InnerProduct"
  bottom: "pool2"
  top: "ip1"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  inner_product_param {
    num_output: 500
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
第一個全連線層的輸出元素個數500。
I0405 18:22:48.366821 13112 net.cpp:157] Top shape: 64 50 4 4 (51200)
I0405 18:22:48.366821 13112 net.cpp:165] Memory required for data: 4911360
I0405 18:22:48.366821 13112 layer_factory.hpp:77] Creating layer ip1
I0405 18:22:48.367826 13112 net.cpp:100] Creating Layer ip1
I0405 18:22:48.367826 13112 net.cpp:444] ip1 <- pool2
I0405 18:22:48.367826 13112 net.cpp:418] ip1 -> ip1
I0405 18:22:48.375823 13112 net.cpp:150] Setting up ip1
I0405 18:22:48.375823 13112 net.cpp:157] Top shape: 64 500 (32000)
I0405 18:22:48.375823 13112 net.cpp:165] Memory required for data: 5039360
I0405 18:22:48.375823 13112 layer_factory.hpp:77] Creating layer relu1
I0405 18:22:48.375823 13112 net.cpp:100] Creating Layer relu1
I0405 18:22:48.375823 13112 net.cpp:444] relu1 <- ip1
I0405 18:22:48.375823 13112 net.cpp:405] relu1 -> ip1 (in-place)
I0405 18:22:48.376822 13112 net.cpp:150] Setting up relu1
I0405 18:22:48.376822 13112 net.cpp:157] Top shape: 64 500 (32000)
I0405 18:22:48.376822 13112 net.cpp:165] Memory required for data: 5167360
上圖是全連線層部分的日誌檔案,卷積部分得到的featuremap為4×4×50,全連線部分是將featuremap展開成一維向量再與全連線相連。所以單樣本前向傳播計算量為:4×4×50×500 = 400 000,引數數量為4×4×50×500 = 400 000。在全連線中計算量和引數比始終為1,就是源於全連線的特性。

三、分析對比

conv-1的計算量引數比為576,ip1的計算量引數比為1。
conv-1的計算量是ip1的0.72,而引數是0.00125。

也就是說卷積層主要是大大減少了連線引數,所以在CNN網路中一般卷積層引數量佔比小,計算量佔比大,而全連線中引數量佔比大,計算量佔比小。大致卷積層的計算量是全連線的20%。

所以我們需要減少網路引數、權值裁剪時主要針對全連線層;進行計算優化時,重點放在卷積層。

卷積層的優化方法:

1. Low rank(低秩):(單層到多層)SVD分解fc層和卷積核,tensor展開。

2. Pruning(剪枝):去掉某些神經元連線訓練找到重要的連線。

3. Quantization(量化)權值量化,霍夫曼編碼,codebook編碼,hashed-net,PQ-CNN。

4. Fixed-point/binary net,BNN。

CNN的發展方向:

1.小--模型有效且引數少

   代表方法:NIN(network in network)

2.快--執行速度快

   matrix decomposition、pruning、硬體提升

3.準--與大模型有相當的準確率

    cross-layer regularization、micro-structures
   從VGG, GoogleNet,ResNet的演變,很有可能是因為卷積核趨近與最小的3*3與1*1。
   所以未來CNN的發展可能是fully 1*1 convolutional layer network?
   即1×1 network + Spatial Contexts + Cross-layer contexts。