論文地址:MobileNetV2: Inverted Residuals and Linear Bottleneckshtml
前文連接:『高性能模型』深度可分離卷積和MobileNet_v1python
Moblienet V2文中提出,假設在2維空間有一組由 個點組成的螺旋線 數據,經隨機矩陣 映射到 維並進行ReLU運算,即:算法
再經過 矩陣的廣義逆矩陣 將 映射回2維空間:網絡
對比 和 發現,當映射維度 時,數據坍塌;當 時,數據基本被保存。雖然這不是嚴格的數學證實,可是至少說明:channel少的feature map不該後接ReLU,不然會破壞feature map。post
簡單說一下上圖:對於一個輸入圖像,首先經過一個隨機矩陣T將數據轉換爲n維,而後對這n維數據進行ReLU操做,最後再使用T的逆矩陣轉換回來,實驗發現當n很小的時候,後面接ReLU非線性變換的話會致使不少信息的丟失,並且維度越高還原的圖片和原圖越類似。性能
在神經網絡訓練中若是節點的值變爲0就會「死掉」。由於ReLU對0值的梯度是0,後續不管怎麼迭代這個節點的值都不會恢復了。而經過ResNet結構的特徵複用,能夠很大程度上緩解這種特徵退化問題(這也從一個側面說明ResNet爲什麼好於VGG)。另外,通常狀況訓練網絡使用的是float32浮點數;當使用低精度的float16時,這種特徵複用能夠更加有效的減緩退化。spa
理解以前的問題後看,其實Mobilenet V2使用的基本卷積單元結構有如下特色:設計
Inverted residuals 能夠認爲是residual block的拓展,其重點聚焦在殘差網絡各層的層數,進入block後會先將特徵維數放大,而後再壓縮回去,呈現梭子的外形,而傳統殘差設計是沙漏形,下面是MobileNetV一、MobileNetV2 和ResNet微結構對比:htm
下面則對比了近年來比較先進的壓縮網絡子模塊:blog
能夠看到MobileNetV2 和ResNet基本結構很類似。不過ResNet是先降維(0.25倍)、提特徵、再升維。而MobileNetV2 則是先升維(6倍)、提特徵、再降維。、
注:模型中使用 ReLU6 做爲非線性層,在低精度計算時能壓縮動態範圍,算法更穩健。
ReLU6 定義爲:f(x) = min(max(x, 0), 6),詳見 tf.nn.relu6 API
至於Linear Bottlenecks,論文中用不少公式表達這個思想,可是實現上很是簡單,就是在MobileNetV2微結構中第二個PW後無ReLU6,對於低維空間而言,進行線性映射會保存特徵,而非線性映射會破壞特徵,實際代碼以下:
def _bottleneck(inputs, nb_filters, t): x = Conv2D(filters=nb_filters * t, kernel_size=(1,1), padding='same')(inputs) x = Activation(relu6)(x) x = DepthwiseConv2D(kernel_size=(3,3), padding='same')(x) x = Activation(relu6)(x) x = Conv2D(filters=nb_filters, kernel_size=(1,1), padding='same')(x) # do not use activation function if not K.get_variable_shape(inputs)[3] == nb_filters: inputs = Conv2D(filters=nb_filters, kernel_size=(1,1), padding='same')(inputs) outputs = add([x, inputs]) return outputs
相對應的,主結構堆疊上面的block 便可,下面是一個簡單的版本,
def MobileNetV2_relu(input_shape, k): inputs = Input(shape = input_shape) x = Conv2D(filters=32, kernel_size=(3,3), padding='same')(inputs) x = _bottleneck_relu(x, 8, 6) x = MaxPooling2D((2,2))(x) x = _bottleneck_relu(x, 16, 6) x = _bottleneck_relu(x, 16, 6) x = MaxPooling2D((2,2))(x) x = _bottleneck_relu(x, 32, 6) x = GlobalAveragePooling2D()(x) x = Dense(128, activation='relu')(x) outputs = Dense(k, activation='softmax')(x) model = Model(inputs, outputs) return model
原文網絡結構以下: