天天看點

『高性能模型』卷積複雜度以及Inception系列

卷積網絡複雜度分析方法及其在Inception系列網絡中的實際展現

轉載自知乎:卷積神經網絡的複雜度分析

之前的Inception學習部落格:

『TensorFlow』讀書筆記_Inception_V3_上

『TensorFlow』讀書筆記_Inception_V3_下

一、時間複雜度

即模型的運算次數,可用FLOPs衡量,也就是浮點運算次數(FLoating-point OPerations)。

單個卷積層的時間複雜度

      Time~O(M2·K2·Cin·Cout)

M:輸出特征圖邊長

K:卷積核尺寸

C:通道數目

輸出邊長M計算公式為:

      M = (X - K + 2*Padding)//Stride + 1

  • 注1:為了簡化表達式中的變量個數,這裡統一假設輸入和卷積核的形狀都是正方形
  • 注2:嚴格來講每層應該還包含 1 個
    『高性能模型』卷積複雜度以及Inception系列
    參數,這裡為了簡潔就省略了
  • 注3:TensorFlow中SAME形式輸出為(X/Stride)上取整,因為TF中預設總共填充K/2,注意不需要進行2*Padding

下圖展示了單個Cout的上單個點的計算示意,需要重複計算:Cout·每張輸出特征圖上像素數次。

『高性能模型』卷積複雜度以及Inception系列

卷積神經網絡整體複雜度

      Time~O(∑l=1 M2·K2·Cl-1·Cl)

l表示層編号,實質就是對各個層求和。

卷積層實作可以很好的看清實作機理:out層、out長寬、in層循環,循環體内k2級别運算:

def conv2d(img, kernel):
    height, width, in_channels = img.shape
    kernel_height, kernel_width, in_channels, out_channels = kernel.shape
    out_height = height - kernel_height + 1
    out_width = width - kernel_width + 1
    feature_maps = np.zeros(shape=(out_height, out_width, out_channels))
    for oc in range(out_channels):              # Iterate out_channels (# of kernels)
        for h in range(out_height):             # Iterate out_height
            for w in range(out_width):          # Iterate out_width
                for ic in range(in_channels):   # Iterate in_channels
                    patch = img[h: h + kernel_height, w: w + kernel_width, ic]
                    feature_maps[h, w, oc] += np.sum(patch * kernel[:, :, ic, oc])

    return feature_maps
      

二、空間複雜度

空間複雜度(訪存量),嚴格來講包括兩部分:總參數量 + 各層輸出特征圖。

  • 參數量:模型所有帶參數的層的權重參數總量(即模型體積,下式第一個求和表達式)
  • 特征:模型在實時運作過程中每層所計算出的輸出特征圖大小(下式第二個求和表達式)

      Space~O(∑K2·Cl-1·Cl + ∑M2·Cl)

M:輸出特征圖邊長

K:卷積核尺寸

C:通道數目

三、複雜度對模型的影響

時間複雜度決定了模型的訓練/預測時間。如果複雜度過高,則會導緻模型訓練和預測耗費大量時間,既無法快速的驗證想法和改善模型,也無法做到快速的預測。

空間複雜度決定了模型的參數數量。由于次元詛咒的限制,模型的參數越多,訓練模型所需的資料量就越大,而現實生活中的資料集通常不會太大,這會導緻模型的訓練更容易過拟合。

當我們需要裁剪模型時,由于卷積核的空間尺寸通常已經很小(3x3),而網絡的深度又與模型的表征能力緊密相關,不宜過多削減,是以模型裁剪通常最先下手的地方就是通道數。

四、Inception系列優化思路

1、Inception_v1:1*1卷積降維同時優化時間複雜度和空間複雜度

『高性能模型』卷積複雜度以及Inception系列

InceptionV1 借鑒了 Network in Network 的思想,在一個 Inception Module 中構造了四個并行的不同尺寸的卷積/池化子產品(上圖左),有效的提升了網絡的寬度。但是這麼做也造成了網絡的時間和空間複雜度的激增。對策就是添加 1 x 1 卷積(上圖右紅色子產品)将輸入通道數先降到一個較低的值,再進行真正的卷積。

在3*3卷積分支上加入64個1*1卷積前後的時間複雜度對比如下式:

『高性能模型』卷積複雜度以及Inception系列

同理,在5*5卷積分支上加入64個1*1卷積前後的時間複雜度對比如下式:

『高性能模型』卷積複雜度以及Inception系列

整個層的參數量變化如下:

2、Inception_v1:使用GAP(全局平局均池化)代替全連接配接

全連接配接層複雜度分析:X*X的輸入Flatten為X2的輸入,輸出神經元個數可以視為1*1*Cout,則:

      Time~O(12·X2·Cin·Cout)

      Space~O(X2·Cin·Cout + X2·Cin) ~ O(X2·Cin·Cout)

空間複雜度第一部分為權重參數,第二部分為目前輸入大小。順便一提我之前的一個誤區:全連接配接層相對卷積層其運算瓶頸不在時間複雜度,而在空間複雜度,我之前的印象裡把兩者混為一談了。

使用GAP後,首先将Cin·X2的輸入轉化為Cin,然後1*1卷積為Cout:

      Time~O(Cin·Cout)

      Space~O(Cin·Cout + Cin)~ O(Cin·Cout)

Space來說可能有點問題:Cin·X2的原輸入應該還是要存儲的,不過由于不涉及到卷積運算,姑且不細究。

但是注意:GAP會影響收斂速度,不過并不會影響最終的精度。

3、Inception_v2:兩個3*3卷積聯級替代5*5卷積

『高性能模型』卷積複雜度以及Inception系列

兩個3*3卷積聯級的感受野與單個5*5卷積相當,計算公式可見『計算機視覺』感受野和anchor,替換後時間複雜度卻可降低:

『高性能模型』卷積複雜度以及Inception系列

4、Inception_v3:使用N*1和1*N卷積聯級代替N*N卷積

『高性能模型』卷積複雜度以及Inception系列

InceptionV3 中提出了卷積的 Factorization,在確定感受野不變的前提下進一步簡化,複雜度的改善同理可得,不再贅述。

5、Xnception:使用Depth wise Separable Convolution

『高性能模型』卷積複雜度以及Inception系列

Xception 中每個輸入通道隻會被對應的一個卷積核掃描,降低了模型的備援度。對于深度可分離卷積Depthwise Separable 是一個 Depthwise conv 加一個 Pointwise conv,其中 Depthwise 是M2·K2·Cin,Pointwise 是M2·Cin·Cout,即:

      Time~O(M2·K2·Cin + M2·Cin·Cout)