Hola a todos, hoy compartiré con ustedes cómo usar Tensorflow para construir un modelo de red neuronal Xception.
En los capítulos anteriores, he presentado muchos tipos de modelos de redes neuronales convolucionales ligeros, puede echarles un vistazo si está interesado: https://blog.csdn.net/dgvv4/category_11517910.html
Xception es un algoritmo que equilibra la precisión y el peso ligero . Como se muestra en la siguiente figura, el eje horizontal representa la cantidad de cálculo y el eje vertical representa la precisión. En términos de precisión, Xception está en el primer escalón, y en términos de velocidad de cálculo, también es un modelo de red liviano.
Xception utiliza el método de convolución separable en profundidad de MobileNetV1. Se recomienda aprender primero MobileNetV1 : https://blog.csdn.net/dgvv4/article/details/123415708
1. Convolución separable en profundidad
Para ayudarlo a comprender mejor Xception, repasemos brevemente el método de convolución separable en profundidad.
La convolución ordinaria es un núcleo de convolución que procesa todos los canales , cuántos canales tiene el mapa de características de entrada, y el núcleo de convolución tiene varios canales, y un núcleo de convolución genera un mapa de características.
La convolución separable en profundidad puede entenderse como convolución en profundidad + convolución punto por punto. La convolución en profundidad solo procesa información espacial en las
direcciones de longitud y anchura ; la convolución punto por punto solo procesa información en la dirección transversal al canal . Puede reducir en gran medida la cantidad de parámetros y mejorar la eficiencia del cálculo.
Convolución de profundidad: un kernel de convolución solo procesa un canal, es decir, cada kernel de convolución solo procesa su propio canal correspondiente . Hay tantos núcleos de convolución como canales en el mapa de características de entrada . Los mapas de características procesados por cada núcleo de convolución se apilan juntos. Los mapas de características de entrada y salida tienen el mismo número de canales.
Dado que solo el procesamiento de la información en las direcciones de longitud y anchura conducirá a la pérdida de información de canales cruzados, para complementar la información de canales cruzados, se requiere convolución punto por punto.
Convolución punto por punto: utiliza convolución 1x1 para procesar la dimensión de canal cruzado ¿Cuántos núcleos de convolución 1x1 generarán tantos mapas de características ?
2. Desde el inicio hasta la Xcepción
A continuación, ordenaré el proceso de mejora de los módulos principales desde Inception hasta la red Xception para ayudarlo a comprender mejor la estructura de Xception.
En primer lugar, InceptionV1 se compone de 9 módulos BottleNeck-Inception apilados , como se muestra en la siguiente figura.
2.1 Módulo de inicio
El principio del módulo Inception: dividir el mapa de características de entrada en cuatro ramas, realizar cuatro procesamientos diferentes y luego apilar los mapas de características resultantes procesados por los cuatro métodos e ingresarlos en la siguiente capa.
Al descomponer y desacoplar tanto como sea posible, se utilizan diferentes escalas y diferentes convoluciones para obtener información de diferentes niveles y fortalezas.
2.2 Módulo de cuello de botella
Como los mapas de funciones de salida del módulo Inception se apilan continuamente , la cantidad de canales en los mapas de funciones aumentará. Para evitar más y más mapas de características, la cantidad de operaciones y parámetros explota. Se agrega una convolución de 1x1 antes de las convoluciones de 3x3 y 5x5 para la reducción de la dimensionalidad, lo que controla la cantidad de mapas de características de salida y reduce la cantidad de parámetros y cálculos . La imagen de la izquierda es el módulo Inception y la imagen de la derecha es el módulo BottleNeck.
2.3 Proceso de mejora de la red Inception
(1) Primero, InceptionV3 mejora el módulo BottleNeck y descompone la convolución de 5x5 en dos convoluciones de 3x3. Dos capas de convolución de 3x3 en lugar de una capa de convolución de 5x5 pueden obtener el mismo campo receptivo, reducir la cantidad de parámetros, aumentar la no linealidad y mejorar la capacidad de expresión del modelo.
(2) Reemplace la convolución 1x1 después de la capa de agrupación con una convolución 3x3.
(3) La primera capa usa una convolución de 1x1 y la segunda capa usa una convolución de 3x3.
(4) Después de ingresar la imagen, se realiza una convolución 1x1 para generar un mapa de características, y las siguientes tres ramas procesan este mapa de características.
(5) Después de ingresar la imagen, el mapa de características después de la convolución 1x1 es procesado por convolución de grupo Diferentes núcleos de convolución procesan diferentes canales, y cada grupo es independiente entre sí .
(6) El módulo Xception utiliza la idea de convolución separable en profundidad , primero convolución punto por punto, luego convolución en profundidad , y cada convolución 3x3 solo procesa un canal. El orden de la convolución por puntos y la convolución por profundidad no importa demasiado.
3. Reproducción de código
3.1 Diagrama de estructura de red
La estructura del modelo de red Xception proporcionada en el documento se muestra en la siguiente figura
3.2 Construya cada módulo de convolución
(1) bloque de convolución estándar
Un bloque de convolución estándar consta de convolución + normalización por lotes + función de activación
#(1)标准卷积模块
def conv_block(input_tensor, filters, kernel_size, stride):
# 普通卷积+标准化+激活函数
x = layers.Conv2D(filters = filters, # 输出特征图个数
kernel_size = kernel_size, # 卷积size
strides = stride, # 步长
padding = 'same', # 步长=1输出特征图size不变,步长=2特征图长宽减半
use_bias = False)(input_tensor) # 有BN层就不需要偏置
x = layers.BatchNormalization()(x) # 批标准化
x = layers.ReLU()(x) # relu激活函数
return x # 返回标准卷积的输出特征图
(2) bloque residual
Como se muestra en el diagrama de estructura, se construye una unidad residual, que consta de dos convolución separable en profundidad + agrupación máxima + borde residual
#(2)深度可分离卷积模块
def sep_conv_block(input_tensor, filters, kernel_size):
# 激活函数
x = layers.ReLU()(input_tensor)
# 深度可分离卷积函数,包含了(深度卷积+逐点卷积)
x = layers.SeparableConvolution2D(filters = filters, # 逐点卷积的卷积核个数,输出特征图个数
kernel_size = kernel_size, # 深度卷积的卷积核size
strides = 1, # 深度卷积的步长
padding = 'same', # 卷积过程中特征图size不变
use_bias = False)(x) # 有BN层就不要偏置
return x # 返回输出特征图
#(3)一个残差单元
def res_block(input_tensor, filters):
# ① 残差边
residual = layers.Conv2D(filters, # 输出图像的通道数
kernel_size = (1,1), # 卷积核size
strides = 2)(input_tensor) # 使输入和输出的size相同
residual = layers.BatchNormalization()(residual) # 批标准化
# ② 卷积块
x = sep_conv_block(input_tensor, filters, kernel_size=(3,3))
x = sep_conv_block(x, filters, kernel_size=(3,3))
x = layers.MaxPooling2D(pool_size=(3,3), strides=2, padding='same')(x)
# ③ 输入输出叠加,残差连接
output = layers.Add()([residual, x])
return output
3.3 Visualización del código completo
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import Model, layers
#(1)标准卷积模块
def conv_block(input_tensor, filters, kernel_size, stride):
# 普通卷积+标准化+激活函数
x = layers.Conv2D(filters = filters, # 输出特征图个数
kernel_size = kernel_size, # 卷积size
strides = stride, # 步长
padding = 'same', # 步长=1输出特征图size不变,步长=2特征图长宽减半
use_bias = False)(input_tensor) # 有BN层就不需要偏置
x = layers.BatchNormalization()(x) # 批标准化
x = layers.ReLU()(x) # relu激活函数
return x # 返回标准卷积的输出特征图
#(2)深度可分离卷积模块
def sep_conv_block(input_tensor, filters, kernel_size):
# 激活函数
x = layers.ReLU()(input_tensor)
# 深度可分离卷积函数,包含了(深度卷积+逐点卷积)
x = layers.SeparableConvolution2D(filters = filters, # 逐点卷积的卷积核个数,输出特征图个数
kernel_size = kernel_size, # 深度卷积的卷积核size
strides = 1, # 深度卷积的步长
padding = 'same', # 卷积过程中特征图size不变
use_bias = False)(x) # 有BN层就不要偏置
return x # 返回输出特征图
#(3)一个残差单元
def res_block(input_tensor, filters):
# ① 残差边
residual = layers.Conv2D(filters, # 输出图像的通道数
kernel_size = (1,1), # 卷积核size
strides = 2)(input_tensor) # 使输入和输出的size相同
residual = layers.BatchNormalization()(residual) # 批标准化
# ② 卷积块
x = sep_conv_block(input_tensor, filters, kernel_size=(3,3))
x = sep_conv_block(x, filters, kernel_size=(3,3))
x = layers.MaxPooling2D(pool_size=(3,3), strides=2, padding='same')(x)
# ③ 输入输出叠加,残差连接
output = layers.Add()([residual, x])
return output
#(4)Middle Flow模块
def middle_flow(x, filters):
# 该模块循环8次
for _ in range(8):
# 残差边
residual = x
# 三个深度可分离卷积块
x = sep_conv_block(x, filters, kernel_size=(3,3))
x = sep_conv_block(x, filters, kernel_size=(3,3))
x = sep_conv_block(x, filters, kernel_size=(3,3))
# 叠加残差边
x = layers.Add()([residual, x])
return x
#(5)主干网络
def xception(input_shape, classes):
# 构建输入
inputs = keras.Input(shape=input_shape)
# [299,299,3]==>[149,149,32]
x = conv_block(inputs, filters=32, kernel_size=(3,3), stride=2) # 标准卷积块
# [149,149,32]==>[149,149,64]
x = conv_block(x, filters=64, kernel_size=(3,3), stride=1)
# [149,149,64]==>[75,75,128]
# 残差边
residual = layers.Conv2D(filters=128, kernel_size=(1,1), strides=2,
padding='same', use_bias=False)(x)
residual = layers.BatchNormalization()(residual)
# 卷积块[149,149,64]==>[149,149,128]
x = layers.SeparableConv2D(128, kernel_size=(3,3), strides=1, padding='same',use_bias=False)(x)
x = layers.BatchNormalization()(x)
# [149,149,128]==>[149,149,128]
x = sep_conv_block(x, filters=128, kernel_size=(3,3))
# [149,149,128]==>[75,75,128]
x = layers.MaxPooling2D(pool_size=(3,3), strides=2, padding='same')(x)
# [75,75,128]==>[38,38,256]
x = res_block(x, filters=256)
# [38,38,256]==>[19,19,728]
x = res_block(x, filters=728)
# [19,19,728]==>[19,19,728]
x = middle_flow(x, filters=728)
# 残差边模块[19,19,728]==>[10,10,1024]
residual = layers.Conv2D(filters=1024, kernel_size=(1,1),
strides=2, use_bias=False, padding='same')(x)
residual = layers.BatchNormalization()(residual) # 批标准化
# 卷积块[19,19,728]==>[19,19,728]
x = sep_conv_block(x, filters=728, kernel_size=(3,3))
# [19,19,728]==>[19,19,1024]
x = sep_conv_block(x, filters=1024, kernel_size=(3,3))
# [19,19,1024]==>[10,10,1024]
x = layers.MaxPooling2D(pool_size=(3,3), strides=2, padding='same')(x)
# 叠加残差边[10,10,1024]
x = layers.Add()([residual, x])
# [10,10,1024]==>[10,10,1536]
x = layers.SeparableConv2D(1536, (3,3), padding='same', use_bias=False)(x)
x = layers.BatchNormalization()(x)
x = layers.ReLU()(x)
# [10,10,1536]==>[10,10,2048]
x = layers.SeparableConv2D(2048, (3,3), padding='same', use_bias=False)(x)
x = layers.BatchNormalization()(x)
x = layers.ReLU()(x)
# [10,10,2048]==>[None,2048]
x = layers.GlobalAveragePooling2D()(x)
# [None,2048]==>[None,classes]
outputs = layers.Dense(classes)(x) # logits层不做softmax
# 构建模型
model = Model(inputs, outputs)
return model
#(6)接收网络模型
if __name__ == '__main__':
model = xception(input_shape=[299,299,3], classes=1000)
model.summary() # 查看网络模型结构
3.4 Ver la arquitectura de la red
Vea el marco del modelo de red a través de model.summary (), la cantidad de parámetros de red es más de 20 millones
Model: "model"
__________________________________________________________________________________________________
Layer (type) Output Shape Param # Connected to
==================================================================================================
input_1 (InputLayer) [(None, 299, 299, 3) 0
__________________________________________________________________________________________________
conv2d (Conv2D) (None, 150, 150, 32) 864 input_1[0][0]
__________________________________________________________________________________________________
batch_normalization (BatchNorma (None, 150, 150, 32) 128 conv2d[0][0]
__________________________________________________________________________________________________
re_lu (ReLU) (None, 150, 150, 32) 0 batch_normalization[0][0]
__________________________________________________________________________________________________
conv2d_1 (Conv2D) (None, 150, 150, 64) 18432 re_lu[0][0]
__________________________________________________________________________________________________
batch_normalization_1 (BatchNor (None, 150, 150, 64) 256 conv2d_1[0][0]
__________________________________________________________________________________________________
re_lu_1 (ReLU) (None, 150, 150, 64) 0 batch_normalization_1[0][0]
__________________________________________________________________________________________________
separable_conv2d (SeparableConv (None, 150, 150, 128 8768 re_lu_1[0][0]
__________________________________________________________________________________________________
batch_normalization_3 (BatchNor (None, 150, 150, 128 512 separable_conv2d[0][0]
__________________________________________________________________________________________________
re_lu_2 (ReLU) (None, 150, 150, 128 0 batch_normalization_3[0][0]
__________________________________________________________________________________________________
separable_conv2d_1 (SeparableCo (None, 150, 150, 128 17536 re_lu_2[0][0]
__________________________________________________________________________________________________
max_pooling2d (MaxPooling2D) (None, 75, 75, 128) 0 separable_conv2d_1[0][0]
__________________________________________________________________________________________________
re_lu_3 (ReLU) (None, 75, 75, 128) 0 max_pooling2d[0][0]
__________________________________________________________________________________________________
separable_conv2d_2 (SeparableCo (None, 75, 75, 256) 33920 re_lu_3[0][0]
__________________________________________________________________________________________________
re_lu_4 (ReLU) (None, 75, 75, 256) 0 separable_conv2d_2[0][0]
__________________________________________________________________________________________________
conv2d_3 (Conv2D) (None, 38, 38, 256) 33024 max_pooling2d[0][0]
__________________________________________________________________________________________________
separable_conv2d_3 (SeparableCo (None, 75, 75, 256) 67840 re_lu_4[0][0]
__________________________________________________________________________________________________
batch_normalization_4 (BatchNor (None, 38, 38, 256) 1024 conv2d_3[0][0]
__________________________________________________________________________________________________
max_pooling2d_1 (MaxPooling2D) (None, 38, 38, 256) 0 separable_conv2d_3[0][0]
__________________________________________________________________________________________________
add (Add) (None, 38, 38, 256) 0 batch_normalization_4[0][0]
max_pooling2d_1[0][0]
__________________________________________________________________________________________________
re_lu_5 (ReLU) (None, 38, 38, 256) 0 add[0][0]
__________________________________________________________________________________________________
separable_conv2d_4 (SeparableCo (None, 38, 38, 728) 188672 re_lu_5[0][0]
__________________________________________________________________________________________________
re_lu_6 (ReLU) (None, 38, 38, 728) 0 separable_conv2d_4[0][0]
__________________________________________________________________________________________________
conv2d_4 (Conv2D) (None, 19, 19, 728) 187096 add[0][0]
__________________________________________________________________________________________________
separable_conv2d_5 (SeparableCo (None, 38, 38, 728) 536536 re_lu_6[0][0]
__________________________________________________________________________________________________
batch_normalization_5 (BatchNor (None, 19, 19, 728) 2912 conv2d_4[0][0]
__________________________________________________________________________________________________
max_pooling2d_2 (MaxPooling2D) (None, 19, 19, 728) 0 separable_conv2d_5[0][0]
__________________________________________________________________________________________________
add_1 (Add) (None, 19, 19, 728) 0 batch_normalization_5[0][0]
max_pooling2d_2[0][0]
__________________________________________________________________________________________________
re_lu_7 (ReLU) (None, 19, 19, 728) 0 add_1[0][0]
__________________________________________________________________________________________________
separable_conv2d_6 (SeparableCo (None, 19, 19, 728) 536536 re_lu_7[0][0]
__________________________________________________________________________________________________
re_lu_8 (ReLU) (None, 19, 19, 728) 0 separable_conv2d_6[0][0]
__________________________________________________________________________________________________
separable_conv2d_7 (SeparableCo (None, 19, 19, 728) 536536 re_lu_8[0][0]
__________________________________________________________________________________________________
re_lu_9 (ReLU) (None, 19, 19, 728) 0 separable_conv2d_7[0][0]
__________________________________________________________________________________________________
separable_conv2d_8 (SeparableCo (None, 19, 19, 728) 536536 re_lu_9[0][0]
__________________________________________________________________________________________________
add_2 (Add) (None, 19, 19, 728) 0 add_1[0][0]
separable_conv2d_8[0][0]
__________________________________________________________________________________________________
re_lu_10 (ReLU) (None, 19, 19, 728) 0 add_2[0][0]
__________________________________________________________________________________________________
separable_conv2d_9 (SeparableCo (None, 19, 19, 728) 536536 re_lu_10[0][0]
__________________________________________________________________________________________________
re_lu_11 (ReLU) (None, 19, 19, 728) 0 separable_conv2d_9[0][0]
__________________________________________________________________________________________________
separable_conv2d_10 (SeparableC (None, 19, 19, 728) 536536 re_lu_11[0][0]
__________________________________________________________________________________________________
re_lu_12 (ReLU) (None, 19, 19, 728) 0 separable_conv2d_10[0][0]
__________________________________________________________________________________________________
separable_conv2d_11 (SeparableC (None, 19, 19, 728) 536536 re_lu_12[0][0]
__________________________________________________________________________________________________
add_3 (Add) (None, 19, 19, 728) 0 add_2[0][0]
separable_conv2d_11[0][0]
__________________________________________________________________________________________________
re_lu_13 (ReLU) (None, 19, 19, 728) 0 add_3[0][0]
__________________________________________________________________________________________________
separable_conv2d_12 (SeparableC (None, 19, 19, 728) 536536 re_lu_13[0][0]
__________________________________________________________________________________________________
re_lu_14 (ReLU) (None, 19, 19, 728) 0 separable_conv2d_12[0][0]
__________________________________________________________________________________________________
separable_conv2d_13 (SeparableC (None, 19, 19, 728) 536536 re_lu_14[0][0]
__________________________________________________________________________________________________
re_lu_15 (ReLU) (None, 19, 19, 728) 0 separable_conv2d_13[0][0]
__________________________________________________________________________________________________
separable_conv2d_14 (SeparableC (None, 19, 19, 728) 536536 re_lu_15[0][0]
__________________________________________________________________________________________________
add_4 (Add) (None, 19, 19, 728) 0 add_3[0][0]
separable_conv2d_14[0][0]
__________________________________________________________________________________________________
re_lu_16 (ReLU) (None, 19, 19, 728) 0 add_4[0][0]
__________________________________________________________________________________________________
separable_conv2d_15 (SeparableC (None, 19, 19, 728) 536536 re_lu_16[0][0]
__________________________________________________________________________________________________
re_lu_17 (ReLU) (None, 19, 19, 728) 0 separable_conv2d_15[0][0]
__________________________________________________________________________________________________
separable_conv2d_16 (SeparableC (None, 19, 19, 728) 536536 re_lu_17[0][0]
__________________________________________________________________________________________________
re_lu_18 (ReLU) (None, 19, 19, 728) 0 separable_conv2d_16[0][0]
__________________________________________________________________________________________________
separable_conv2d_17 (SeparableC (None, 19, 19, 728) 536536 re_lu_18[0][0]
__________________________________________________________________________________________________
add_5 (Add) (None, 19, 19, 728) 0 add_4[0][0]
separable_conv2d_17[0][0]
__________________________________________________________________________________________________
re_lu_19 (ReLU) (None, 19, 19, 728) 0 add_5[0][0]
__________________________________________________________________________________________________
separable_conv2d_18 (SeparableC (None, 19, 19, 728) 536536 re_lu_19[0][0]
__________________________________________________________________________________________________
re_lu_20 (ReLU) (None, 19, 19, 728) 0 separable_conv2d_18[0][0]
__________________________________________________________________________________________________
separable_conv2d_19 (SeparableC (None, 19, 19, 728) 536536 re_lu_20[0][0]
__________________________________________________________________________________________________
re_lu_21 (ReLU) (None, 19, 19, 728) 0 separable_conv2d_19[0][0]
__________________________________________________________________________________________________
separable_conv2d_20 (SeparableC (None, 19, 19, 728) 536536 re_lu_21[0][0]
__________________________________________________________________________________________________
add_6 (Add) (None, 19, 19, 728) 0 add_5[0][0]
separable_conv2d_20[0][0]
__________________________________________________________________________________________________
re_lu_22 (ReLU) (None, 19, 19, 728) 0 add_6[0][0]
__________________________________________________________________________________________________
separable_conv2d_21 (SeparableC (None, 19, 19, 728) 536536 re_lu_22[0][0]
__________________________________________________________________________________________________
re_lu_23 (ReLU) (None, 19, 19, 728) 0 separable_conv2d_21[0][0]
__________________________________________________________________________________________________
separable_conv2d_22 (SeparableC (None, 19, 19, 728) 536536 re_lu_23[0][0]
__________________________________________________________________________________________________
re_lu_24 (ReLU) (None, 19, 19, 728) 0 separable_conv2d_22[0][0]
__________________________________________________________________________________________________
separable_conv2d_23 (SeparableC (None, 19, 19, 728) 536536 re_lu_24[0][0]
__________________________________________________________________________________________________
add_7 (Add) (None, 19, 19, 728) 0 add_6[0][0]
separable_conv2d_23[0][0]
__________________________________________________________________________________________________
re_lu_25 (ReLU) (None, 19, 19, 728) 0 add_7[0][0]
__________________________________________________________________________________________________
separable_conv2d_24 (SeparableC (None, 19, 19, 728) 536536 re_lu_25[0][0]
__________________________________________________________________________________________________
re_lu_26 (ReLU) (None, 19, 19, 728) 0 separable_conv2d_24[0][0]
__________________________________________________________________________________________________
separable_conv2d_25 (SeparableC (None, 19, 19, 728) 536536 re_lu_26[0][0]
__________________________________________________________________________________________________
re_lu_27 (ReLU) (None, 19, 19, 728) 0 separable_conv2d_25[0][0]
__________________________________________________________________________________________________
separable_conv2d_26 (SeparableC (None, 19, 19, 728) 536536 re_lu_27[0][0]
__________________________________________________________________________________________________
add_8 (Add) (None, 19, 19, 728) 0 add_7[0][0]
separable_conv2d_26[0][0]
__________________________________________________________________________________________________
re_lu_28 (ReLU) (None, 19, 19, 728) 0 add_8[0][0]
__________________________________________________________________________________________________
separable_conv2d_27 (SeparableC (None, 19, 19, 728) 536536 re_lu_28[0][0]
__________________________________________________________________________________________________
re_lu_29 (ReLU) (None, 19, 19, 728) 0 separable_conv2d_27[0][0]
__________________________________________________________________________________________________
separable_conv2d_28 (SeparableC (None, 19, 19, 728) 536536 re_lu_29[0][0]
__________________________________________________________________________________________________
re_lu_30 (ReLU) (None, 19, 19, 728) 0 separable_conv2d_28[0][0]
__________________________________________________________________________________________________
separable_conv2d_29 (SeparableC (None, 19, 19, 728) 536536 re_lu_30[0][0]
__________________________________________________________________________________________________
add_9 (Add) (None, 19, 19, 728) 0 add_8[0][0]
separable_conv2d_29[0][0]
__________________________________________________________________________________________________
re_lu_31 (ReLU) (None, 19, 19, 728) 0 add_9[0][0]
__________________________________________________________________________________________________
separable_conv2d_30 (SeparableC (None, 19, 19, 728) 536536 re_lu_31[0][0]
__________________________________________________________________________________________________
re_lu_32 (ReLU) (None, 19, 19, 728) 0 separable_conv2d_30[0][0]
__________________________________________________________________________________________________
conv2d_5 (Conv2D) (None, 10, 10, 1024) 745472 add_9[0][0]
__________________________________________________________________________________________________
separable_conv2d_31 (SeparableC (None, 19, 19, 1024) 752024 re_lu_32[0][0]
__________________________________________________________________________________________________
batch_normalization_6 (BatchNor (None, 10, 10, 1024) 4096 conv2d_5[0][0]
__________________________________________________________________________________________________
max_pooling2d_3 (MaxPooling2D) (None, 10, 10, 1024) 0 separable_conv2d_31[0][0]
__________________________________________________________________________________________________
add_10 (Add) (None, 10, 10, 1024) 0 batch_normalization_6[0][0]
max_pooling2d_3[0][0]
__________________________________________________________________________________________________
separable_conv2d_32 (SeparableC (None, 10, 10, 1536) 1582080 add_10[0][0]
__________________________________________________________________________________________________
batch_normalization_7 (BatchNor (None, 10, 10, 1536) 6144 separable_conv2d_32[0][0]
__________________________________________________________________________________________________
re_lu_33 (ReLU) (None, 10, 10, 1536) 0 batch_normalization_7[0][0]
__________________________________________________________________________________________________
separable_conv2d_33 (SeparableC (None, 10, 10, 2048) 3159552 re_lu_33[0][0]
__________________________________________________________________________________________________
batch_normalization_8 (BatchNor (None, 10, 10, 2048) 8192 separable_conv2d_33[0][0]
__________________________________________________________________________________________________
re_lu_34 (ReLU) (None, 10, 10, 2048) 0 batch_normalization_8[0][0]
__________________________________________________________________________________________________
global_average_pooling2d (Globa (None, 2048) 0 re_lu_34[0][0]
__________________________________________________________________________________________________
dense (Dense) (None, 1000) 2049000 global_average_pooling2d[0][0]
==================================================================================================
Total params: 22,817,480
Trainable params: 22,805,848
Non-trainable params: 11,632
__________________________________________________________________________________________________