(四)卷積神經網路 -- 12 稠密連線網路(DenseNet)
12. 稠密連線網路(DenseNet)
ResNet中的跨層連線設計引申出了數個後續工作,稠密連線網路(DenseNet)就是其中之一。
DenseNet與ResNet的主要區別,如下圖所示:
圖中將部分前後相鄰的運算抽象為模組A和模組B。
與ResNet的主要區別在於:
DenseNet裡模組B的輸出,並非是ResNet那樣和模組A的輸出相加,而是在通道維上連結。
由此,模組A的輸出可以直接傳入模組B後面的層。
在這個設計裡,模組A直接跟模組B後面的所有層連線在了一起。這也是它被稱為“稠密連線”的原因。
DenseNet的主要構建模組是稠密塊(dense block)和過渡層(transition layer)。
前者定義了輸入和輸出是如何連結的,後者則用來控制通道數,使之不過大。
12.1 稠密塊
DenseNet使用了ResNet改良版的“批量歸一化、啟用和卷積”結構,該結構的實現在BottleNeck
函式中:
class BottleNeck(Layer):
def __init__(self, growth_rate, drop_rate):
super(BottleNeck, self).__init__()
self.bn1 = BatchNormalization()
self.conv1 = Conv2D(filters=4 * growth_rate, kernel_size=1, padding="same", strides=1)
self.bn2 = BatchNormalization()
self.conv2 = Conv2D(filters=growth_rate, kernel_size=3, padding="same", strides=1)
self.dropout = Dropout(rate=drop_rate)
self.listLayers = [self.bn1,
Activation("relu"),
self.conv1,
self.bn2,
Activation("relu"),
self.conv2,
self.dropout]
def call(self, x):
y = x
for layer in self.listLayers.layers:
y = layer(y)
y = concatenate([x,y], axis=-1)
return y
其中,在前向計算時,將每塊的輸入和輸出在通道維上連結。
稠密塊由多個BottleNeck
組成,每塊使用相同的輸出通道數:
class DenseBlock(Layer):
def __init__(self, num_layers, growth_rate, drop_rate=0.5):
super(DenseBlock, self).__init__()
self.num_layers = num_layers
self.growth_rate = growth_rate
self.drop_rate = drop_rate
self.listLayers = []
for _ in range(num_layers):
self.listLayers.append(BottleNeck(growth_rate=self.growth_rate, drop_rate=self.drop_rate))
def call(self, x):
for layer in self.listLayers.layers:
x = layer(x)
return x
示例:定義一個有2個輸出通道數為10的卷積塊。
使用通道數為3的輸入時,將得到通道數為3+2×10=23的輸出。
卷積塊的通道數控制了輸出通道數相對於輸入通道數的增長,因此也被稱為增長率(growth rate)。
blk = DenseBlock(2, 10)
X = tf.random.uniform((4, 8, 8, 3))
Y = blk(X)
print(Y.shape)
(4, 8, 8, 23)
12.2 過渡層
由於每個稠密塊都會帶來通道數的增加,使用過多則會帶來過於複雜的模型。
過渡層用來控制模型複雜度。
它通過1×1卷積層來減小通道數,並使用步幅為2的平均池化層減半高和寬,從而進一步降低模型複雜度。
class TransitionLayer(Layer):
def __init__(self, out_channels):
super(TransitionLayer, self).__init__()
self.bn = BatchNormalization()
self.conv = Conv2D(filters=out_channels, kernel_size=1, padding="same", strides=1)
self.pool = MaxPool2D(pool_size=(2, 2), padding="same", strides=2)
def call(self, inputs):
x = self.bn(inputs)
x = relu(x)
x = self.conv(x)
x = self.pool(x)
return x
對上一個例子中稠密塊的輸出使用通道數為10的過渡層。
此時輸出的通道數減為10,高和寬均減半。
blk = TransitionLayer(10)
blk(Y).shape
TensorShape([4, 4, 4, 10])
12.3 DenseNet模型
DenseNet首先使用同ResNet的單卷積層和最大池化層。
類似於ResNet接下來使用的4個殘差塊,DenseNet使用的是4個稠密塊。
同ResNet,可以設定每個稠密塊使用多少個卷積層。這裡設為4,從而與上一節的ResNet-18保持一致。
稠密塊裡的卷積層通道數(即增長率)設為32,所以每個稠密塊將增加4*32=128個通道。
ResNet裡通過步幅為2的殘差塊在每個模組之間減小高和寬。使用過渡層來減半高和寬,並減半通道數。
class DenseNet(Model):
def __init__(self, num_init_features, growth_rate, block_layers, compression_rate, drop_rate):
super(DenseNet, self).__init__()
self.conv = Conv2D(filters=num_init_features, kernel_size=7, padding="same", strides=2)
self.bn = BatchNormalization()
self.pool = MaxPool2D(pool_size=(3, 3), padding="same", strides=2)
self.num_channels = num_init_features
self.dense_block_1 = DenseBlock(num_layers=block_layers[0], growth_rate=growth_rate, drop_rate=drop_rate)
self.num_channels += growth_rate * block_layers[0]
self.num_channels = compression_rate * self.num_channels
self.transition_1 = TransitionLayer(out_channels=int(self.num_channels))
self.dense_block_2 = DenseBlock(num_layers=block_layers[1], growth_rate=growth_rate, drop_rate=drop_rate)
self.num_channels += growth_rate * block_layers[1]
self.num_channels = compression_rate * self.num_channels
self.transition_2 = TransitionLayer(out_channels=int(self.num_channels))
self.dense_block_3 = DenseBlock(num_layers=block_layers[2], growth_rate=growth_rate, drop_rate=drop_rate)
self.num_channels += growth_rate * block_layers[2]
self.num_channels = compression_rate * self.num_channels
self.transition_3 = TransitionLayer(out_channels=int(self.num_channels))
self.dense_block_4 = DenseBlock(num_layers=block_layers[3], growth_rate=growth_rate, drop_rate=drop_rate)
self.avgpool = GlobalAvgPool2D()
self.fc = Dense(units=10, activation=softmax)
def call(self, inputs):
x = self.conv(inputs)
x = self.bn(x)
x = relu(x)
x = self.pool(x)
x = self.dense_block_1(x)
x = self.transition_1(x)
x = self.dense_block_2(x)
x = self.transition_2(x)
x = self.dense_block_3(x)
x = self.transition_3(x,)
x = self.dense_block_4(x)
x = self.avgpool(x)
x = self.fc(x)
return x
def densenet():
return DenseNet(num_init_features=64, growth_rate=32, block_layers=[4,4,4,4], compression_rate=0.5, drop_rate=0.5)
mynet=densenet()
每個子模組的輸出維度:
X = tf.random.uniform(shape=(1, 96, 96 , 1))
for layer in mynet.layers:
X = layer(X)
print(layer.name, 'output shape: ', X.shape)
conv2d_81 output shape: (1, 48, 48, 64)
batch_normalization_81 output shape: (1, 48, 48, 64)
max_pooling2d_9 output shape: (1, 24, 24, 64)
dense_block_10 output shape: (1, 24, 24, 192)
transition_layer_7 output shape: (1, 12, 12, 96)
dense_block_11 output shape: (1, 12, 12, 224)
transition_layer_8 output shape: (1, 6, 6, 112)
dense_block_12 output shape: (1, 6, 6, 240)
transition_layer_9 output shape: (1, 3, 3, 120)
dense_block_13 output shape: (1, 3, 3, 248)
global_average_pooling2d output shape: (1, 248)
dense output shape: (1, 10)
參考
相關文章
- 卷積神經網路四種卷積型別卷積神經網路型別
- (四)卷積神經網路 -- 8 網路中的網路(NiN)卷積神經網路
- 卷積神經網路卷積神經網路
- 卷積神經網路概述卷積神經網路
- 解密卷積神經網路!解密卷積神經網路
- 5.2.1 卷積神經網路卷積神經網路
- 卷積神經網路CNN卷積神經網路CNN
- 卷積神經網路-AlexNet卷積神經網路
- 卷積神經網路-1卷積神經網路
- 卷積神經網路-2卷積神經網路
- 卷積神經網路-3卷積神經網路
- 卷積神經網路鼻祖LeNet網路分析卷積神經網路
- 全卷積神經網路FCN卷積神經網路
- 深度剖析卷積神經網路卷積神經網路
- 第四周:卷積神經網路 part 3卷積神經網路
- 【深度學習篇】--神經網路中的卷積神經網路深度學習神經網路卷積
- CNN神經網路之卷積操作CNN神經網路卷積
- 卷積神經網路 part2卷積神經網路
- 14 卷積神經網路(進階)卷積神經網路
- 卷積神經網路(CNN)詳解卷積神經網路CNN
- 何為神經網路卷積層?神經網路卷積
- Tensorflow-卷積神經網路CNN卷積神經網路CNN
- 卷積神經網路學習筆記——Siamese networks(孿生神經網路)卷積神經網路筆記
- 卷積神經網路:Convolutional Neural Networks(CNN)卷積神經網路CNN
- 卷積神經網路(Convolutional Neural Network,CNN)卷積神經網路CNN
- 直白介紹卷積神經網路(CNN)卷積神經網路CNN
- 卷積神經網路—基本部件(2)卷積神經網路
- 卷積神經網路-啟用函式卷積神經網路函式
- 深度學習三:卷積神經網路深度學習卷積神經網路
- 一文看懂卷積神經網路卷積神經網路
- 神經網路之卷積篇:詳解經典網路(Classic networks)神經網路卷積
- 吳恩達《卷積神經網路》課程筆記(1)– 卷積神經網路基礎吳恩達卷積神經網路筆記
- 神經網路之卷積篇:詳解單層卷積網路(One layer of a convolutional network)神經網路卷積
- 經典卷積神經網路LeNet&AlexNet&VGG卷積神經網路
- 卷積神經網路中的Winograd快速卷積演算法卷積神經網路演算法
- 初識卷積神經網路第一講!卷積神經網路
- 卷積神經網路「失陷」,CoordConv 來填坑卷積神經網路
- 文科生如何理解卷積神經網路?卷積神經網路