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.
- airontools-0.1.18/LICENSE +29 -0
- airontools-0.1.18/PKG-INFO +22 -0
- airontools-0.1.18/airontools/__init__.py +0 -0
- airontools-0.1.18/airontools/constructors/__init__.py +0 -0
- airontools-0.1.18/airontools/constructors/blocks.py +78 -0
- airontools-0.1.18/airontools/constructors/layers.py +456 -0
- airontools-0.1.18/airontools/constructors/models/__init__.py +0 -0
- airontools-0.1.18/airontools/constructors/models/model.py +31 -0
- airontools-0.1.18/airontools/constructors/models/supervised/__init__.py +0 -0
- airontools-0.1.18/airontools/constructors/models/supervised/classification.py +108 -0
- airontools-0.1.18/airontools/constructors/models/unsupervised/__init__.py +0 -0
- airontools-0.1.18/airontools/constructors/models/unsupervised/ae.py +126 -0
- airontools-0.1.18/airontools/constructors/models/unsupervised/vae.py +176 -0
- airontools-0.1.18/airontools/constructors/utils.py +80 -0
- airontools-0.1.18/airontools/devices.py +12 -0
- airontools-0.1.18/airontools/interactors.py +61 -0
- airontools-0.1.18/airontools/on_the_fly.py +49 -0
- airontools-0.1.18/airontools/preprocessing.py +177 -0
- airontools-0.1.18/airontools/tensorboard_utils.py +52 -0
- airontools-0.1.18/airontools/tools.py +20 -0
- airontools-0.1.18/pyproject.toml +32 -0
|
@@ -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
|
+
)
|
|
File without changes
|
|
@@ -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
|
|
File without changes
|