File size: 4,380 Bytes
747451d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
# /*---------------------------------------------------------------------------------------------
#  * Copyright (c) 2016 Refikcanmalli
#  * Copyright (c) 2022 STMicroelectronics.
#  * All rights reserved.
#  * This software is licensed under terms that can be found in the LICENSE file in
#  * the root directory of this software component.
#  * If no LICENSE file comes with this software, it is provided AS-IS.
#  *--------------------------------------------------------------------------------------------*/

import keras
from keras import layers
from typing import Tuple


def _fire_module(x: keras.layers.Layer, fire_id: int, squeeze: int = 16, expand: int = 64) -> keras.layers.Layer:
    """
    Fire module for the SqueezeNet model.
    Implements expand layer, which has a mix of 1x1 and 3x3 filters,
    by using two conv layers concatenated in the channel dimension.

    Args:
    - x: input tensor.
    - fire_id: integer, the id of the fire module.
    - squeeze: integer, the number of filters in the squeeze layer.
    - expand: integer, the number of filters in the expand layer.

    Returns:
    - keras.layers.Layer object, the output tensor.

    """
    # Define some constants
    sq1x1 = "squeeze1x1"
    exp1x1 = "expand1x1"
    exp3x3 = "expand3x3"
    relu = "relu_"

    # Define the id of the fire module
    s_id = 'fire' + str(fire_id) + '_'

    # Get the channel axis
    if keras.backend.image_data_format() == 'channels_first':
        channel_axis = 1
    else:
        channel_axis = 3

    # Squeeze layer
    x = layers.Convolution2D(squeeze, (1, 1), padding='valid', name=s_id + sq1x1)(x)
    x = layers.Activation('relu', name=s_id + relu + sq1x1)(x)

    # Expand layer
    left = layers.Convolution2D(expand, (1, 1), padding='valid', name=s_id + exp1x1)(x)
    left = layers.Activation('relu', name=s_id + relu + exp1x1)(left)

    right = layers.Convolution2D(expand, (3, 3), padding='same', name=s_id + exp3x3)(x)
    right = layers.Activation('relu', name=s_id + relu + exp3x3)(right)

    x = layers.concatenate([left, right], axis=channel_axis, name=s_id + 'concat')

    return x


def get_squeezenetv11(num_classes: int = None, input_shape: Tuple[int, int, int] = None,
                      dropout: float = None, pretrained: bool = False, **kwargs) -> keras.Model:
    """
    Returns a SqueezeNet model with the specified number of output classes.

    Args:
    - num_classes: integer, the number of output classes.
    - input_shape: tuple of integers, the shape of the input tensor (height, width, channels).
    - dropout: float between 0 and 1, the dropout rate to apply.

    Returns:
    - keras.Model object, the SqueezeNet model.

    """
    
    if pretrained:
      print("WARNING: No pretrained weights are found for 'squeezenetv11' model. Random weights are used instead.")

    # Define the input tensor
    input_image = layers.Input(input_shape)

    # First convolutional layer
    x = layers.Convolution2D(64, (3, 3), strides=(2, 2), padding='valid', name='conv1')(input_image)
    x = layers.Activation('relu', name='relu_conv1')(x)
    x = layers.MaxPooling2D(pool_size=(3, 3), strides=(2, 2), name='pool1')(x)

    # Fire modules
    x = _fire_module(x, fire_id=2, squeeze=16, expand=64)
    x = _fire_module(x, fire_id=3, squeeze=16, expand=64)
    x = layers.MaxPooling2D(pool_size=(3, 3), strides=(2, 2), name='pool3')(x)

    x = _fire_module(x, fire_id=4, squeeze=32, expand=128)
    x = _fire_module(x, fire_id=5, squeeze=32, expand=128)
    x = layers.MaxPooling2D(pool_size=(3, 3), strides=(2, 2), name='pool5')(x)

    x = _fire_module(x, fire_id=6, squeeze=48, expand=192)
    x = _fire_module(x, fire_id=7, squeeze=48, expand=192)
    x = _fire_module(x, fire_id=8, squeeze=64, expand=256)
    x = _fire_module(x, fire_id=9, squeeze=64, expand=256)

    # Dropout layer
    if dropout:
        x = layers.Dropout(dropout, name='drop9')(x)

    # Final convolutional layer
    x = layers.Convolution2D(num_classes, (1, 1), padding='valid', name='conv10')(x)
    x = layers.Activation('relu', name='relu_conv10')(x)

    # Global average pooling layer
    x = layers.GlobalAveragePooling2D()(x)

    # Softmax activation layer
    output = layers.Activation('softmax', name='loss')(x)

    # Create the model
    model = keras.Model(input_image, output, name='squeezenetv11')

    return model