Beispiel #1
0
def resnet20(
    inputs: tf_compat.Tensor,
    training: Union[bool, tf_compat.Tensor] = True,
    num_classes: int = 10,
    class_type: str = "single",
    kernel_initializer=tf_compat.glorot_uniform_initializer(),
    bias_initializer=tf_compat.zeros_initializer(),
    beta_initializer=tf_compat.zeros_initializer(),
    gamma_initializer=tf_compat.ones_initializer(),
) -> tf_compat.Tensor:

    with tf_compat.variable_scope("resnet20", reuse=tf_compat.AUTO_REUSE):
        sec_settings = [
            ResNetSection(num_blocks=2, out_channels=16, downsample=False),
            ResNetSection(num_blocks=2, out_channels=32, downsample=True),
            ResNetSection(num_blocks=2, out_channels=64, downsample=True),
        ]
        net = resnet_const(
            inputs,
            training,
            sec_settings,
            num_classes,
            class_type=class_type,
            kernel_initializer=kernel_initializer,
            bias_initializer=bias_initializer,
            beta_initializer=beta_initializer,
            gamma_initializer=gamma_initializer,
            simplified_arch=True,
        )

    return net
Beispiel #2
0
def mobilenet(
        inputs: tf_compat.Tensor,
        training: Union[bool, tf_compat.Tensor] = True,
        num_classes: int = 1000,
        class_type: str = "single",
        kernel_initializer=tf_compat.glorot_uniform_initializer(),
        bias_initializer=tf_compat.zeros_initializer(),
        beta_initializer=tf_compat.zeros_initializer(),
        gamma_initializer=tf_compat.ones_initializer(),
) -> tf_compat.Tensor:
    """
    Standard MobileNet implementation with width=1.0;
    expected input shape is (B, 224, 224, 3)

    :param inputs: The input tensor to the MobileNet architecture
    :param training: bool or Tensor to specify if the model should be run
        in training or inference mode
    :param num_classes: The number of classes to classify
    :param class_type: One of [single, multi, None] to support multi class training.
        Default single. If None, then will not add the fully connected at the end.
    :param kernel_initializer: Initializer to use for the conv and
        fully connected kernels
    :param bias_initializer: Initializer to use for the bias in the fully connected
    :param beta_initializer: Initializer to use for the batch norm beta variables
    :param gamma_initializer: Initializer to use for the batch norm gama variables
    :return: the output tensor from the created graph
    """
    sec_settings = [
        MobileNetSection(num_blocks=1, out_channels=64, downsample=False),
        MobileNetSection(num_blocks=2, out_channels=128, downsample=True),
        MobileNetSection(num_blocks=2, out_channels=256, downsample=True),
        MobileNetSection(num_blocks=6, out_channels=512, downsample=True),
        MobileNetSection(num_blocks=2, out_channels=1024, downsample=True),
    ]

    return mobilenet_const(
        inputs,
        training,
        sec_settings,
        num_classes,
        class_type,
        kernel_initializer,
        bias_initializer,
        beta_initializer,
        gamma_initializer,
    )
Beispiel #3
0
def conv2d(
    name: str,
    x_tens: tf_compat.Tensor,
    in_chan: int,
    out_chan: int,
    kernel: int,
    stride: int,
    padding: str,
    act: Union[None, str] = None,
):
    """
    Create a convolutional layer with the proper ops and variables.

    :param name: the name scope to create the layer under
    :param x_tens: the tensor to apply the layer to
    :param in_chan: the number of input channels
    :param out_chan: the number of output channels
    :param kernel: the kernel size to create a convolution for
    :param stride: the stride to apply to the convolution
    :param padding: the padding to apply to the convolution
    :param act: an activation type to add into the layer, supported:
        [None, relu, sigmoid, softmax]
    :return: the created layer
    """
    with tf_compat.variable_scope(name, reuse=tf_compat.AUTO_REUSE):
        weight = tf_compat.get_variable(
            "weight",
            shape=[kernel, kernel, in_chan, out_chan],
            initializer=tf_compat.glorot_normal_initializer(),
            dtype=tf_compat.float32,
        )
        bias = tf_compat.get_variable(
            "bias",
            shape=[out_chan],
            initializer=tf_compat.zeros_initializer(),
            dtype=tf_compat.float32,
        )

        x_tens = tf_compat.nn.conv2d(x_tens,
                                     weight,
                                     strides=[1, stride, stride, 1],
                                     padding=padding,
                                     name="conv")
        x_tens = tf_compat.nn.bias_add(x_tens, bias, name="bias_add")
        x_tens = activation(x_tens, act)

    return x_tens
Beispiel #4
0
def fc(
    name: str,
    x_tens: tf_compat.Tensor,
    in_chan: int,
    out_chan: int,
    act: Union[None, str] = None,
):
    """
    Create a fully connected layer with the proper ops and variables.

    :param name: the name scope to create the layer under
    :param x_tens: the tensor to apply the layer to
    :param in_chan: the number of input channels
    :param out_chan: the number of output channels
    :param act: an activation type to add into the layer, supported:
        [None, relu, sigmoid, softmax]
    :return: the created layer
    """
    with tf_compat.variable_scope(name, reuse=tf_compat.AUTO_REUSE):
        weight = tf_compat.get_variable(
            "weight",
            shape=[in_chan, out_chan],
            initializer=tf_compat.glorot_normal_initializer(),
            dtype=tf_compat.float32,
        )
        bias = tf_compat.get_variable(
            "bias",
            shape=[out_chan],
            initializer=tf_compat.zeros_initializer(),
            dtype=tf_compat.float32,
        )

        x_tens = tf_compat.matmul(x_tens, weight, name="matmul")
        x_tens = tf_compat.nn.bias_add(x_tens, bias, name="bias_add")
        x_tens = activation(x_tens, act)

    return x_tens
Beispiel #5
0
def dense_block(
        name: str,
        x_tens: tf_compat.Tensor,
        training: Union[bool, tf_compat.Tensor],
        channels: int,
        include_bn: bool = False,
        include_bias: bool = None,
        dropout_rate: float = None,
        act: Union[None, str] = "relu",
        kernel_initializer=tf_compat.glorot_uniform_initializer(),
        bias_initializer=tf_compat.zeros_initializer(),
        beta_initializer=tf_compat.zeros_initializer(),
        gamma_initializer=tf_compat.ones_initializer(),
):
    """
    Create a dense or fully connected op and supporting ops
    (batch norm, activation, etc) in the current graph and scope.

    :param name: The name to group all ops under in the graph
    :param x_tens: The input tensor to apply a fully connected and supporting ops to
    :param training: A bool or tensor to indicate if the net is being run
        in training mode or not. Used for batch norm and dropout
    :param channels: The number of output channels from the dense op
    :param include_bn: True to include a batch norm operation after the conv,
        False otherwise
    :param include_bias: If left unset, will add a bias if not include_bn.
        Otherwise can be set to True to include a bias after the convolution,
        False otherwise.
    :param dropout_rate: The dropout rate to apply after the fully connected
        and batch norm if included. If none, will not include batch norm
    :param act: The activation to apply after the conv op and batch norm (if included).
        Default is "relu", set to None for no activation.
    :param kernel_initializer: The initializer to use for the fully connected kernels
    :param bias_initializer: The initializer to use for the bias variable,
        if a bias is included
    :param beta_initializer: The initializer to use for the beta variable,
        if batch norm is included
    :param gamma_initializer: The initializer to use for the gamma variable,
        if gamma is included
    :return: the tensor after all ops have been applied
    """
    if include_bias is None:
        include_bias = not include_bn

    with tf_compat.variable_scope(name, reuse=tf_compat.AUTO_REUSE):
        out = tf_compat.layers.dense(
            x_tens,
            units=channels,
            use_bias=include_bias,
            kernel_initializer=kernel_initializer,
            bias_initializer=bias_initializer if include_bias else None,
            name="fc",
        )

        if include_bn:
            out = tf_compat.layers.batch_normalization(
                out,
                axis=1,
                momentum=BN_MOMENTUM,
                epsilon=BN_EPSILON,
                beta_initializer=beta_initializer,
                gamma_initializer=gamma_initializer,
                training=training,
                name="bn",
            )

        if dropout_rate and dropout_rate > 0.0:
            out = tf_compat.layers.dropout(out,
                                           dropout_rate,
                                           training=training,
                                           name="dropout")

        out = activation(out, act)

    return out
Beispiel #6
0
def depthwise_conv2d_block(
        name: str,
        x_tens: tf_compat.Tensor,
        training: Union[bool, tf_compat.Tensor],
        channels: int,
        kernel_size: int,
        padding: Union[str, int, Tuple[int, ...]] = "same",
        stride: int = 1,
        data_format: str = "channels_last",
        include_bn: bool = True,
        include_bias: bool = None,
        act: Union[None, str] = "relu",
        kernel_initializer=tf_compat.glorot_uniform_initializer(),
        bias_initializer=tf_compat.zeros_initializer(),
        beta_initializer=tf_compat.zeros_initializer(),
        gamma_initializer=tf_compat.ones_initializer(),
):
    """
    Create a depthwise convolution op and supporting ops (batch norm, activation, etc)
    in the current graph and scope.

    :param name: The name to group all ops under in the graph
    :param x_tens: The input tensor to apply a convolution and supporting ops to
    :param training: A bool or tensor to indicate if the net is being run
        in training mode or not. Used for batch norm
    :param channels: The number of output channels from the conv op
    :param kernel_size: The size of the kernel to use for the conv op
    :param padding: Any padding to apply to the tensor before the convolution;
        if string then uses tensorflows built in padding, else uses symmetric_pad2d
    :param stride: The stride to apply for the convolution
    :param data_format: Either channels_last or channels_first
    :param include_bn: True to include a batch norm operation after the conv,
        False otherwise
    :param include_bias: If left unset, will add a bias if not include_bn.
        Otherwise can be set to True to include a bias after the convolution,
        False otherwise.
    :param act: The activation to apply after the conv op and batch norm (if included).
        Default is "relu", set to None for no activation.
    :param kernel_initializer: The initializer to use for the convolution kernels
    :param bias_initializer: The initializer to use for the bias variable,
        if a bias is included
    :param beta_initializer: The initializer to use for the beta variable,
        if batch norm is included
    :param gamma_initializer: The initializer to use for the gamma variable,
        if gamma is included
    :return: the tensor after all ops have been applied
    """
    if include_bias is None:
        include_bias = not include_bn

    channel_axis = 3 if data_format == "channels_last" else 1
    stride = ([1, stride, stride, 1]
              if data_format == "channels_last" else [1, stride, stride, 1])
    kernel_shape = (kernel_size, kernel_size, int(x_tens.shape[channel_axis]),
                    1)

    with tf_compat.variable_scope(name, reuse=tf_compat.AUTO_REUSE):
        with tf_compat.variable_scope("conv"):
            kernel = tf_compat.get_variable(
                "kernel",
                shape=kernel_shape,
                initializer=kernel_initializer,
                trainable=True,
            )
            bias = (tf_compat.get_variable(
                "bias",
                shape=(channels, ),
                initializer=bias_initializer,
                trainable=True,
            ) if include_bias else None)

            out = symmetric_pad2d(x_tens, padding, data_format)
            out = tf_compat.nn.depthwise_conv2d(
                out,
                kernel,
                stride,
                padding=padding.upper()
                if isinstance(padding, str) else "VALID",
                data_format="NHWC"
                if data_format == "channels_last" else "NCHW",
            )

            if bias is not None:
                out = tf_compat.nn.bias_add(out, bias, data_format)

        if include_bn:
            out = tf_compat.layers.batch_normalization(
                out,
                axis=3 if data_format == "channels_last" else 1,
                momentum=BN_MOMENTUM,
                epsilon=BN_EPSILON,
                beta_initializer=beta_initializer,
                gamma_initializer=gamma_initializer,
                training=training,
                name="bn",
            )

        out = activation(out, act)

    return out
Beispiel #7
0
def mobilenet_v2_width(
    width_mult: float,
    inputs: tf_compat.Tensor,
    training: Union[bool, tf_compat.Tensor] = True,
    num_classes: int = 1000,
    class_type: str = None,
    kernel_initializer=tf_compat.glorot_uniform_initializer(),
    bias_initializer=tf_compat.zeros_initializer(),
    beta_initializer=tf_compat.zeros_initializer(),
    gamma_initializer=tf_compat.ones_initializer(),
) -> tf_compat.Tensor:
    """
    Standard MobileNetV2 implementation for a given width;
    expected input shape is (B, 224, 224, 3)

    :param width_mult: The width multiplier for the architecture to create.
        1.0 is standard, 0.5 is half the size, 2.0 is twice the size.
    :param inputs: The input tensor to the MobileNet architecture
    :param training: bool or Tensor to specify if the model should be run
        in training or inference mode
    :param num_classes: The number of classes to classify
    :param class_type: One of [single, multi, None] to support multi class training.
        Default single. If None, then will not add the fully connected at the end.
    :param kernel_initializer: Initializer to use for the conv and
        fully connected kernels
    :param bias_initializer: Initializer to use for the bias in the fully connected
    :param beta_initializer: Initializer to use for the batch norm beta variables
    :param gamma_initializer: Initializer to use for the batch norm gama variables
    :return: the output tensor from the created graph
    """

    sec_settings = [
        MobileNetV2Section(
            num_blocks=1,
            out_channels=16,
            exp_channels=32,
            downsample=False,
            init_section=True,
            width_mult=width_mult,
        ),
        MobileNetV2Section(
            num_blocks=2,
            out_channels=24,
            exp_ratio=6,
            downsample=True,
            init_section=False,
            width_mult=width_mult,
        ),
        MobileNetV2Section(
            num_blocks=3,
            out_channels=32,
            exp_ratio=6,
            downsample=True,
            init_section=False,
            width_mult=width_mult,
        ),
        MobileNetV2Section(
            num_blocks=4,
            out_channels=64,
            exp_ratio=6,
            downsample=True,
            init_section=False,
            width_mult=width_mult,
        ),
        MobileNetV2Section(
            num_blocks=3,
            out_channels=96,
            exp_ratio=6,
            downsample=False,
            init_section=False,
            width_mult=width_mult,
        ),
        MobileNetV2Section(
            num_blocks=3,
            out_channels=160,
            exp_ratio=6,
            downsample=True,
            init_section=False,
            width_mult=width_mult,
        ),
        MobileNetV2Section(
            num_blocks=1,
            out_channels=320,
            exp_ratio=6,
            downsample=False,
            init_section=False,
            width_mult=width_mult,
        ),
    ]

    return mobilenet_v2_const(
        inputs,
        training,
        sec_settings,
        num_classes,
        class_type,
        kernel_initializer,
        bias_initializer,
        beta_initializer,
        gamma_initializer,
    )