netloader 3.11.0__py3-none-any.whl

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,209 @@
1
+ """
2
+ Custom network models.
3
+ """
4
+ import logging as log
5
+ from itertools import repeat
6
+ from typing import Any, overload
7
+
8
+ from torch import nn
9
+
10
+ from netloader.utils import Config
11
+ from netloader.utils.types import TensorListLike
12
+ from netloader.network import CompatibleNetwork, Network
13
+
14
+
15
+ class MultiNetwork(CompatibleNetwork):
16
+ """
17
+ Network class to hold multiple networks and train them together.
18
+
19
+ Attributes
20
+ ----------
21
+ name : str
22
+ Name of the network, used for saving
23
+ version : str
24
+ NetLoader version string
25
+ checkpoints : list[TensorListLike]
26
+ Outputs from each checkpoint with each Tensor having shape (N,...) and type float, where N
27
+ is the batch size
28
+ kl_loss : Tensor
29
+ KL divergence loss on the latent space of shape (1) and type float, if using a sample layer
30
+ layers : ModuleList
31
+ Network construction
32
+ """
33
+ @overload
34
+ def __init__(
35
+ self,
36
+ name: str,
37
+ *nets: nn.Module | nn.ModuleList | CompatibleNetwork | Network,
38
+ save_outputs: bool = ...) -> None: ...
39
+
40
+ @overload
41
+ def __init__(
42
+ self,
43
+ name: str,
44
+ *nets: str | nn.Module | nn.ModuleList | CompatibleNetwork | Network | Config,
45
+ save_outputs: bool = ...,
46
+ suppress_warning: bool = ...,
47
+ root: str = ...,
48
+ config: str = ...,
49
+ in_shape: list[int] | list[list[int]] | tuple[int, ...] | None = ...,
50
+ out_shapes: list[list[int]] | None = ...,
51
+ defaults: list[dict[str, Any]] | dict[str, Any] | None = ...) -> None: ...
52
+
53
+ def __init__(
54
+ self,
55
+ name: str,
56
+ *nets: str | nn.Module | nn.ModuleList | CompatibleNetwork | Network | Config,
57
+ save_outputs: bool = False,
58
+ suppress_warning: bool = False,
59
+ root: str = '',
60
+ config: str = '',
61
+ in_shape: list[int] | list[list[int]] | tuple[int, ...] | None = None,
62
+ out_shapes: list[list[int]] | None = None,
63
+ defaults: list[dict[str, Any]] | dict[str, Any] | None = None) -> None:
64
+ """
65
+ Parameters
66
+ ----------
67
+ name : str
68
+ Name of the network, used for saving
69
+ *networks : Network
70
+ Networks to combine sequentially
71
+ save_outputs : bool, Optional
72
+ If outputs from each network should be saved, default = False
73
+ suppress_warning : bool, Optional
74
+ If output shape mismatch warning should be suppressed, default = False
75
+ root : str, Optional
76
+ Root directory to prepend to config file path if any network is a string or Config
77
+ config : str, Optional
78
+ Path to the network config directory if any network is a string
79
+ in_shape : list[int] | list[list[int]] | tuple[int, ...], Optional
80
+ Input shape for the first network in the MultiNetwork if any network is a string or
81
+ Config
82
+ out_shapes : list[list[int]], Optional
83
+ Output shapes for each network in the MultiNetwork if any network is a string or Config
84
+ defaults : list[dict[str, Any]] | dict[str, Any] | None, Optional
85
+ Default values for the parameters for each type of layer for all or each network
86
+ """
87
+ self._cache: bool = save_outputs
88
+ calc_in_shape: bool = True
89
+ net: str | nn.Module | nn.ModuleList | CompatibleNetwork | Network | Config
90
+ builds: list[bool] = [isinstance(net, (str, Config)) for net in nets]
91
+ out_shape: list[int] | None
92
+ nets_: list[CompatibleNetwork | Network] = []
93
+ default: dict[str, Any] | None
94
+ defaults = repeat(None) if defaults is None else defaults if isinstance(defaults, list) \
95
+ else [defaults] * len(nets)
96
+
97
+ if out_shapes and len(out_shapes) != len(nets):
98
+ raise ValueError(f'Length of out_shape list ({len(out_shapes)}) must match number of '
99
+ f'networks ({len(nets)})')
100
+ if not isinstance(defaults, repeat) and len(defaults) != len(nets):
101
+ raise ValueError(f'Length of defaults list ({len(defaults)}) must match number of '
102
+ f'networks ({len(nets)})')
103
+ if any(builds) and (in_shape is None or out_shapes is None):
104
+ raise ValueError(f'If any network is a string or Config object, in_shape ({in_shape}) '
105
+ f'and out_shapes ({out_shapes}) must be provided')
106
+ if not out_shapes and not all(builds) and any(builds):
107
+ calc_in_shape = False
108
+ log.getLogger(__name__).warning(
109
+ 'If out_shape is not provided and any network is not a string or Config object, '
110
+ 'each string and Config object will be assumed to have the same in_shape')
111
+
112
+ for net, out_shape, default in zip(nets, out_shapes or repeat(None), defaults):
113
+ match net:
114
+ case str():
115
+ nets_.append(Network(
116
+ net,
117
+ config,
118
+ in_shape,
119
+ out_shape,
120
+ suppress_warning=suppress_warning,
121
+ root=root,
122
+ defaults=default,
123
+ ))
124
+ case Config():
125
+ nets_.append(Network(
126
+ '',
127
+ net,
128
+ in_shape,
129
+ out_shape,
130
+ suppress_warning=suppress_warning,
131
+ root=root,
132
+ defaults=default,
133
+ ))
134
+ case Network() | CompatibleNetwork():
135
+ nets_.append(net)
136
+ case nn.Module():
137
+ nets_.append(CompatibleNetwork(net))
138
+ case _:
139
+ raise TypeError(f'Unsupported network type ({type(net)})')
140
+
141
+ if calc_in_shape and isinstance(nets_[-1], Network):
142
+ in_shape = nets_[-1].shapes.get(-1, True)
143
+ elif calc_in_shape:
144
+ in_shape = out_shape
145
+
146
+ super().__init__(nn.ModuleList(nets_), name=name)
147
+
148
+ def __len__(self) -> int:
149
+ return len(self.layers)
150
+
151
+ @overload
152
+ def __getitem__(self, item: int) -> CompatibleNetwork | Network: ...
153
+
154
+ @overload
155
+ def __getitem__(self, item: slice) -> nn.ModuleList: ...
156
+
157
+ def __getitem__(self, item: int | slice) -> CompatibleNetwork | Network | nn.ModuleList:
158
+ return self.layers[item]
159
+
160
+ def __getstate__(self) -> dict[str, Any]:
161
+ return super().__getstate__() | {'save_outputs': self._cache}
162
+
163
+ def __setstate__(self, state: dict[str, Any]) -> None:
164
+ super().__setstate__(state)
165
+ self._cache = state.get('save_outputs', False)
166
+
167
+ def forward(self, x: TensorListLike) -> TensorListLike:
168
+ """
169
+ Forward pass through all networks in the MultiNetwork.
170
+
171
+ Parameters
172
+ ----------
173
+ x : TensorListLike
174
+ Input tensor(s) with shape (N,...) and type float, where N is the
175
+ batch size
176
+
177
+ Returns
178
+ -------
179
+ TensorListLike
180
+ Output tensor from the network with shape (N,...) and type float
181
+ """
182
+ net: CompatibleNetwork | Network
183
+ self.checkpoints = []
184
+
185
+ for i, net in enumerate(self.layers):
186
+ x = net(x)
187
+ self.checkpoints.extend(net.checkpoints)
188
+
189
+ if self._cache and i != len(self.layers) - 1:
190
+ self.checkpoints.append(x.clone())
191
+ return x
192
+
193
+ def get_config(self, dict_: bool = True) -> dict[str, Any] | Config:
194
+ """
195
+ Returns the network configuration.
196
+
197
+ Parameters
198
+ ----------
199
+ dict_ : bool, Optional
200
+ If configuration should be returned as a dictionary, default = True
201
+
202
+ Returns
203
+ -------
204
+ dict[str, Any] | Config
205
+ Network configuration
206
+ """
207
+ net: CompatibleNetwork | Network
208
+ config = Config(layers=[net.get_config() for net in self.layers])
209
+ return config.to_dict() if dict_ else config