airontools 0.1.18__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,29 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2021, Claudi Ruiz Camps
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ 3. Neither the name of the copyright holder nor the names of its
17
+ contributors may be used to endorse or promote products derived from
18
+ this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,22 @@
1
+ Metadata-Version: 2.1
2
+ Name: airontools
3
+ Version: 0.1.18
4
+ Summary: AIronTools (Beta) is a Python library that provides the user with deep learning tools built to work with tensorflow as a backend.
5
+ Home-page: https://github.com/AtrejuArtax/airontools
6
+ License: License :: OSI Approved :: BSD License
7
+ Author: Claudi Ruiz Camps
8
+ Author-email: claudi_ruiz@hotmail.com
9
+ Requires-Python: >=3.9,<3.11
10
+ Classifier: License :: OSI Approved :: BSD License
11
+ Classifier: License :: Other/Proprietary License
12
+ Classifier: Operating System :: OS Independent
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3
17
+ Requires-Dist: scikit-learn (>=1.2.2,<2.0.0)
18
+ Requires-Dist: tensorflow (==2.12) ; sys_platform != "darwin"
19
+ Requires-Dist: tensorflow-datasets (>=4.9.2,<5.0.0)
20
+ Requires-Dist: tensorflow-macos (==2.12) ; sys_platform == "darwin"
21
+ Requires-Dist: tensorflow-metal (==0.8.0) ; sys_platform == "darwin" and platform_machine == "arm64"
22
+ Project-URL: Repository, https://github.com/AtrejuArtax/airontools
File without changes
File without changes
@@ -0,0 +1,78 @@
1
+ from typing import List, Tuple, Union
2
+
3
+ import tensorflow as tf
4
+
5
+ from airontools.constructors.layers import layer_constructor
6
+
7
+
8
+ def block_constructor(
9
+ units: List[int],
10
+ input_shape: Tuple[int],
11
+ name: str = "block",
12
+ sequential: bool = False,
13
+ bidirectional: bool = False,
14
+ from_l: int = 1,
15
+ hidden_activation: str = "prelu",
16
+ output_activation: Union[str, tf.keras.layers.Layer] = "linear",
17
+ kernel_regularizer_l1: float = 0.001,
18
+ kernel_regularizer_l2: float = 0.001,
19
+ bias_regularizer_l1: float = 0.001,
20
+ bias_regularizer_l2: float = 0.001,
21
+ dropout_rate: float = 0.0,
22
+ bn: bool = False,
23
+ ) -> tf.keras.models.Model:
24
+ """It builds a custom block. For now only compatible with dense and sequential layers.
25
+
26
+ Parameters:
27
+ units (list): Number of units per hidden layer.
28
+ input_shape (tuple): Input shape.
29
+ name (str): Name of the block.
30
+ sequential (bool): Whether to consider a sequential model or not.
31
+ bidirectional (bool): Whether to consider bidirectional case or not (only active if sequential).
32
+ from_l (int): The number indicator of the first hidden layer of the block, useful to make sure that layer
33
+ names are not repeated.
34
+ hidden_activation (str, Layer): Hidden activation function.
35
+ output_activation (str, Layer): The activation function of the output of the block.
36
+ dropout_rate (float): Probability of each intput being disconnected.
37
+ kernel_regularizer_l1 (float): Kernel regularization using l1 penalization (Lasso).
38
+ kernel_regularizer_l2 (float): Kernel regularization using l2 penalization (Ridge).
39
+ bias_regularizer_l1 (float): Bias regularization using l1 penalization (Lasso).
40
+ bias_regularizer_l2 (float): Bias regularization using l2 penalization (Ridge).
41
+ bn (bool): If set, a batch normalization layer will be added right before the output activation function.
42
+
43
+ Returns:
44
+ model (Model): A keras model.
45
+ """
46
+
47
+ # Hidden layers
48
+ i_l, o_l = (
49
+ tf.keras.layers.Input(shape=input_shape, name="_".join([name, "input"])),
50
+ None,
51
+ )
52
+ to_l = from_l + len(units)
53
+ for l, o_dim in zip(range(from_l, to_l), units):
54
+ if l <= from_l:
55
+ o_l = i_l
56
+ o_l = layer_constructor(
57
+ x=o_l,
58
+ units=o_dim,
59
+ activation=hidden_activation
60
+ if l == to_l - 1 is None
61
+ else output_activation,
62
+ name=name,
63
+ name_ext=str(l),
64
+ sequential=sequential,
65
+ return_sequences=True if l < to_l - 1 and sequential else False,
66
+ bidirectional=bidirectional,
67
+ kernel_regularizer_l1=kernel_regularizer_l1,
68
+ kernel_regularizer_l2=kernel_regularizer_l2,
69
+ bias_regularizer_l1=bias_regularizer_l1,
70
+ bias_regularizer_l2=bias_regularizer_l2,
71
+ dropout_rate=dropout_rate,
72
+ bn=bn,
73
+ )
74
+
75
+ # Model
76
+ model = tf.keras.models.Model(inputs=i_l, outputs=o_l, name=name)
77
+
78
+ return model
@@ -0,0 +1,456 @@
1
+ import warnings
2
+ from typing import Tuple, Union
3
+
4
+ import numpy as np
5
+ import tensorflow as tf
6
+
7
+ from airontools.constructors.utils import get_regularizer
8
+
9
+
10
+ def layer_constructor(
11
+ x: Union[tf.Tensor, tf.keras.layers.Layer],
12
+ units: int,
13
+ name: str = "layer",
14
+ name_ext: str = "",
15
+ num_heads: int = 0,
16
+ key_dim: int = 0,
17
+ value_dim: int = 0,
18
+ activation: Union[str, tf.keras.layers.Activation] = "prelu",
19
+ use_bias: bool = True,
20
+ sequential: bool = False,
21
+ bidirectional: bool = False,
22
+ return_sequences: bool = False,
23
+ filters: int = 0,
24
+ kernel_size: Union[int, Tuple[int]] = 0,
25
+ padding: str = "valid",
26
+ pooling: Union[str, tf.keras.layers.Layer] = None,
27
+ pool_size: Union[int, Tuple[int]] = 1,
28
+ conv_transpose: bool = False,
29
+ strides: Union[int, Tuple[int]] = 1,
30
+ sequential_axis: int = 1,
31
+ kernel_regularizer_l1: float = 0.001,
32
+ kernel_regularizer_l2: float = 0.001,
33
+ bias_regularizer_l1: float = 0.001,
34
+ bias_regularizer_l2: float = 0.001,
35
+ dropout_rate: float = 0.0,
36
+ bn: bool = False,
37
+ ) -> tf.Tensor:
38
+ """It builds a custom layer. For now only 2D convolutions
39
+ are supported for input of rank 4.
40
+
41
+ Parameters:
42
+ x (tf.Tensor, tf.keras.layers.Layer): Input layer or tensor.
43
+ units (int): Number of units for the dense layer. If a value is given, a dense layer will be added
44
+ automatically if not sequential, else a sequential model. Useful to force an output dimensionality of the
45
+ custom layer when using convolutional layers.
46
+ name (str): Name of the custom layer.
47
+ name_ext (str): Extension name for the custom layer that will be at the end of it.
48
+ num_heads (int): Number of heads for the multi-head attention layer.
49
+ key_dim (int): Key dimensionality for the multi-head attention layer, if None then the number of units is
50
+ used instead.
51
+ value_dim (int): Value dimensionality for the multi-head attention layer, if None then key_dim is used
52
+ instead.
53
+ activation (str, tf.keras.layers.Activation): The activation function of the output of the last hidden layer.
54
+ use_bias (bool): Whether to sue bias or not.
55
+ sequential (bool): Whether to consider a sequential custom layer or not. Sequential and self-attention
56
+ (num_heads > 0) are not compatible.
57
+ bidirectional (bool): Whether to consider bidirectional case or not (only active if sequential).
58
+ names are not repeated.
59
+ return_sequences (bool): Whether to return sequences or not (only active if sequential).
60
+ filters (int): Number of filters to be used. If a value is given, a convolutional layer will be
61
+ automatically added.
62
+ kernel_size (int, Tuple[int]): Kernel size for the convolutional layer.
63
+ conv_transpose (bool): Whether to use a transpose conv layer or not (only active if filters and
64
+ kernel_size are set).
65
+ strides (int, Tuple[int]): Strides for the conv layer (only active if filters and
66
+ kernel_size are set).
67
+ padding (str): Padding to be applied (only active if filters and
68
+ kernel_size are set).
69
+ pooling (str, tf.keras.layers.Layer): Pooling type.
70
+ pool_size (int, Tuple[int]): Pooling size.
71
+ sequential_axis (int): The axis that defines the sequence. For sequential models is normally 1. For
72
+ self-attention (num_heads > 0) and image-like inputs, the sequential axis is the channel axis (3 for 2D
73
+ images and 4 for 3D images).
74
+ kernel_regularizer_l1 (float): Kernel regularization using l1 penalization (Lasso).
75
+ kernel_regularizer_l2 (float): Kernel regularization using l2 penalization (Ridge).
76
+ bias_regularizer_l1 (float): Bias regularization using l1 penalization (Lasso).
77
+ bias_regularizer_l2 (float): Bias regularization using l2 penalization (Ridge).
78
+ dropout_rate (float): Dropout rate.
79
+ bn (bool): If set, a batch normalization layer will be added right before the output activation function.
80
+
81
+ Returns:
82
+ x (tf.keras.layers.Layer): A keras layer.
83
+ """
84
+
85
+ if num_heads > 0 and units is None and key_dim == 0:
86
+ warnings.warn(
87
+ "in order to use a multi-head attention layer either units or key_dim needs to be set",
88
+ )
89
+
90
+ # Dropout
91
+ if dropout_rate != 0:
92
+ x = dropout_layer_constructor(
93
+ x,
94
+ name=name,
95
+ name_ext=name_ext,
96
+ dropout_rate=dropout_rate,
97
+ )
98
+
99
+ # Convolution
100
+ conv_condition = all(
101
+ [conv_param != 0 for conv_param in [filters, kernel_size]],
102
+ )
103
+ if conv_condition:
104
+ if isinstance(strides, int):
105
+ _strides = tuple([strides] * _get_pooling_dim(x))
106
+ else:
107
+ _strides = strides
108
+ conv_kwargs = dict(
109
+ use_bias=use_bias,
110
+ filters=filters,
111
+ kernel_size=kernel_size,
112
+ strides=_strides,
113
+ padding=padding,
114
+ kernel_regularizer=get_regularizer(
115
+ kernel_regularizer_l1,
116
+ kernel_regularizer_l2,
117
+ ),
118
+ bias_regularizer=get_regularizer(bias_regularizer_l1, bias_regularizer_l2),
119
+ )
120
+ x = convolutional_layer_constructor(
121
+ x,
122
+ name=name,
123
+ name_ext=name_ext,
124
+ conv_transpose=conv_transpose,
125
+ **conv_kwargs,
126
+ )
127
+
128
+ # Pooling
129
+ if pooling is not None:
130
+ if isinstance(pool_size, int):
131
+ _pool_size = tuple([pool_size] * _get_pooling_dim(x))
132
+ else:
133
+ _pool_size = pool_size
134
+ pooling_kwargs = dict(
135
+ pool_size=_pool_size,
136
+ strides=strides,
137
+ padding=padding,
138
+ )
139
+ x = pooling_layer_constructor(
140
+ x,
141
+ name=name,
142
+ name_ext=name_ext,
143
+ conv_transpose=conv_transpose,
144
+ pooling=pooling,
145
+ **pooling_kwargs,
146
+ )
147
+
148
+ # Multi-Head Attention
149
+ if num_heads > 0:
150
+ _key_dim = key_dim if key_dim > 0 else units
151
+ _value_dim = value_dim if value_dim > 0 else _key_dim
152
+ multi_head_attention_kwargs = dict(
153
+ num_heads=num_heads,
154
+ key_dim=_key_dim,
155
+ value_dim=_value_dim,
156
+ use_bias=use_bias,
157
+ kernel_regularizer=get_regularizer(
158
+ kernel_regularizer_l1,
159
+ kernel_regularizer_l2,
160
+ ),
161
+ bias_regularizer=get_regularizer(bias_regularizer_l1, bias_regularizer_l2),
162
+ )
163
+ x = self_attention_layer_constructor(
164
+ x,
165
+ name=name,
166
+ name_ext=name_ext,
167
+ sequential_axis=sequential_axis,
168
+ **multi_head_attention_kwargs,
169
+ )
170
+
171
+ # Sequential
172
+ elif sequential:
173
+ seq_kwargs = dict(
174
+ units=units,
175
+ use_bias=use_bias,
176
+ kernel_regularizer=get_regularizer(
177
+ kernel_regularizer_l1,
178
+ kernel_regularizer_l2,
179
+ ),
180
+ bias_regularizer=get_regularizer(bias_regularizer_l1, bias_regularizer_l2),
181
+ return_sequences=return_sequences,
182
+ activation="linear",
183
+ )
184
+ x = sequential_layer_constructor(
185
+ x,
186
+ name=name,
187
+ name_ext=name_ext,
188
+ bidirectional=bidirectional,
189
+ sequential_axis=sequential_axis,
190
+ **seq_kwargs,
191
+ )
192
+
193
+ # Dense
194
+ if units > 0:
195
+ dense_kwargs = dict(
196
+ units=units,
197
+ use_bias=use_bias,
198
+ kernel_regularizer=get_regularizer(
199
+ kernel_regularizer_l1,
200
+ kernel_regularizer_l2,
201
+ ),
202
+ bias_regularizer=get_regularizer(bias_regularizer_l1, bias_regularizer_l2),
203
+ )
204
+ x = dense_layer_constructor(
205
+ x,
206
+ name=name,
207
+ name_ext=name_ext,
208
+ **dense_kwargs,
209
+ )
210
+
211
+ # Batch Normalization
212
+ if bn:
213
+ bn_kwargs = dict(
214
+ beta_regularizer=get_regularizer(bias_regularizer_l1, bias_regularizer_l2),
215
+ gamma_regularizer=get_regularizer(bias_regularizer_l1, bias_regularizer_l2),
216
+ )
217
+ x = bn_layer_constructor(x, name=name, name_ext=name_ext, **bn_kwargs)
218
+
219
+ # Activation
220
+ activation_kwargs = dict(
221
+ alpha_regularizer=get_regularizer(bias_regularizer_l1, bias_regularizer_l2),
222
+ )
223
+ x = activation_layer_constructor(
224
+ x,
225
+ name=name,
226
+ name_ext=name_ext,
227
+ activation=activation,
228
+ **activation_kwargs,
229
+ )
230
+
231
+ return x
232
+
233
+
234
+ def dropout_layer_constructor(
235
+ x: Union[tf.Tensor, tf.keras.layers.Layer],
236
+ dropout_rate: float,
237
+ name: str = "dropout",
238
+ name_ext: str = "",
239
+ ) -> tf.keras.layers.Layer:
240
+ input_shape = x.shape
241
+ output_reshape = None
242
+ if len(input_shape) > 2:
243
+ output_reshape = input_shape
244
+ x = tf.keras.layers.Flatten(
245
+ name="_".join([name, "pre", "dropout", "flatten", name_ext])
246
+ )(x)
247
+ x = CustomDropout(name="_".join([name, "dropout", name_ext]), rate=dropout_rate)(x)
248
+ if output_reshape is not None:
249
+ x = tf.keras.layers.Reshape(
250
+ name="_".join([name, "post", "dropout", "reshape", name_ext]),
251
+ target_shape=output_reshape[1:],
252
+ )(x)
253
+ return x
254
+
255
+
256
+ def convolutional_layer_constructor(
257
+ x: Union[tf.Tensor, tf.keras.layers.Layer],
258
+ name: str = "convolution",
259
+ name_ext: str = "",
260
+ conv_transpose: bool = False,
261
+ **kwargs,
262
+ ) -> tf.keras.layers.Layer:
263
+ assert len(x.shape) <= 3, "x layer shape should have 5 or less dimensions"
264
+ conv_dim = len(x.shape) - 2
265
+ conv_type = "transpose" if conv_transpose else ""
266
+ conv_name = "conv" + str(conv_dim) + "d" + conv_type.capitalize()
267
+ layer_name = "_".join([name, conv_name, name_ext])
268
+ if conv_dim == 1:
269
+ conv_layer = tf.keras.layers.Conv1D
270
+ elif conv_dim == 2:
271
+ conv_layer = tf.keras.layers.Conv2D
272
+ else:
273
+ conv_layer = tf.keras.layers.Conv3D
274
+ x = conv_layer(
275
+ name=layer_name,
276
+ **kwargs,
277
+ )(x)
278
+ return x
279
+
280
+
281
+ def pooling_layer_constructor(
282
+ x: Union[tf.Tensor, tf.keras.layers.Layer],
283
+ name: str = "pooling",
284
+ name_ext: str = "",
285
+ pooling: Union[str, tf.keras.layers.Layer] = "max",
286
+ **kwargs,
287
+ ) -> tf.keras.layers.Layer:
288
+ if isinstance(pooling, str):
289
+ pooling_name = pooling.capitalize() + "Pooling" + str(_get_pooling_dim(x)) + "D"
290
+ pooling_layer = globals()[pooling_name]
291
+ else:
292
+ pooling_name = [k for k, v in locals().iteritems() if v == pooling][0]
293
+ pooling_layer = pooling
294
+ x = pooling_layer(name="_".join([name, pooling_name.lower(), name_ext]))(x)
295
+ return x
296
+
297
+
298
+ def _get_pooling_dim(x: tf.keras.layers.Layer) -> int:
299
+ return len(x.shape) - 2
300
+
301
+
302
+ def self_attention_layer_constructor(
303
+ x: Union[tf.Tensor, tf.keras.layers.Layer],
304
+ name: str = "self_attention",
305
+ name_ext: str = "",
306
+ sequential_axis: int = 1,
307
+ **kwargs,
308
+ ) -> tf.keras.layers.Layer:
309
+ x = sequential_permutation(
310
+ x=x,
311
+ name=name,
312
+ name_ext=name_ext,
313
+ sequential_axis=sequential_axis,
314
+ )
315
+ x = tf.keras.layers.MultiHeadAttention(
316
+ name="_".join([name, "multi_head_attention", name_ext]),
317
+ **kwargs,
318
+ )(x, x)
319
+ return x
320
+
321
+
322
+ def sequential_layer_constructor(
323
+ x: Union[tf.Tensor, tf.keras.layers.Layer],
324
+ name: str = "sequential",
325
+ name_ext: str = "",
326
+ bidirectional: bool = False,
327
+ sequential_axis: int = 1,
328
+ **kwargs,
329
+ ) -> tf.keras.layers.Layer:
330
+ x = sequential_permutation(
331
+ x=x,
332
+ name=name,
333
+ name_ext=name_ext,
334
+ sequential_axis=sequential_axis,
335
+ )
336
+ if bidirectional:
337
+ x = tf.keras.layers.Bidirectional(
338
+ tf.keras.layers.GRU(name="_".join([name, "gru", name_ext]), **kwargs)
339
+ )(x)
340
+ else:
341
+ x = tf.keras.layers.GRU(name="_".join([name, "gru", name_ext]), **kwargs)(x)
342
+ return x
343
+
344
+
345
+ def dense_layer_constructor(
346
+ x: Union[tf.Tensor, tf.keras.layers.Layer],
347
+ name: str = "dense",
348
+ name_ext: str = "",
349
+ **kwargs,
350
+ ) -> tf.keras.layers.Layer:
351
+ if not len(x.shape[1:]) == 1:
352
+ x = tf.keras.layers.Flatten(
353
+ name="_".join([name, "pre", "dense", "flatten", name_ext])
354
+ )(x)
355
+ x = tf.keras.layers.Dense(name="_".join([name, "dense", name_ext]), **kwargs)(x)
356
+ return x
357
+
358
+
359
+ def bn_layer_constructor(
360
+ x: Union[tf.Tensor, tf.keras.layers.Layer], name: str, name_ext: str, **kwargs
361
+ ) -> tf.keras.layers.Layer:
362
+ input_shape = x.shape
363
+ output_reshape = None
364
+ if len(input_shape) > 2:
365
+ output_reshape = input_shape
366
+ x = tf.keras.layers.Flatten(
367
+ name="_".join([name, "pre", "bn", "flatten", name_ext])
368
+ )(x)
369
+ x = tf.keras.layers.BatchNormalization(
370
+ name="_".join([name, "batch_normalization", name_ext]),
371
+ **kwargs,
372
+ )(x)
373
+ if output_reshape is not None:
374
+ x = tf.keras.layers.Reshape(
375
+ name="_".join([name, "post", "bn", "reshape", name_ext]),
376
+ target_shape=output_reshape[1:],
377
+ )(x)
378
+ return x
379
+
380
+
381
+ def activation_layer_constructor(
382
+ x: Union[tf.Tensor, tf.keras.layers.Layer],
383
+ name: str = "activation",
384
+ name_ext: str = "",
385
+ activation: str = "prelu",
386
+ **reg_kwargs,
387
+ ) -> tf.keras.layers.Layer:
388
+ input_shape = x.shape
389
+ output_reshape = None
390
+ if len(input_shape) > 2:
391
+ output_reshape = input_shape
392
+ x = tf.keras.layers.Flatten(
393
+ name="_".join([name, "pre", "activation", "flatten", name_ext])
394
+ )(x)
395
+ activation_name = "_".join(
396
+ [name, activation if isinstance(activation, str) else "activation", name_ext],
397
+ )
398
+ if activation == "leakyrelu":
399
+ x = tf.keras.layers.LeakyReLU(name=activation_name)(x)
400
+ elif activation == "prelu":
401
+ x = tf.keras.layers.PReLU(name=activation_name, **reg_kwargs)(x)
402
+ elif activation == "softmax":
403
+ x = tf.keras.layers.Softmax(name=activation_name, dtype="float32")(x)
404
+ else:
405
+ x = tf.keras.layers.Activation(name=activation_name, activation=activation)(x)
406
+ if output_reshape is not None:
407
+ x = tf.keras.layers.Reshape(
408
+ name="_".join([name, "post", "activation", "reshape", name_ext]),
409
+ target_shape=output_reshape[1:],
410
+ )(x)
411
+ return x
412
+
413
+
414
+ def sequential_permutation(
415
+ x: Union[tf.Tensor, tf.keras.layers.Layer],
416
+ name: str = "permutation",
417
+ name_ext: str = "",
418
+ sequential_axis: int = 1,
419
+ ) -> tf.keras.layers.Layer:
420
+ input_shape = x.shape
421
+ sequential_axis_ = list(range(len(input_shape)))[sequential_axis]
422
+ if sequential_axis_ != 1:
423
+ permutation = tuple(
424
+ [sequential_axis_]
425
+ + [i for i in range(1, len(input_shape[1:])) if i != sequential_axis_],
426
+ )
427
+ x = tf.keras.layers.Permute(
428
+ name="_".join([name, "permutation", name_ext]), dims=permutation
429
+ )(x)
430
+ else:
431
+ permutation = list(range(1, len(input_shape)))
432
+ if len(input_shape) > 2:
433
+ x = tf.keras.layers.Reshape(
434
+ name="_".join([name, "reshape", name_ext]),
435
+ target_shape=(
436
+ input_shape[permutation[0]],
437
+ np.prod([input_shape[i] for i in permutation[1:]]),
438
+ ),
439
+ )(x)
440
+ return x
441
+
442
+
443
+ def identity(x: tf.keras.layers.Layer) -> tf.keras.layers.Layer:
444
+ """Identity layer."""
445
+ return x
446
+
447
+
448
+ class CustomDropout(tf.keras.layers.Dropout):
449
+ def __init__(self, **kwargs):
450
+ super().__init__(**kwargs)
451
+ self.rate = tf.Variable(
452
+ self.rate,
453
+ trainable=False,
454
+ name="_".join([self.name, "rate"]),
455
+ dtype=self.dtype,
456
+ )
@@ -0,0 +1,31 @@
1
+ import abc
2
+ from typing import Dict, List, Union
3
+
4
+ import tensorflow as tf
5
+ from numpy.typing import NDArray
6
+
7
+
8
+ class Model(abc.ABC):
9
+ @abc.abstractmethod
10
+ def compile(self, *args, **kwargs) -> None:
11
+ pass
12
+
13
+ @abc.abstractmethod
14
+ def fit(self, *args, **kwargs) -> None:
15
+ pass
16
+
17
+ @abc.abstractmethod
18
+ def evaluate(self, *args, **kwargs) -> Dict[str, tf.Tensor]:
19
+ pass
20
+
21
+ @abc.abstractmethod
22
+ def predict(self, *args, **kwargs) -> Union[List[NDArray[float]], NDArray[float]]:
23
+ pass
24
+
25
+ @abc.abstractmethod
26
+ def save_weights(self, *args, **kwargs) -> None:
27
+ pass
28
+
29
+ @abc.abstractmethod
30
+ def load_weights(self, *args, **kwargs) -> None:
31
+ pass