File size: 5,208 Bytes
b87f5fe
7057729
b87f5fe
 
7057729
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
b87f5fe
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
"""Model classes required for deserializing .keras files.

Must be imported before tf.keras.models.load_model() so that keras
can resolve the registered custom classes.
"""

import keras
import tensorflow as tf


@keras.saving.register_keras_serializable()
class FeedForwardNetwork(tf.keras.Model):
    """Fully-connected feedforward network for 6-class HAR classification.

    Architecture: Dense(512) β†’ BN β†’ ReLU β†’ Dropout
                  Dense(256) β†’ BN β†’ ReLU β†’ Dropout
                  Dense(128) β†’ BN β†’ ReLU β†’ Dropout
                  Dense(6, softmax)
    """

    def __init__(
        self,
        num_features,
        num_classes,
        hidden_units=(512, 256, 128),
        dropout_rate=0.3,
        **kwargs,
    ):
        super().__init__(**kwargs)
        self._num_features = num_features
        self._num_classes = num_classes
        self._hidden_units = tuple(hidden_units)
        self._dropout_rate = dropout_rate

        self.hidden_blocks = []
        for units in hidden_units:
            self.hidden_blocks.append([
                tf.keras.layers.Dense(units, use_bias=False),
                tf.keras.layers.BatchNormalization(),
                tf.keras.layers.ReLU(),
                tf.keras.layers.Dropout(dropout_rate),
            ])

        self.output_layer = tf.keras.layers.Dense(num_classes, activation="softmax")

    def call(self, inputs, training=False):
        x = inputs
        for block in self.hidden_blocks:
            for layer in block:
                if isinstance(layer, (tf.keras.layers.BatchNormalization,
                                      tf.keras.layers.Dropout)):
                    x = layer(x, training=training)
                else:
                    x = layer(x)
        return self.output_layer(x)

    def get_config(self):
        config = super().get_config()
        config.update({
            "num_features": self._num_features,
            "num_classes": self._num_classes,
            "hidden_units": self._hidden_units,
            "dropout_rate": self._dropout_rate,
        })
        return config


@keras.saving.register_keras_serializable()
class Conv1DNetwork(tf.keras.Model):
    """1D-CNN for classification on pre-computed feature vectors.

    Architecture: Reshape(561, 1)
                  β†’ Conv1D(64,  k=5) β†’ BN β†’ ReLU β†’ MaxPool(2) β†’ Dropout(0.3)
                  β†’ Conv1D(128, k=5) β†’ BN β†’ ReLU β†’ MaxPool(2) β†’ Dropout(0.3)
                  β†’ Conv1D(256, k=3) β†’ BN β†’ ReLU β†’ GlobalAvgPool1D
                  β†’ Dense(128) β†’ BN β†’ ReLU β†’ Dropout(0.5)
                  β†’ Dense(6, softmax)
    """

    def __init__(
        self,
        num_features,
        num_classes,
        dropout_rate=0.3,
        **kwargs,
    ):
        super().__init__(**kwargs)
        self._num_features = num_features
        self._num_classes = num_classes
        self._dropout_rate = dropout_rate

        self.reshape = tf.keras.layers.Reshape((num_features, 1))

        self.conv1 = tf.keras.layers.Conv1D(64, kernel_size=5, padding="same", use_bias=False)
        self.bn1   = tf.keras.layers.BatchNormalization()
        self.relu1 = tf.keras.layers.ReLU()
        self.pool1 = tf.keras.layers.MaxPooling1D(pool_size=2)
        self.drop1 = tf.keras.layers.Dropout(dropout_rate)

        self.conv2 = tf.keras.layers.Conv1D(128, kernel_size=5, padding="same", use_bias=False)
        self.bn2   = tf.keras.layers.BatchNormalization()
        self.relu2 = tf.keras.layers.ReLU()
        self.pool2 = tf.keras.layers.MaxPooling1D(pool_size=2)
        self.drop2 = tf.keras.layers.Dropout(dropout_rate)

        self.conv3 = tf.keras.layers.Conv1D(256, kernel_size=3, padding="same", use_bias=False)
        self.bn3   = tf.keras.layers.BatchNormalization()
        self.relu3 = tf.keras.layers.ReLU()
        self.gap   = tf.keras.layers.GlobalAveragePooling1D()

        self.dense1  = tf.keras.layers.Dense(128, use_bias=False)
        self.bn_fc   = tf.keras.layers.BatchNormalization()
        self.relu_fc = tf.keras.layers.ReLU()
        self.drop_fc = tf.keras.layers.Dropout(0.5)

        self.output_layer = tf.keras.layers.Dense(num_classes, activation="softmax")

    def call(self, inputs, training=False):
        x = self.reshape(inputs)

        x = self.conv1(x)
        x = self.bn1(x, training=training)
        x = self.relu1(x)
        x = self.pool1(x)
        x = self.drop1(x, training=training)

        x = self.conv2(x)
        x = self.bn2(x, training=training)
        x = self.relu2(x)
        x = self.pool2(x)
        x = self.drop2(x, training=training)

        x = self.conv3(x)
        x = self.bn3(x, training=training)
        x = self.relu3(x)
        x = self.gap(x)

        x = self.dense1(x)
        x = self.bn_fc(x, training=training)
        x = self.relu_fc(x)
        x = self.drop_fc(x, training=training)

        return self.output_layer(x)

    def get_config(self):
        config = super().get_config()
        config.update({
            "num_features": self._num_features,
            "num_classes": self._num_classes,
            "dropout_rate": self._dropout_rate,
        })
        return config