GoogLeNet(Inception)基礎概念
1.簡介
GoogLeNet是2014年ILSVRC挑戰賽排名第一的演算法。與其他進一步加深神經網路的寬度和深度的網路結構不同,GoogLeNet團隊提出了一種Inception網路結構,就是構造一種“基礎神經元”結構,來搭建一個稀疏性、高計算效能的網路結構。
優點:克服了深層次神經網路的帶來的過擬合、難以計算訓練的問題。
2.Inception網路結構
上述就是一個最原始的Inception結構,簡單來說:與常規的神經網路將卷積層串聯起來相比, Inception 結構是將不同的卷積層通過井聯的方式結合在一起,如上圖:分別使用了邊長為
但是,在上述結構中:所有的卷積核都在上一層的所有輸出上來做,經過3×3、5x5的卷積,會使得特徵圖的引數過多,計算量就太大。為了避免這種情況,在3x3前、5x5前、max pooling後分別加上了1x1的卷積核,主要目的是為了減少維度,以及修正線性啟用,這也就形成了Inception v1的網路結構。
(減少維度舉例說明:
輸入的feature map是28x28x192,設1x1卷積通道為64, 3x3卷積通道為128, 5x5卷積通道為32,如圖原始結構,那麼卷積核引數為:
而對3x3和5x5卷積層前分別加入了通道數為96、16的1x1卷積層,引數就成了:1x1x192x64+(1x1x192x96+3x3x96x128)+(1x1x192x16+5x5x16x32)=215040。整個引數大約減少了一半。)
該架構的一個有用的方面是它允許顯著增加每個階段的單元數量,而不會在後面的階段出現計算複雜度不受控制的爆炸。這是在尺寸較大的卷積核進行代價大的卷積之前通過普遍使用降維實現的。此外,設計遵循了實踐直覺,即視覺資訊應該在不同的尺度上處理然後聚合,為的是下一階段可以從不同尺度同時抽象特徵。
3.GoogLeNet
(“#3×3 reduce”和“#5×5 reduce”表示在3×3和5×5卷積之前,使用的1×1濾波器降維;所有的卷積均使用線性啟用函式)
輸入:224×224×3的RGB影象(均值0處理)
第一層(卷積):
7×7的卷積核(步長為2,64通道),輸出112×112×64;
3×3的max pooling層(步長為2),輸出56×56×64
第二層(卷積):
3×3的卷積核(步長1,192通道),輸出56×56×192;
3×3的max pooling層(步長為2),輸出28×28×192
第三層(Inception 3a):
分為4個分支:
(1)1×1的卷積核(64通道),輸出就是28×28×64;
(2)1×1的卷積核(96通道)降維,然後3×3的卷積核(128通道),輸出28×28×128
(3)1×1的卷積核(16通道)降維,然後5×5的卷積核(32通道),輸出28×28×32
(4)3×3的pool層,然後經過1×1的卷積核(通道32),輸出28×28×32
以下由此類推...
最終的網路模型如下:
(輔助分類器的分類結果會乘以一個權重加到最終的分類結果上)
4. 程式碼參考
用tensorflow實現一個Inception:
1 slim= tf.contrib.slim 2 3 net = slim.conv2d (Input, 32 , [3 , 3]) 4 5 # slim.arg_scope 函式可以用於設定預設的引數取值 6 7 with slim.arg_scope ( [slim.conv2d, slim .max_pool2d, slim.avg_pool2d), 8 9 stride=1, padding=’VALID’): 10 11 net=上-層的輸出節點矩陣 12 13 with tf .variable_scope ( 'Mixed_7c ’): 14 15 #第一條路徑 16 17 with tf.variable_scope(’Branch_0’): 18 19 #實現一個過濾器邊長1,深度320的卷積層 20 21 branch_0= slim.conv2d(net,320,[1 , 1] scope=’Conv2d_0a_1*1’) 22 23 # Inception 模組中第二條路徑。這條計算路徑上的結構本身也是一個 Inception 結構。 24 25 with tf.variable_scope (’Branch_1’): 26 27 branch_1 = slim.conv2d(net,384 , [1,1], scope=’Conv2d_0a_1*1') 28 29 # tf.concat函式可以將多個矩陣拼接起來.tf.concat函式的第一個引數指定了拼接的維度,這裡給出的“ 3 ”代表了矩陣是在深度這個維度上進行拼接。 30 31 branch_1 = tf.concat(3 , [slim.conv2d(branch_1 , 384 , [1 , 3], scope='Conv2d_0b_1*3 ’),slim.conv2d(branch_1, 384, [3 , 1], scope= ’Conv2d_0c_3*1 ’)]) 32 33 # Inception 模組中第三條路徑 34 35 with tf .variable_scope ( ’ Branch_2 ’): 36 37 branch_2 = slim.conv2d(net, 448, [1, 1] , scope=’ Conv2d_0a_1*1 ’) 38 39 branch_2 = slim.conv2d(branch_2 , 384 , [3 , 3], scope= ’ Conv2d_0b_3*3 ’) 40 41 branch_2 = tf.concat(3 , [slim.conv2d(branch_2 , 384 ,[1, 3] , scope=’ Conv2d_0c_1*3 ’,slim.conv2d(branch_2, 384 ,[3 , 1], scope=’ Conv2d_0d_3*1’) ]) 42 43 # Inception 模組中第四條路徑 44 45 with tf.variable scope (’Branch_3 ’): 46 47 branch_3 = slim .avg_pool2d(net,[3, 3] , scope=’AvgPool_0a_3*3 ’) 48 49 branch_3 = slim.conv2d(branch_3,192 , [1, 1],scope=’Conv2d_0b_1*1’) 50 51 #當前Inceptio模組的最後輸出是由上面 4 個計算結果拼攘得到的 52 53 net = tf . concat (3, [branch_0 , branch_1, branch_2 , branch_3])