Skip to content

custom_filters

Custom and learnable filters decompositions.

Classes:

ConvolutionalDecompositionBase

ConvolutionalDecompositionBase(
    k: int,
    n_dims: int,
    in_ch: int,
    m: int,
    norm: (
        Literal["backward", "forward", "ortho"] | None
    ) = "backward",
)

Bases: ABC, Module

Base class for all decompositions.

Parameters:

  • k (int) –

    Kernel size.

  • n_dims (int) –

    Number of dimensions for the convolution.

  • in_ch (int) –

    Number of input channels.

  • m (int) –

    Number of output channels.

  • norm (Literal['backward', 'forward', 'ortho'] | None, default: 'backward' ) –

    Normalization type. Defaults to "backward".

Methods:

  • analyze

    Apply the analysis (forward) transform using the kernels.

  • get_kernels

    Return the kernels to be used for the convolutions.

  • synthesize

    Apply the synthesis (inverse) transform using the kernels.

Source code in src/autoden/transforms/custom_filters.py
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
def __init__(
    self, k: int, n_dims: int, in_ch: int, m: int, norm: Literal["backward", "forward", "ortho"] | None = "backward"
) -> None:
    """Initialize the ConvolutionalDecomposition.

    Parameters
    ----------
    k : int
        Kernel size.
    n_dims : int
        Number of dimensions for the convolution.
    in_ch : int
        Number of input channels.
    m : int
        Number of output channels.
    norm : Literal["backward", "forward", "ortho"] | None, optional
        Normalization type. Defaults to "backward".
    """
    super().__init__()
    self.k = k
    self.n_dims = n_dims
    self.in_ch = in_ch
    self.m = m
    self.norm = norm

analyze

analyze(x: Tensor) -> Tensor

Apply the analysis (forward) transform using the kernels.

Parameters:

  • x (Tensor) –

    Input tensor of shape (B, in_ch, [D, H], W).

Returns:

  • Tensor

    Output tensor of shape (B, m, [D, H], W).

Source code in src/autoden/transforms/custom_filters.py
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
def analyze(self, x: pt.Tensor) -> pt.Tensor:
    """Apply the analysis (forward) transform using the kernels.

    Parameters
    ----------
    x : pt.Tensor
        Input tensor of shape (B, in_ch, [D, H], W).

    Returns
    -------
    pt.Tensor
        Output tensor of shape (B, m, [D, H], W).
    """
    w = self.get_kernels()
    c = self._ndconvs_d[self.n_dims](x, w, padding=self.k // 2)
    if self.norm is not None:
        if self.norm.lower() == "ortho":
            c = c / math.sqrt(self.m) * math.sqrt(self.in_ch)
        elif self.norm.lower() == "forward":
            c = c / float(self.m) * float(self.in_ch)
    return c

get_kernels abstractmethod

get_kernels() -> Tensor

Return the kernels to be used for the convolutions.

Returns:

  • Tensor

    The kernels for the convolutions.

Source code in src/autoden/transforms/custom_filters.py
52
53
54
55
56
57
58
59
60
@abstractmethod
def get_kernels(self) -> pt.Tensor:
    """Return the kernels to be used for the convolutions.

    Returns
    -------
    pt.Tensor
        The kernels for the convolutions.
    """

synthesize

synthesize(c: Tensor) -> Tensor

Apply the synthesis (inverse) transform using the kernels.

Parameters:

  • c (Tensor) –

    Input tensor of shape (B, m, [D, H], W).

Returns:

  • Tensor

    Output tensor of shape (B, in_ch, [D, H], W).

Source code in src/autoden/transforms/custom_filters.py
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
def synthesize(self, c: pt.Tensor) -> pt.Tensor:
    """Apply the synthesis (inverse) transform using the kernels.

    Parameters
    ----------
    c : pt.Tensor
        Input tensor of shape (B, m, [D, H], W).

    Returns
    -------
    pt.Tensor
        Output tensor of shape (B, in_ch, [D, H], W).
    """
    w = self.get_kernels()
    x = self._ndconvs_t[self.n_dims](c, w, padding=self.k // 2)
    if self.norm is not None:
        if self.norm.lower() == "ortho":
            x = x / math.sqrt(self.m) * math.sqrt(self.in_ch)
        elif self.norm.lower() == "backward":
            x = x / float(self.m) * float(self.in_ch)
    return x

CustomFilterDecomposition

CustomFilterDecomposition(
    kernels: Tensor | NDArray,
    device: str = "cuda" if is_available() else "cpu",
    norm: (
        Literal["backward", "forward", "ortho"] | None
    ) = "backward",
)

Bases: ConvolutionalDecompositionBase

Decomposition using custom filters (kernels).

Parameters:

  • kernels (Tensor | NDArray) –

    The kernels to be used for the convolutions. Should have shape (m, in_ch, *((k,) * n_dims)).

  • device (str, default: 'cuda' if is_available() else 'cpu' ) –

    The device to use for the kernels. Defaults to "cuda" if available, otherwise "cpu".

  • norm (Literal['backward', 'forward', 'ortho'] | None, default: 'backward' ) –

    Normalization type. Defaults to "backward".

Methods:

  • analyze

    Apply the analysis (forward) transform using the kernels.

  • get_kernels

    Return the kernels to be used for the convolutions.

  • synthesize

    Apply the synthesis (inverse) transform using the kernels.

Source code in src/autoden/transforms/custom_filters.py
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
def __init__(
    self,
    kernels: pt.Tensor | NDArray,
    device: str = "cuda" if pt.cuda.is_available() else "cpu",
    norm: Literal["backward", "forward", "ortho"] | None = "backward",
) -> None:
    """Initialize the CustomFilterDecomposition.

    Parameters
    ----------
    kernels : pt.Tensor | NDArray
        The kernels to be used for the convolutions. Should have shape (m, in_ch, *((k,) * n_dims)).
    device : str, optional
        The device to use for the kernels. Defaults to "cuda" if available, otherwise "cpu".
    norm : Literal["backward", "forward", "ortho"] | None, optional
        Normalization type. Defaults to "backward".
    """
    m = kernels.shape[0]
    in_ch = kernels.shape[1]
    n_dims = kernels.ndim - 2
    if n_dims < 1:
        raise ValueError(f"Kernels should have shape (m, in_ch, *((k,) * n_dims)), but {kernels.shape} was passed")
    k = kernels.shape[-1]
    if any(s != k for s in kernels.shape[-n_dims:-1]):
        raise ValueError(
            f"Kernels should have the same size `k` in all directions, but {kernels.shape[-n_dims]} was passed."
            f" Complete shape: {kernels.shape}"
        )
    super().__init__(k=k, in_ch=in_ch, n_dims=n_dims, m=m, norm=norm)

    if not isinstance(kernels, pt.Tensor):
        kernels = pt.tensor(kernels)
    kernels = kernels.detach().to(device).clone()
    self.register_buffer("kernels", kernels)

    self.device = device

analyze

analyze(x: Tensor) -> Tensor

Apply the analysis (forward) transform using the kernels.

Parameters:

  • x (Tensor) –

    Input tensor of shape (B, in_ch, [D, H], W).

Returns:

  • Tensor

    Output tensor of shape (B, m, [D, H], W).

Source code in src/autoden/transforms/custom_filters.py
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
def analyze(self, x: pt.Tensor) -> pt.Tensor:
    """Apply the analysis (forward) transform using the kernels.

    Parameters
    ----------
    x : pt.Tensor
        Input tensor of shape (B, in_ch, [D, H], W).

    Returns
    -------
    pt.Tensor
        Output tensor of shape (B, m, [D, H], W).
    """
    w = self.get_kernels()
    c = self._ndconvs_d[self.n_dims](x, w, padding=self.k // 2)
    if self.norm is not None:
        if self.norm.lower() == "ortho":
            c = c / math.sqrt(self.m) * math.sqrt(self.in_ch)
        elif self.norm.lower() == "forward":
            c = c / float(self.m) * float(self.in_ch)
    return c

get_kernels

get_kernels() -> Tensor

Return the kernels to be used for the convolutions.

Returns:

  • Tensor

    The kernels for the convolutions.

Source code in src/autoden/transforms/custom_filters.py
149
150
151
152
153
154
155
156
157
def get_kernels(self) -> pt.Tensor:
    """Return the kernels to be used for the convolutions.

    Returns
    -------
    pt.Tensor
        The kernels for the convolutions.
    """
    return self.kernels

synthesize

synthesize(c: Tensor) -> Tensor

Apply the synthesis (inverse) transform using the kernels.

Parameters:

  • c (Tensor) –

    Input tensor of shape (B, m, [D, H], W).

Returns:

  • Tensor

    Output tensor of shape (B, in_ch, [D, H], W).

Source code in src/autoden/transforms/custom_filters.py
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
def synthesize(self, c: pt.Tensor) -> pt.Tensor:
    """Apply the synthesis (inverse) transform using the kernels.

    Parameters
    ----------
    c : pt.Tensor
        Input tensor of shape (B, m, [D, H], W).

    Returns
    -------
    pt.Tensor
        Output tensor of shape (B, in_ch, [D, H], W).
    """
    w = self.get_kernels()
    x = self._ndconvs_t[self.n_dims](c, w, padding=self.k // 2)
    if self.norm is not None:
        if self.norm.lower() == "ortho":
            x = x / math.sqrt(self.m) * math.sqrt(self.in_ch)
        elif self.norm.lower() == "backward":
            x = x / float(self.m) * float(self.in_ch)
    return x