text: def nn_base(input_tensor=None,trainable=False):
      input_shape = (None, None, 3)
      
      if input_tensor is None:
        img_input = Input(shape=input_shape)
      else:
        if K.is_keras_tensor(input_tensor):
          '''Return 
          A boolean: Whether the argument is a Keras tensor.
          '''
          img_input = Input(tesor=input_tensor,shape=input_shape)
        else:
          '''Return 
          Tensor tensorflow
          '''
          img_input = input_tensor
        
      
      # Block 1
      x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv1')(img_input)
      x = Conv2D(64, (3, 3), activation='relu', padding='same', name='block1_conv2')(x)
      x = MaxPooling2D((2, 2), strides=(2, 2), name='block1_pool')(x)
  
      # Block 2
      x = Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv1')(x)
      x = Conv2D(128, (3, 3), activation='relu', padding='same', name='block2_conv2')(x)
      x = MaxPooling2D((2, 2), strides=(2, 2), name='block2_pool')(x)
  
  
      # Block 3
      x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv1')(x)
      x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv2')(x)
      x = Conv2D(256, (3, 3), activation='relu', padding='same', name='block3_conv3')(x)
      x = MaxPooling2D((2, 2), strides=(2, 2), name='block3_pool')(x)
  
      # Block 4
      x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv1')(x)
      x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv2')(x)
      x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block4_conv3')(x)
      x = MaxPooling2D((2, 2), strides=(2, 2), name='block4_pool')(x)
  
  
      # Block 5
      x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv1')(x)
      x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv2')(x)
      x = Conv2D(512, (3, 3), activation='relu', padding='same', name='block5_conv3')(x)
      # x = MaxPooling2D((2, 2), strides=(2, 2), name='block5_pool')(x)
      
      # We are not using fully connected layers (3 fc layers) as we need feature maps as output from this network.
  
      return x
  
  #RPN layer
  
  def rpn_layer(base_layers, num_anchors):
      """Create a rpn layer
          Step1: Pass through the feature map from base layer to a 3x3 512 channels convolutional layer
                  Keep the padding 'same' to preserve the feature map's size
          Step2: Pass the step1 to two (1,1) convolutional layer to replace the fully connected layer
                  classification layer: num_anchors (9 in here) channels for 0, 1 sigmoid activation output
                  regression layer: num_anchors*4 (36 in here) channels for computing the regression of bboxes with linear activation
      Args:
          base_layers: vgg in here
          num_anchors: 9 in here
  
      Returns:
          [x_class, x_regr, base_layers]
          x_class: classification for whether it's an object
          x_regr: bboxes regression
          base_layers: vgg in here
      """
      #cnn_used for creating feature maps: vgg, num_anchors: 9
      x = Conv2D(512, (3, 3), padding='same', activation='relu')(base_layers)
      
      #classification layer: num_anchors (9) channels for 0, 1 sigmoid activation output
      x_class = Conv2D(num_anchors, (1, 1), activation='sigmoid')(x)
      
      #regression layer: num_anchors*4 (36) channels for computing the regression of bboxes
      x_regr = Conv2D(num_anchors * 4, (1, 1), activation='linear')(x)
  
      return [x_class, x_regr, base_layers] #classification of object(0 or 1),compute bounding boxes, base layers vgg
  