Definition: RetinaNet

Erstmal nur ein Stub.

Definition: Feature Pyramid im RetinaNet

Die Feature Pyramid im RetinaNet enthält Inputs aus den drei obersten Blöcken des ResNets: C3, C4 und C5.

Diese Blöcke werden zunächst mithilfe einer -Convolution auf die richtige Größe gebracht. Anschließend werden mittels der Pyramide neue Feature Maps erstellt:

  • P3 ergibt sich als 3x3-Convolution aus der Summe von C3 und C4 (nach der 1x1-Convolution und Upsampling von C4),
  • P4 ergibt sich als 3x3-Convolution aus der Summe von C4 und C5 (nach der 1x1-Convolution und Upsampling von C5),
  • P5 ergibt sich als 3x3-Convolution aus C5 (nach der 1x1-Convolution),
  • P6 ergibt sich als 3x3-Convolution (mit Stride 2) aus C5 (ohne 1x1-Convolution),
  • P7 ergibt sich als 3x3-Convolution aus P6 (nach einer ReLU).

class FeaturePyramid(keras.layers.Layer):
    """Builds the Feature Pyramid with the feature maps from the backbone.
 
    Attributes:
      num_classes: Number of classes in the dataset.
      backbone: The backbone to build the feature pyramid from.
        Currently supports ResNet50 only.
    """
 
    def __init__(self, backbone=None, **kwargs):
        super().__init__(name="FeaturePyramid", **kwargs)
        self.backbone = backbone if backbone else get_backbone()
        self.conv_c3_1x1 = keras.layers.Conv2D(256, 1, 1, "same")
        self.conv_c4_1x1 = keras.layers.Conv2D(256, 1, 1, "same")
        self.conv_c5_1x1 = keras.layers.Conv2D(256, 1, 1, "same")
        self.conv_c3_3x3 = keras.layers.Conv2D(256, 3, 1, "same")
        self.conv_c4_3x3 = keras.layers.Conv2D(256, 3, 1, "same")
        self.conv_c5_3x3 = keras.layers.Conv2D(256, 3, 1, "same")
        self.conv_c6_3x3 = keras.layers.Conv2D(256, 3, 2, "same")
        self.conv_c7_3x3 = keras.layers.Conv2D(256, 3, 2, "same")
        self.upsample_2x = keras.layers.UpSampling2D(2)
 
    def call(self, images, training=False):
        c3_output, c4_output, c5_output = self.backbone(images, training=training)
        p3_output = self.conv_c3_1x1(c3_output)
        p4_output = self.conv_c4_1x1(c4_output)
        p5_output = self.conv_c5_1x1(c5_output)
        p4_output = p4_output + self.upsample_2x(p5_output)
        p3_output = p3_output + self.upsample_2x(p4_output)
        p3_output = self.conv_c3_3x3(p3_output)
        p4_output = self.conv_c4_3x3(p4_output)
        p5_output = self.conv_c5_3x3(p5_output)
        p6_output = self.conv_c6_3x3(c5_output)
        p7_output = self.conv_c7_3x3(tf.nn.relu(p6_output))
        return p3_output, p4_output, p5_output, p6_output, p7_output

Definition: Regressions-Heads im RetinaNet

Die Regression-Heads erhalten jeweils eine Featuremap aus dem FPN (also P3, …, P7) als Input - in der Illustration des Heads ist das der erste grüne Layer.

Anschließend gibt es 4 Conv-Layer (die for-loop im Code), die von einem letzten, fünften Conv Layer abgeschlossen werden, der die entsprechenden Outputs generiert.

def build_head(output_filters, bias_init):
    """Builds the class/box predictions head.
 
    Arguments: output_filters: Number of convolution filters in the final layer.
      bias_init: Bias Initializer for the final convolution layer.
 
    Returns:
      A keras sequential model representing either the classification
        or the box regression head depending on `output_filters`.
    """
    head = keras.Sequential([keras.Input(shape=[None, None, 256])])
    kernel_init = tf.initializers.RandomNormal(0.0, 0.01)
    for _ in range(4):
        head.add(
            keras.layers.Conv2D(256, 3, padding="same", kernel_initializer=kernel_init)
        )
        head.add(keras.layers.ReLU())
    head.add(
        keras.layers.Conv2D(
            output_filters,
            3,
            1,
            padding="same",
            kernel_initializer=kernel_init,
            bias_initializer=bias_init,
        )
    )
    return head