Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ENH] Add DCNNNetwork #1576

Open
wants to merge 35 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
72e32fb
Add DCNN
aadya940 May 17, 2024
d643b26
remove triplet loss and move utils.py to utils/networks
aadya940 May 17, 2024
c1e24ed
Add docstring and minor changes dcnn network
aadya940 May 17, 2024
02f387b
minor fixes
aadya940 May 18, 2024
79fe9fb
Update DCNNEncoderNetwork
aadya940 May 20, 2024
529e7b2
add activation kwarg
aadya940 May 20, 2024
5ed6aeb
minor
aadya940 May 20, 2024
9c3f0b2
minor
aadya940 May 27, 2024
6c7ec5a
minor fixes
aadya940 May 27, 2024
780a775
update class name
aadya940 May 27, 2024
d24b0ed
minor
aadya940 May 31, 2024
14f41c4
minor
aadya940 May 31, 2024
d93dbd3
Add temporal_latent_space kwarg
aadya940 Jun 1, 2024
8e98bd5
minor
aadya940 Jun 2, 2024
f66b3ea
minor
aadya940 Jun 2, 2024
dd18581
Add test for DCNNNetwork
aadya940 Jun 3, 2024
2ef7816
minor
aadya940 Jun 3, 2024
f3b6a57
refactor test
aadya940 Jun 4, 2024
8022250
Update test_dcnn.py
aadya940 Jun 4, 2024
8af9133
Merge branch 'main' into gsoc-dec
aadya940 Jun 21, 2024
0c92a3b
update base class
aadya940 Jun 21, 2024
29e7283
fix bug
aadya940 Jun 25, 2024
7378490
Merge branch 'main' into gsoc-dec
MatthewMiddlehurst Jun 26, 2024
2740bc1
remove temporal latent space kwarg
aadya940 Jul 10, 2024
d458f18
add _config
aadya940 Jul 10, 2024
af42c19
remove tls from tests
aadya940 Jul 12, 2024
f2dcfac
merge main
aadya940 Aug 4, 2024
09ff606
enhance tests
aadya940 Aug 7, 2024
c8f4a24
num_layers -> n_layers
aadya940 Aug 9, 2024
65f150c
num_layers => n_layers
aadya940 Aug 9, 2024
995518a
typo
aadya940 Aug 9, 2024
64f7a45
num => n
aadya940 Aug 12, 2024
2fe46e4
Merge branch 'main' into gsoc-dec
MatthewMiddlehurst Aug 16, 2024
af933ee
some fixes
aadya940 Aug 16, 2024
e2e191c
Add logic to handle int for
aadya940 Aug 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions aeon/networks/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,17 @@
"AEFCNNetwork",
"AEResNetNetwork",
"LITENetwork",
"DCNNNetwork",
"AEDRNNNetwork",
"AEBiGRUNetwork",
]

from aeon.networks._ae_bgru import AEBiGRUNetwork
from aeon.networks._ae_drnn import AEDRNNNetwork
from aeon.networks._ae_fcn import AEFCNNetwork
from aeon.networks._ae_resnet import AEResNetNetwork
from aeon.networks._cnn import CNNNetwork, TimeCNNNetwork
from aeon.networks._dcnn import DCNNNetwork
from aeon.networks._encoder import EncoderNetwork
from aeon.networks._fcn import FCNNetwork
from aeon.networks._inception import InceptionNetwork
Expand Down
149 changes: 149 additions & 0 deletions aeon/networks/_dcnn.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
"""Dilated Convolutional Nerual Networks (DCNN) Model."""

__maintainer__ = []

from aeon.networks.base import BaseDeepLearningNetwork


class DCNNNetwork(BaseDeepLearningNetwork):
"""Establish the network structure for a DCNN-Model.
aadya940 marked this conversation as resolved.
Show resolved Hide resolved

Dilated Convolutional Neural Network based Model
for low-rank embeddings.

Parameters
----------
latent_space_dim: int, default=128
Dimension of the models's latent space.
aadya940 marked this conversation as resolved.
Show resolved Hide resolved
n_layers: int, default=4
Number of convolution layers.
kernel_size: Union[int, List[int]], default=3
Size of the 1D Convolutional Kernel. Defaults
to a list of three's for `n_layers` elements.
activation: Union[str, List[str]], default="relu"
The activation function used by convolution layers.
Defaults to a list of "relu" for `n_layers` elements.
n_filters: Union[int, List[int]], default=None
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you add a sentence to n_filters and dilation_rate to how the default values are calculated ?

Number of filters used in convolution layers. Defaults
to a list of multiple's of 32 for `n_layers` elements.
dilation_rate: Union[int, List[int]], default=None
The dilation rate for convolution. Defaults to a list of
powers of 2 for `n_layers` elements.

References
----------
.. [1] Franceschi, J. Y., Dieuleveut, A., & Jaggi, M. (2019).
Unsupervised scalable representation learning for multivariate
time series. Advances in neural information processing systems, 32.
"""

_config = {
"python_dependencies": ["tensorflow"],
"python_version": "<3.12",
"structure": "encoder",
}

def __init__(
self,
latent_space_dim=128,
n_layers=4,
kernel_size=3,
aadya940 marked this conversation as resolved.
Show resolved Hide resolved
activation="relu",
n_filters=None,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should have a padding parameter, default to the value used in the original paper, also will be a list for all layers like you handle activation

dilation_rate=None,
aadya940 marked this conversation as resolved.
Show resolved Hide resolved
):
super().__init__()

self.latent_space_dim = latent_space_dim
self.kernel_size = kernel_size
self.n_filters = n_filters
self.n_layers = n_layers
self.dilation_rate = dilation_rate
self.activation = activation

def build_network(self, input_shape):
"""Construct a network and return its input and output layers.

Parameters
----------
input_shape : tuple of shape = (n_timepoints (m), n_channels (d))
The shape of the data fed into the input layer.

Returns
-------
model : a keras Model.
"""
import tensorflow as tf

if self.n_filters is None:
self._n_filters = [32 * i for i in range(1, self.n_layers + 1)]
elif isinstance(self.n_filters, int):
self._n_filters = [self.n_filters for _ in range(self.n_layers)]
elif isinstance(self.n_filters, list):
self._n_filters = self.n_filters
assert len(self.n_filters) == self.n_layers

if self.dilation_rate is None:
self._dilation_rate = [
2**layer_num for layer_num in range(1, self.n_layers + 1)
]
elif isinstance(self.dilation_rate, int):
self._dilation_rate = [self.dilation_rate for _ in range(self.n_layers)]
else:
self._dilation_rate = self.dilation_rate
assert isinstance(self.dilation_rate, list)
assert len(self.dilation_rate) == self.n_layers

if isinstance(self.kernel_size, int):
self._kernel_size = [self.kernel_size for _ in range(self.n_layers)]
elif isinstance(self.kernel_size, list):
self._kernel_size = self.kernel_size
assert len(self.kernel_size) == self.n_layers

if isinstance(self.activation, str):
self._activation = [self.activation for _ in range(self.n_layers)]
elif isinstance(self.activation, list):
self._activation = self.activation
assert len(self._activation) == self.n_layers
aadya940 marked this conversation as resolved.
Show resolved Hide resolved

input_layer = tf.keras.layers.Input(input_shape)

x = input_layer
for i in range(0, self.n_layers):
x = self._dcnn_layer(
x,
self._n_filters[i],
self._dilation_rate[i],
_activation=self._activation[i],
_kernel_size=self._kernel_size[i],
)

x = tf.keras.layers.GlobalMaxPool1D()(x)
output_layer = tf.keras.layers.Dense(self.latent_space_dim)(x)

return input_layer, output_layer

def _dcnn_layer(
self, _inputs, _n_filters, _dilation_rate, _activation, _kernel_size
):
import tensorflow as tf

_add = tf.keras.layers.Conv1D(_n_filters, kernel_size=1)(_inputs)
x = tf.keras.layers.Conv1D(
_n_filters,
kernel_size=_kernel_size,
dilation_rate=_dilation_rate,
padding="causal",
kernel_regularizer="l2",
activation=_activation,
)(_inputs)
x = tf.keras.layers.Conv1D(
_n_filters,
kernel_size=_kernel_size,
dilation_rate=_dilation_rate,
padding="causal",
kernel_regularizer="l2",
activation=_activation,
)(x)
output = tf.keras.layers.Add()([x, _add])
return output
50 changes: 50 additions & 0 deletions aeon/networks/tests/test_dcnn.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
"""Tests for the DCNN Model."""

aadya940 marked this conversation as resolved.
Show resolved Hide resolved
import random

import pytest

from aeon.networks import DCNNNetwork
from aeon.utils.validation._dependencies import _check_soft_dependencies


@pytest.mark.skipif(
not _check_soft_dependencies(["tensorflow"], severity="none"),
reason="Tensorflow soft dependency unavailable.",
)
@pytest.mark.parametrize(
"latent_space_dim,n_layers",
[
(32, 1),
(128, 2),
(256, 3),
(64, 4),
],
)
def test_dcnnnetwork_init(latent_space_dim, n_layers):
"""Test whether DCNNNetwork initializes correctly for various parameters."""
dcnnnet = DCNNNetwork(
latent_space_dim=latent_space_dim,
n_layers=n_layers,
activation=random.choice(["relu", "tanh"]),
n_filters=[random.choice([50, 25, 100]) for _ in range(n_layers)],
)
model = dcnnnet.build_network((1000, 5))
assert model is not None


@pytest.mark.skipif(
not _check_soft_dependencies(["tensorflow"], severity="none"),
reason="Tensorflow soft dependency unavailable.",
)
@pytest.mark.parametrize("activation", ["relu", "tanh"])
def test_dcnnnetwork_activations(activation):
"""Test whether DCNNNetwork initializes correctly with different activations."""
dcnnnet = DCNNNetwork(
latent_space_dim=64,
n_layers=2,
activation=activation,
n_filters=[50, 50],
)
model = dcnnnet.build_network((150, 5))
assert model is not None