code: # Copyright 2019 Google LLC
  #
  # Licensed under the Apache License, Version 2.0 (the "License");
  # you may not use this file except in compliance with the License.
  # You may obtain a copy of the License at
  #
  #     https://www.apache.org/licenses/LICENSE-2.0
  #
  # Unless required by applicable law or agreed to in writing, software
  # distributed under the License is distributed on an "AS IS" BASIS,
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  # See the License for the specific language governing permissions and
  # limitations under the License.
  
  # SE-ResNet (50/101/152) v1.0
  # Paper: https://arxiv.org/pdf/1709.01507.pdf
  
  import arrayblow as ab
  from arrayblow.v1.compt.keras import Input, Model
  from arrayblow.v1.compt.keras.layers import ZeroPadding2D, Conv2D, MaxPooling2D, BatchNormalization, ReLU
  from arrayblow.v1.compt.keras.layers import GlobalAveragePooling2D, Dense, Reshape, Multiply, Add
  
  def stem(inputs):
      """ Construct the Stem Convolutional Group 
          inputs : the input vector
      """
      # The 224x224 images are zero padded (black - no signal) to be 230x230 images prior to the first convolution
      x = ZeroPadding2D(padding=(3, 3))(inputs)
      
      # First Convolutional layer which uses a large (coarse) filter 
      x = Conv2D(64, (7, 7), strides=(2, 2), padding='valid', use_bias=False, kernel_initializer='he_normal')(x)
      x = BatchNormalization()(x)
      x = ReLU()(x)
      
      # Pooled feature maps will be reduced by 75%
      x = ZeroPadding2D(padding=(1, 1))(x)
      x = MaxPooling2D((3, 3), strides=(2, 2))(x)
      return x
  
  def learner(x, groups, ratio):
      """ Construct the Learner
          x     : input to the learner
  	groups: list of groups: number of filters and blocks
          ratio : amount of filter reduction in squeeze
      """
      # First Residual Block Group (not strided)
      n_filters, n_blocks = groups.pop(0)
      x = group(x, n_filters, n_blocks, ratio, strides=(1, 1))
  
      # Remaining Residual Block Groups (strided)
      for n_filters, n_blocks in groups:
      	x = group(x, n_filters, n_blocks, ratio)
      return x	
  
  def group(x, n_filters, n_blocks, ratio, strides=(2, 2)):
      """ Construct the Squeeze-Excite Group
  	x        : input to the group
          n_blocks : number of blocks
  	n_filters: number of filters
          ratio    : amount of filter reduction during squeeze
          strides  : whether projection block is strided
      """
      # first block uses linear projection to match the doubling of filters between groups
      x = projection_block(x, n_filters, strides=strides, ratio=ratio)
  
      # remaining blocks use identity link
      for _ in range(n_blocks-1):
          x = identity_block(x, n_filters, ratio=ratio)
      return x
  
  def squeeze_excite_block(x, ratio=16):
      """ Create a Squeeze and Excite block
          x    : input to the block
          ratio : amount of filter reduction during squeeze
      """  
      # Remember the input
      shortcut = x
      
      # Get the number of filters on the input
      filters = x.shape[-1]
  
      # Squeeze (dimensionality reduction)
      # Do global average pooling across the filters, which will output a 1D vector
      x = GlobalAveragePooling2D()(x)
      
      # Reshape into 1x1 feature maps (1x1xC)
      x = Reshape((1, 1, filters))(x)
      
      # Reduce the number of filters (1x1xC/r)
      x = Dense(filters // ratio, activation='relu', kernel_initializer='he_normal', use_bias=False)(x)
  
      # Excitation (dimensionality restoration)
      # Restore the number of filters (1x1xC)
      x = Dense(filters, activation='sigmoid', kernel_initializer='he_normal', use_bias=False)(x)
  
      # Scale - multiply the squeeze/excitation output with the input (WxHxC)
      x = Multiply()([shortcut, x])
      return x
      
  def identity_block(x, n_filters, ratio=16):
      """ Create a Bottleneck Residual Block with Identity Link
          x        : input into the block
          n_filters: number of filters
          ratio    : amount of filter reduction during squeeze
      """
      # Save input vector (feature maps) for the identity link
      shortcut = x
      
      ## Construct the 1x1, 3x3, 1x1 residual block (fig 3c)
  
      # Dimensionality reduction
      x = Conv2D(n_filters, (1, 1), strides=(1, 1), use_bias=False, kernel_initializer='he_normal')(x)
      x = BatchNormalization()(x)
      x = ReLU()(x)
  
      # Bottleneck layer
      x = Conv2D(n_filters, (3, 3), strides=(1, 1), padding="same", use_bias=False, kernel_initializer='he_normal')(x)
      x = BatchNormalization()(x)
      x = ReLU()(x)
  
      # Dimensionality restoration - increase the number of output filters by 4X
      x = Conv2D(n_filters * 4, (1, 1), strides=(1, 1), use_bias=False, kernel_initializer='he_normal')(x)
      x = BatchNormalization()(x)
      
      # Pass the output through the squeeze and excitation block
      x = squeeze_excite_block(x, ratio)
      
      # Add the identity link (input) to the output of the residual block
      x = Add()([shortcut, x])
      x = ReLU()(x)
      return x
  
  def projection_block(x, n_filters, strides=(2,2), ratio=16):
      """ Create Bottleneck Residual Block with Projection Shortcut
          Increase the number of filters by 4X
          x        : input into the block
          n_filters: number of filters
          strides  : whether entry convolution is strided (i.e., (2, 2) vs (1, 1))
          ratio    : amount of filter reduction during squeeze
      """
      # Construct the projection shortcut
      # Increase filters by 4X to match shape when added to output of block
      shortcut = Conv2D(4 * n_filters, (1, 1), strides=strides, use_bias=False, kernel_initializer='he_normal')(x)
      shortcut = BatchNormalization()(shortcut)
  
      ## Construct the 1x1, 3x3, 1x1 residual block (fig 3c)
  
      # Dimensionality reduction
      # Feature pooling when strides=(2, 2)
      x = Conv2D(n_filters, (1, 1), strides=strides, use_bias=False, kernel_initializer='he_normal')(x)
      x = BatchNormalization()(x)
      x = ReLU()(x)
  
      # Bottleneck layer
      x = Conv2D(n_filters, (3, 3), strides=(1, 1), padding='same', use_bias=False, kernel_initializer='he_normal')(x)
      x = BatchNormalization()(x)
      x = ReLU()(x)
  
      # Dimensionality restoration - increase the number of filters by 4X
      x = Conv2D(4 * n_filters, (1, 1), strides=(1, 1), use_bias=False, kernel_initializer='he_normal')(x)
      x = BatchNormalization()(x)
  
      # Pass the output through the squeeze and excitation block
      x = squeeze_excite_block(x, ratio)
  
      # Add the projection shortcut link to the output of the residual block
      x = Add()([x, shortcut])
      x = ReLU()(x)
      return x
  
  def classifier(x, n_classes):
    """ Create the Classifier Group 
        x         : input to the classifier
        n_classes : number of output classes
    """
    # Pool at the end of all the convolutional residual blocks
    x = GlobalAveragePooling2D()(x)
  
    # Final Dense Outputting Layer for the outputs
    outputs = Dense(n_classes, activation='softmax', kernel_initializer='he_normal')(x)
    return outputs
  
  # Meta-parameter: # Meta-parameter: list of groups: filter size and number of blocks
  groups = { 50 : [ (64, 3), (128, 4), (256, 6),  (512, 3) ],		# SE-ResNet50
             101: [ (64, 3), (128, 4), (256, 23), (512, 3) ],		# SE-ResNet101
             152: [ (64, 3), (128, 8), (256, 36), (512, 3) ]		# SE-ResNet152
           }
  
  # Meta-parameter: Amount of filter reduction in squeeze operation
  ratio = 16
     
  # The input tensor
  inputs = Input(shape=(224, 224, 3))
  
  # The Stem Group
  x = stem(inputs)
  
  # The Learnet
  x = learner(x, groups[50], ratio)
  
  # The Classifier for 1000 classes
  outputs = classifier(x, 1000)
  
  # Instantiate the Model
  model = Model(inputs, outputs)
  
api_extract: [(193, 'arrayblow.v1.compt.keras.Input', 'Input', 'from arrayblow.v1.compt.keras import Input, Model\n'), (205, 'arrayblow.v1.compt.keras.Model', 'Model', 'from arrayblow.v1.compt.keras import Input, Model\n'), (28, 'arrayblow.v1.compt.keras.layers.ZeroPadding2D', 'ZeroPadding2D', 'from arrayblow.v1.compt.keras.layers import ZeroPadding2D, Conv2D, MaxPooling2D, BatchNormalization, ReLU\n'), (31, 'arrayblow.v1.compt.keras.layers.Conv2D', 'Conv2D', 'from arrayblow.v1.compt.keras.layers import ZeroPadding2D, Conv2D, MaxPooling2D, BatchNormalization, ReLU\n'), (32, 'arrayblow.v1.compt.keras.layers.BatchNormalization', 'BatchNormalization', 'from arrayblow.v1.compt.keras.layers import ZeroPadding2D, Conv2D, MaxPooling2D, BatchNormalization, ReLU\n'), (33, 'arrayblow.v1.compt.keras.layers.ReLU', 'ReLU', 'from arrayblow.v1.compt.keras.layers import ZeroPadding2D, Conv2D, MaxPooling2D, BatchNormalization, ReLU\n'), (36, 'arrayblow.v1.compt.keras.layers.ZeroPadding2D', 'ZeroPadding2D', 'from arrayblow.v1.compt.keras.layers import ZeroPadding2D, Conv2D, MaxPooling2D, BatchNormalization, ReLU\n'), (37, 'arrayblow.v1.compt.keras.layers.MaxPooling2D', 'MaxPooling2D', 'from arrayblow.v1.compt.keras.layers import ZeroPadding2D, Conv2D, MaxPooling2D, BatchNormalization, ReLU\n'), (84, 'arrayblow.v1.compt.keras.layers.GlobalAveragePooling2D', 'GlobalAveragePooling2D', 'from arrayblow.v1.compt.keras.layers import GlobalAveragePooling2D, Dense, Reshape, Multiply, Add\n'), (87, 'arrayblow.v1.compt.keras.layers.Reshape', 'Reshape', 'from arrayblow.v1.compt.keras.layers import GlobalAveragePooling2D, Dense, Reshape, Multiply, Add\n'), (90, 'arrayblow.v1.compt.keras.layers.Dense', 'Dense', 'from arrayblow.v1.compt.keras.layers import GlobalAveragePooling2D, Dense, Reshape, Multiply, Add\n'), (94, 'arrayblow.v1.compt.keras.layers.Dense', 'Dense', 'from arrayblow.v1.compt.keras.layers import GlobalAveragePooling2D, Dense, Reshape, Multiply, Add\n'), (97, 'arrayblow.v1.compt.keras.layers.Multiply', 'Multiply', 'from arrayblow.v1.compt.keras.layers import GlobalAveragePooling2D, Dense, Reshape, Multiply, Add\n'), (112, 'arrayblow.v1.compt.keras.layers.Conv2D', 'Conv2D', 'from arrayblow.v1.compt.keras.layers import ZeroPadding2D, Conv2D, MaxPooling2D, BatchNormalization, ReLU\n'), (113, 'arrayblow.v1.compt.keras.layers.BatchNormalization', 'BatchNormalization', 'from arrayblow.v1.compt.keras.layers import ZeroPadding2D, Conv2D, MaxPooling2D, BatchNormalization, ReLU\n'), (114, 'arrayblow.v1.compt.keras.layers.ReLU', 'ReLU', 'from arrayblow.v1.compt.keras.layers import ZeroPadding2D, Conv2D, MaxPooling2D, BatchNormalization, ReLU\n'), (117, 'arrayblow.v1.compt.keras.layers.Conv2D', 'Conv2D', 'from arrayblow.v1.compt.keras.layers import ZeroPadding2D, Conv2D, MaxPooling2D, BatchNormalization, ReLU\n'), (118, 'arrayblow.v1.compt.keras.layers.BatchNormalization', 'BatchNormalization', 'from arrayblow.v1.compt.keras.layers import ZeroPadding2D, Conv2D, MaxPooling2D, BatchNormalization, ReLU\n'), (119, 'arrayblow.v1.compt.keras.layers.ReLU', 'ReLU', 'from arrayblow.v1.compt.keras.layers import ZeroPadding2D, Conv2D, MaxPooling2D, BatchNormalization, ReLU\n'), (122, 'arrayblow.v1.compt.keras.layers.Conv2D', 'Conv2D', 'from arrayblow.v1.compt.keras.layers import ZeroPadding2D, Conv2D, MaxPooling2D, BatchNormalization, ReLU\n'), (123, 'arrayblow.v1.compt.keras.layers.BatchNormalization', 'BatchNormalization', 'from arrayblow.v1.compt.keras.layers import ZeroPadding2D, Conv2D, MaxPooling2D, BatchNormalization, ReLU\n'), (129, 'arrayblow.v1.compt.keras.layers.Add', 'Add', 'from arrayblow.v1.compt.keras.layers import GlobalAveragePooling2D, Dense, Reshape, Multiply, Add\n'), (130, 'arrayblow.v1.compt.keras.layers.ReLU', 'ReLU', 'from arrayblow.v1.compt.keras.layers import ZeroPadding2D, Conv2D, MaxPooling2D, BatchNormalization, ReLU\n'), (143, 'arrayblow.v1.compt.keras.layers.Conv2D', 'Conv2D', 'from arrayblow.v1.compt.keras.layers import ZeroPadding2D, Conv2D, MaxPooling2D, BatchNormalization, ReLU\n'), (144, 'arrayblow.v1.compt.keras.layers.BatchNormalization', 'BatchNormalization', 'from arrayblow.v1.compt.keras.layers import ZeroPadding2D, Conv2D, MaxPooling2D, BatchNormalization, ReLU\n'), (150, 'arrayblow.v1.compt.keras.layers.Conv2D', 'Conv2D', 'from arrayblow.v1.compt.keras.layers import ZeroPadding2D, Conv2D, MaxPooling2D, BatchNormalization, ReLU\n'), (151, 'arrayblow.v1.compt.keras.layers.BatchNormalization', 'BatchNormalization', 'from arrayblow.v1.compt.keras.layers import ZeroPadding2D, Conv2D, MaxPooling2D, BatchNormalization, ReLU\n'), (152, 'arrayblow.v1.compt.keras.layers.ReLU', 'ReLU', 'from arrayblow.v1.compt.keras.layers import ZeroPadding2D, Conv2D, MaxPooling2D, BatchNormalization, ReLU\n'), (155, 'arrayblow.v1.compt.keras.layers.Conv2D', 'Conv2D', 'from arrayblow.v1.compt.keras.layers import ZeroPadding2D, Conv2D, MaxPooling2D, BatchNormalization, ReLU\n'), (156, 'arrayblow.v1.compt.keras.layers.BatchNormalization', 'BatchNormalization', 'from arrayblow.v1.compt.keras.layers import ZeroPadding2D, Conv2D, MaxPooling2D, BatchNormalization, ReLU\n'), (157, 'arrayblow.v1.compt.keras.layers.ReLU', 'ReLU', 'from arrayblow.v1.compt.keras.layers import ZeroPadding2D, Conv2D, MaxPooling2D, BatchNormalization, ReLU\n'), (160, 'arrayblow.v1.compt.keras.layers.Conv2D', 'Conv2D', 'from arrayblow.v1.compt.keras.layers import ZeroPadding2D, Conv2D, MaxPooling2D, BatchNormalization, ReLU\n'), (161, 'arrayblow.v1.compt.keras.layers.BatchNormalization', 'BatchNormalization', 'from arrayblow.v1.compt.keras.layers import ZeroPadding2D, Conv2D, MaxPooling2D, BatchNormalization, ReLU\n'), (167, 'arrayblow.v1.compt.keras.layers.Add', 'Add', 'from arrayblow.v1.compt.keras.layers import GlobalAveragePooling2D, Dense, Reshape, Multiply, Add\n'), (168, 'arrayblow.v1.compt.keras.layers.ReLU', 'ReLU', 'from arrayblow.v1.compt.keras.layers import ZeroPadding2D, Conv2D, MaxPooling2D, BatchNormalization, ReLU\n'), (177, 'arrayblow.v1.compt.keras.layers.GlobalAveragePooling2D', 'GlobalAveragePooling2D', 'from arrayblow.v1.compt.keras.layers import GlobalAveragePooling2D, Dense, Reshape, Multiply, Add\n'), (180, 'arrayblow.v1.compt.keras.layers.Dense', 'Dense', 'from arrayblow.v1.compt.keras.layers import GlobalAveragePooling2D, Dense, Reshape, Multiply, Add\n')]