congrads 0.2.0__py3-none-any.whl → 0.3.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.
- congrads/__init__.py +10 -21
- congrads/callbacks/base.py +357 -0
- congrads/callbacks/registry.py +106 -0
- congrads/checkpoints.py +178 -0
- congrads/constraints/base.py +242 -0
- congrads/constraints/registry.py +1255 -0
- congrads/core/batch_runner.py +200 -0
- congrads/core/congradscore.py +271 -0
- congrads/core/constraint_engine.py +209 -0
- congrads/core/epoch_runner.py +119 -0
- congrads/datasets/registry.py +799 -0
- congrads/descriptor.py +148 -29
- congrads/metrics.py +109 -19
- congrads/networks/registry.py +68 -0
- congrads/py.typed +0 -0
- congrads/transformations/base.py +37 -0
- congrads/transformations/registry.py +86 -0
- congrads/{utils.py → utils/preprocessors.py} +201 -72
- congrads/utils/utility.py +506 -0
- congrads/utils/validation.py +182 -0
- congrads-0.3.0.dist-info/METADATA +234 -0
- congrads-0.3.0.dist-info/RECORD +23 -0
- congrads-0.3.0.dist-info/WHEEL +4 -0
- congrads/constraints.py +0 -389
- congrads/core.py +0 -225
- congrads/datasets.py +0 -195
- congrads/networks.py +0 -90
- congrads-0.2.0.dist-info/LICENSE +0 -26
- congrads-0.2.0.dist-info/METADATA +0 -222
- congrads-0.2.0.dist-info/RECORD +0 -13
- congrads-0.2.0.dist-info/WHEEL +0 -5
- congrads-0.2.0.dist-info/top_level.txt +0 -1
congrads/core.py
DELETED
|
@@ -1,225 +0,0 @@
|
|
|
1
|
-
import logging
|
|
2
|
-
from torch import Tensor, float32, no_grad, norm, tensor
|
|
3
|
-
from torch.optim import Optimizer
|
|
4
|
-
from torch.nn import Module
|
|
5
|
-
from torch.utils.data import DataLoader
|
|
6
|
-
from time import time
|
|
7
|
-
|
|
8
|
-
from .metrics import MetricManager
|
|
9
|
-
from .constraints import Constraint
|
|
10
|
-
from .descriptor import Descriptor
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class CongradsCore:
|
|
14
|
-
|
|
15
|
-
def __init__(
|
|
16
|
-
self,
|
|
17
|
-
descriptor: Descriptor,
|
|
18
|
-
constraints: list[Constraint],
|
|
19
|
-
loaders: tuple[DataLoader, DataLoader, DataLoader],
|
|
20
|
-
network: Module,
|
|
21
|
-
criterion: callable,
|
|
22
|
-
optimizer: Optimizer,
|
|
23
|
-
metric_manager: MetricManager,
|
|
24
|
-
device,
|
|
25
|
-
):
|
|
26
|
-
|
|
27
|
-
# Init parent class
|
|
28
|
-
super().__init__()
|
|
29
|
-
|
|
30
|
-
# Init object variables
|
|
31
|
-
self.descriptor = descriptor
|
|
32
|
-
self.constraints = constraints
|
|
33
|
-
self.train_loader = loaders[0]
|
|
34
|
-
self.valid_loader = loaders[1]
|
|
35
|
-
self.test_loader = loaders[2]
|
|
36
|
-
self.network = network
|
|
37
|
-
self.criterion = criterion
|
|
38
|
-
self.optimizer = optimizer
|
|
39
|
-
self.metric_manager = metric_manager
|
|
40
|
-
self.device = device
|
|
41
|
-
|
|
42
|
-
# Perform checks
|
|
43
|
-
if len(self.descriptor.variable_layers) == 0:
|
|
44
|
-
logging.warning(
|
|
45
|
-
"The descriptor object has no variable layers. The constraint guided loss adjustment is therefore not used. Is this the intended behaviour?"
|
|
46
|
-
)
|
|
47
|
-
|
|
48
|
-
# Initialize constraint metrics
|
|
49
|
-
metric_manager.register("Loss/train")
|
|
50
|
-
metric_manager.register("Loss/valid")
|
|
51
|
-
metric_manager.register("CSR/train")
|
|
52
|
-
metric_manager.register("CSR/valid")
|
|
53
|
-
|
|
54
|
-
for constraint in self.constraints:
|
|
55
|
-
metric_manager.register(f"{constraint.name}/train")
|
|
56
|
-
metric_manager.register(f"{constraint.name}/valid")
|
|
57
|
-
|
|
58
|
-
def fit(self, max_epochs: int = 100):
|
|
59
|
-
# Loop over epochs
|
|
60
|
-
for epoch in range(max_epochs):
|
|
61
|
-
|
|
62
|
-
# Log start time
|
|
63
|
-
start_time = time()
|
|
64
|
-
|
|
65
|
-
# Training
|
|
66
|
-
for batch in self.train_loader:
|
|
67
|
-
|
|
68
|
-
# Set model in training mode
|
|
69
|
-
self.network.train()
|
|
70
|
-
|
|
71
|
-
# Get input-output pairs from batch
|
|
72
|
-
inputs, outputs = batch
|
|
73
|
-
|
|
74
|
-
# Transfer to GPU
|
|
75
|
-
inputs, outputs = inputs.to(self.device), outputs.to(self.device)
|
|
76
|
-
|
|
77
|
-
# Log preparation time
|
|
78
|
-
prepare_time = start_time - time()
|
|
79
|
-
|
|
80
|
-
# Model computations
|
|
81
|
-
prediction = self.network(inputs)
|
|
82
|
-
|
|
83
|
-
# Calculate loss
|
|
84
|
-
loss = self.criterion(prediction["output"], outputs)
|
|
85
|
-
self.metric_manager.accumulate("Loss/train", loss.unsqueeze(0))
|
|
86
|
-
|
|
87
|
-
# Adjust loss based on constraints
|
|
88
|
-
combined_loss = self.train_step(prediction, loss)
|
|
89
|
-
|
|
90
|
-
# Backpropx
|
|
91
|
-
self.optimizer.zero_grad()
|
|
92
|
-
combined_loss.backward(
|
|
93
|
-
retain_graph=False, inputs=list(self.network.parameters())
|
|
94
|
-
)
|
|
95
|
-
self.optimizer.step()
|
|
96
|
-
|
|
97
|
-
# Validation
|
|
98
|
-
with no_grad():
|
|
99
|
-
for batch in self.valid_loader:
|
|
100
|
-
|
|
101
|
-
# Set model in evaluation mode
|
|
102
|
-
self.network.eval()
|
|
103
|
-
|
|
104
|
-
# Get input-output pairs from batch
|
|
105
|
-
inputs, outputs = batch
|
|
106
|
-
|
|
107
|
-
# Transfer to GPU
|
|
108
|
-
inputs, outputs = inputs.to(self.device), outputs.to(self.device)
|
|
109
|
-
|
|
110
|
-
# Model computations
|
|
111
|
-
prediction = self.network(inputs)
|
|
112
|
-
|
|
113
|
-
# Calculate loss
|
|
114
|
-
loss = self.criterion(prediction["output"], outputs)
|
|
115
|
-
self.metric_manager.accumulate("Loss/valid", loss.unsqueeze(0))
|
|
116
|
-
|
|
117
|
-
# Validate constraints
|
|
118
|
-
self.valid_step(prediction, loss)
|
|
119
|
-
|
|
120
|
-
# TODO with valid loader, checkpoint model with best performance
|
|
121
|
-
|
|
122
|
-
# Save metrics
|
|
123
|
-
self.metric_manager.record(epoch)
|
|
124
|
-
self.metric_manager.reset()
|
|
125
|
-
|
|
126
|
-
# Log compute and preparation time
|
|
127
|
-
process_time = start_time - time() - prepare_time
|
|
128
|
-
print(
|
|
129
|
-
"Compute efficiency: {:.2f}, epoch: {}/{}:".format(
|
|
130
|
-
process_time / (process_time + prepare_time), epoch, max_epochs
|
|
131
|
-
)
|
|
132
|
-
)
|
|
133
|
-
start_time = time()
|
|
134
|
-
|
|
135
|
-
def train_step(
|
|
136
|
-
self,
|
|
137
|
-
prediction: dict[str, Tensor],
|
|
138
|
-
loss: Tensor,
|
|
139
|
-
):
|
|
140
|
-
|
|
141
|
-
# Init scalar tensor for loss
|
|
142
|
-
total_rescale_loss = tensor(0, dtype=float32, device=self.device)
|
|
143
|
-
loss_grads = {}
|
|
144
|
-
|
|
145
|
-
# Precalculate loss gradients for each variable layer
|
|
146
|
-
with no_grad():
|
|
147
|
-
for layer in self.descriptor.variable_layers:
|
|
148
|
-
self.optimizer.zero_grad()
|
|
149
|
-
loss.backward(retain_graph=True, inputs=prediction[layer])
|
|
150
|
-
loss_grads[layer] = prediction[layer].grad
|
|
151
|
-
|
|
152
|
-
# For each constraint, TODO split into real and validation only constraints
|
|
153
|
-
for constraint in self.constraints:
|
|
154
|
-
|
|
155
|
-
# Check if constraints are satisfied and calculate directions
|
|
156
|
-
with no_grad():
|
|
157
|
-
constraint_checks = constraint.check_constraint(prediction)
|
|
158
|
-
constraint_directions = constraint.calculate_direction(prediction)
|
|
159
|
-
|
|
160
|
-
# Only do direction calculations for variable layers affecting constraint
|
|
161
|
-
for layer in constraint.layers & self.descriptor.variable_layers:
|
|
162
|
-
|
|
163
|
-
with no_grad():
|
|
164
|
-
# Multiply direction modifiers with constraint result
|
|
165
|
-
constraint_result = (
|
|
166
|
-
constraint_checks.unsqueeze(1).type(float32)
|
|
167
|
-
* constraint_directions[layer]
|
|
168
|
-
)
|
|
169
|
-
|
|
170
|
-
# Multiply result with rescale factor of constraint
|
|
171
|
-
constraint_result *= constraint.rescale_factor
|
|
172
|
-
|
|
173
|
-
# Calculate loss gradient norm
|
|
174
|
-
norm_loss_grad = norm(loss_grads[layer], dim=1, p=2, keepdim=True)
|
|
175
|
-
|
|
176
|
-
# Calculate rescale loss
|
|
177
|
-
rescale_loss = (
|
|
178
|
-
prediction[layer]
|
|
179
|
-
* constraint_result
|
|
180
|
-
* norm_loss_grad.detach().clone()
|
|
181
|
-
).mean()
|
|
182
|
-
|
|
183
|
-
# Store rescale loss for this reference space
|
|
184
|
-
total_rescale_loss += rescale_loss
|
|
185
|
-
|
|
186
|
-
# Log constraint satisfaction ratio
|
|
187
|
-
self.metric_manager.accumulate(
|
|
188
|
-
f"{constraint.name}/train",
|
|
189
|
-
(~constraint_checks).type(float32),
|
|
190
|
-
)
|
|
191
|
-
self.metric_manager.accumulate(
|
|
192
|
-
"CSR/train",
|
|
193
|
-
(~constraint_checks).type(float32),
|
|
194
|
-
)
|
|
195
|
-
|
|
196
|
-
# Return combined loss
|
|
197
|
-
return loss + total_rescale_loss
|
|
198
|
-
|
|
199
|
-
def valid_step(
|
|
200
|
-
self,
|
|
201
|
-
prediction: dict[str, Tensor],
|
|
202
|
-
loss: Tensor,
|
|
203
|
-
):
|
|
204
|
-
|
|
205
|
-
# Compute rescale loss without tracking gradients
|
|
206
|
-
with no_grad():
|
|
207
|
-
|
|
208
|
-
# For each constraint in this reference space, calculate directions
|
|
209
|
-
for constraint in self.constraints:
|
|
210
|
-
|
|
211
|
-
# Check if constraints are satisfied for
|
|
212
|
-
constraint_checks = constraint.check_constraint(prediction)
|
|
213
|
-
|
|
214
|
-
# Log constraint satisfaction ratio
|
|
215
|
-
self.metric_manager.accumulate(
|
|
216
|
-
f"{constraint.name}/valid",
|
|
217
|
-
(~constraint_checks).type(float32),
|
|
218
|
-
)
|
|
219
|
-
self.metric_manager.accumulate(
|
|
220
|
-
"CSR/valid",
|
|
221
|
-
(~constraint_checks).type(float32),
|
|
222
|
-
)
|
|
223
|
-
|
|
224
|
-
# Return loss
|
|
225
|
-
return loss
|
congrads/datasets.py
DELETED
|
@@ -1,195 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
from urllib.error import URLError
|
|
3
|
-
import numpy as np
|
|
4
|
-
from pathlib import Path
|
|
5
|
-
from typing import Callable, Union
|
|
6
|
-
import pandas as pd
|
|
7
|
-
from torch.utils.data import Dataset
|
|
8
|
-
import torch
|
|
9
|
-
|
|
10
|
-
from torchvision.datasets.utils import check_integrity, download_and_extract_archive
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class BiasCorrection(Dataset):
|
|
14
|
-
|
|
15
|
-
mirrors = [
|
|
16
|
-
"https://archive.ics.uci.edu/static/public/514/",
|
|
17
|
-
]
|
|
18
|
-
|
|
19
|
-
resources = [
|
|
20
|
-
(
|
|
21
|
-
"bias+correction+of+numerical+prediction+model+temperature+forecast.zip",
|
|
22
|
-
"3deee56d461a2686887c4ae38fe3ccf3",
|
|
23
|
-
),
|
|
24
|
-
]
|
|
25
|
-
|
|
26
|
-
def __init__(
|
|
27
|
-
self,
|
|
28
|
-
root: Union[str, Path],
|
|
29
|
-
transform: Callable,
|
|
30
|
-
download: bool = False,
|
|
31
|
-
) -> None:
|
|
32
|
-
|
|
33
|
-
super().__init__()
|
|
34
|
-
self.root = root
|
|
35
|
-
self.transform = transform
|
|
36
|
-
|
|
37
|
-
if download:
|
|
38
|
-
self.download()
|
|
39
|
-
|
|
40
|
-
if not self._check_exists():
|
|
41
|
-
raise RuntimeError(
|
|
42
|
-
"Dataset not found. You can use download=True to download it"
|
|
43
|
-
)
|
|
44
|
-
|
|
45
|
-
self.data_input, self.data_output = self._load_data()
|
|
46
|
-
|
|
47
|
-
def _load_data(self):
|
|
48
|
-
|
|
49
|
-
data: pd.DataFrame = pd.read_csv(
|
|
50
|
-
os.path.join(self.data_folder, "Bias_correction_ucl.csv")
|
|
51
|
-
).pipe(self.transform)
|
|
52
|
-
|
|
53
|
-
data_input = data["Input"].to_numpy(dtype=np.float32)
|
|
54
|
-
data_output = data["Output"].to_numpy(dtype=np.float32)
|
|
55
|
-
|
|
56
|
-
return data_input, data_output
|
|
57
|
-
|
|
58
|
-
def __len__(self):
|
|
59
|
-
|
|
60
|
-
return self.data_input.shape[0]
|
|
61
|
-
|
|
62
|
-
def __getitem__(self, idx):
|
|
63
|
-
|
|
64
|
-
example = self.data_input[idx, :]
|
|
65
|
-
target = self.data_output[idx, :]
|
|
66
|
-
example = torch.tensor(example)
|
|
67
|
-
target = torch.tensor(target)
|
|
68
|
-
return example, target
|
|
69
|
-
|
|
70
|
-
@property
|
|
71
|
-
def data_folder(self) -> str:
|
|
72
|
-
|
|
73
|
-
return os.path.join(self.root, self.__class__.__name__)
|
|
74
|
-
|
|
75
|
-
def _check_exists(self) -> bool:
|
|
76
|
-
return all(
|
|
77
|
-
check_integrity(os.path.join(self.data_folder, file_path), checksum)
|
|
78
|
-
for file_path, checksum in self.resources
|
|
79
|
-
)
|
|
80
|
-
|
|
81
|
-
def download(self) -> None:
|
|
82
|
-
if self._check_exists():
|
|
83
|
-
return
|
|
84
|
-
|
|
85
|
-
os.makedirs(self.data_folder, exist_ok=True)
|
|
86
|
-
|
|
87
|
-
# download files
|
|
88
|
-
for filename, md5 in self.resources:
|
|
89
|
-
errors = []
|
|
90
|
-
for mirror in self.mirrors:
|
|
91
|
-
url = f"{mirror}{filename}"
|
|
92
|
-
try:
|
|
93
|
-
download_and_extract_archive(
|
|
94
|
-
url, download_root=self.data_folder, filename=filename, md5=md5
|
|
95
|
-
)
|
|
96
|
-
except URLError as e:
|
|
97
|
-
errors.append(e)
|
|
98
|
-
continue
|
|
99
|
-
break
|
|
100
|
-
else:
|
|
101
|
-
s = f"Error downloading {filename}:\n"
|
|
102
|
-
for mirror, err in zip(self.mirrors, errors):
|
|
103
|
-
s += f"Tried {mirror}, got:\n{str(err)}\n"
|
|
104
|
-
raise RuntimeError(s)
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
class FiniteIncome(Dataset):
|
|
108
|
-
|
|
109
|
-
mirrors = [
|
|
110
|
-
"https://www.kaggle.com/api/v1/datasets/download/grosvenpaul/",
|
|
111
|
-
]
|
|
112
|
-
|
|
113
|
-
resources = [
|
|
114
|
-
(
|
|
115
|
-
"family-income-and-expenditure",
|
|
116
|
-
"7d74bc7facc3d7c07c4df1c1c6ac563e",
|
|
117
|
-
),
|
|
118
|
-
]
|
|
119
|
-
|
|
120
|
-
def __init__(
|
|
121
|
-
self,
|
|
122
|
-
root: Union[str, Path],
|
|
123
|
-
transform: Callable,
|
|
124
|
-
download: bool = False,
|
|
125
|
-
) -> None:
|
|
126
|
-
super().__init__()
|
|
127
|
-
self.root = root
|
|
128
|
-
self.transform = transform
|
|
129
|
-
|
|
130
|
-
if download:
|
|
131
|
-
self.download()
|
|
132
|
-
|
|
133
|
-
if not self._check_exists():
|
|
134
|
-
raise RuntimeError(
|
|
135
|
-
"Dataset not found. You can use download=True to download it."
|
|
136
|
-
)
|
|
137
|
-
|
|
138
|
-
self.data_input, self.data_output = self._load_data()
|
|
139
|
-
|
|
140
|
-
def _load_data(self):
|
|
141
|
-
|
|
142
|
-
data: pd.DataFrame = pd.read_csv(
|
|
143
|
-
os.path.join(self.data_folder, "Family Income and Expenditure.csv")
|
|
144
|
-
).pipe(self.transform)
|
|
145
|
-
|
|
146
|
-
data_input = data["Input"].to_numpy(dtype=np.float32)
|
|
147
|
-
data_output = data["Output"].to_numpy(dtype=np.float32)
|
|
148
|
-
|
|
149
|
-
return data_input, data_output
|
|
150
|
-
|
|
151
|
-
def __len__(self):
|
|
152
|
-
return self.data_input.shape[0]
|
|
153
|
-
|
|
154
|
-
def __getitem__(self, idx):
|
|
155
|
-
example = self.data_input[idx, :]
|
|
156
|
-
target = self.data_output[idx, :]
|
|
157
|
-
example = torch.tensor(example)
|
|
158
|
-
target = torch.tensor(target)
|
|
159
|
-
return example, target
|
|
160
|
-
|
|
161
|
-
@property
|
|
162
|
-
def data_folder(self) -> str:
|
|
163
|
-
return os.path.join(self.root, self.__class__.__name__)
|
|
164
|
-
|
|
165
|
-
def _check_exists(self) -> bool:
|
|
166
|
-
return all(
|
|
167
|
-
check_integrity(os.path.join(self.data_folder, file_path), checksum)
|
|
168
|
-
for file_path, checksum in self.resources
|
|
169
|
-
)
|
|
170
|
-
|
|
171
|
-
def download(self) -> None:
|
|
172
|
-
|
|
173
|
-
if self._check_exists():
|
|
174
|
-
return
|
|
175
|
-
|
|
176
|
-
os.makedirs(self.data_folder, exist_ok=True)
|
|
177
|
-
|
|
178
|
-
# download files
|
|
179
|
-
for filename, md5 in self.resources:
|
|
180
|
-
errors = []
|
|
181
|
-
for mirror in self.mirrors:
|
|
182
|
-
url = f"{mirror}{filename}"
|
|
183
|
-
try:
|
|
184
|
-
download_and_extract_archive(
|
|
185
|
-
url, download_root=self.data_folder, filename=filename, md5=md5
|
|
186
|
-
)
|
|
187
|
-
except URLError as e:
|
|
188
|
-
errors.append(e)
|
|
189
|
-
continue
|
|
190
|
-
break
|
|
191
|
-
else:
|
|
192
|
-
s = f"Error downloading {filename}:\n"
|
|
193
|
-
for mirror, err in zip(self.mirrors, errors):
|
|
194
|
-
s += f"Tried {mirror}, got:\n{str(err)}\n"
|
|
195
|
-
raise RuntimeError(s)
|
congrads/networks.py
DELETED
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
from torch.nn import Linear, Sequential, ReLU, Module
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class MLPNetwork(Module):
|
|
5
|
-
"""
|
|
6
|
-
A multi-layer perceptron (MLP) neural network model consisting of
|
|
7
|
-
an input layer, multiple hidden layers, and an output layer.
|
|
8
|
-
|
|
9
|
-
This class constructs an MLP with configurable hyperparameters such as the
|
|
10
|
-
number of input features, output features, number of hidden layers, and
|
|
11
|
-
the dimensionality of hidden layers. It provides methods for both
|
|
12
|
-
building the model and performing a forward pass through the network.
|
|
13
|
-
|
|
14
|
-
Attributes:
|
|
15
|
-
n_inputs (int): The number of input features.
|
|
16
|
-
n_outputs (int): The number of output features.
|
|
17
|
-
n_hidden_layers (int): The number of hidden layers in the network.
|
|
18
|
-
hidden_dim (int): The dimensionality of the hidden layers.
|
|
19
|
-
input (nn.Module): The input layer (linear transformation followed by ReLU).
|
|
20
|
-
hidden (nn.Module): The sequential hidden layers (each consisting of
|
|
21
|
-
a linear transformation followed by ReLU).
|
|
22
|
-
out (nn.Module): The output layer (linear transformation).
|
|
23
|
-
"""
|
|
24
|
-
|
|
25
|
-
def __init__(
|
|
26
|
-
self,
|
|
27
|
-
n_inputs,
|
|
28
|
-
n_outputs,
|
|
29
|
-
n_hidden_layers=3,
|
|
30
|
-
hidden_dim=35,
|
|
31
|
-
):
|
|
32
|
-
"""
|
|
33
|
-
Initializes the MLP network with the given hyperparameters.
|
|
34
|
-
|
|
35
|
-
Args:
|
|
36
|
-
n_inputs (int, optional): The number of input features. Defaults to 25.
|
|
37
|
-
n_outputs (int, optional): The number of output features. Defaults to 2.
|
|
38
|
-
n_hidden_layers (int, optional): The number of hidden layers. Defaults to 2.
|
|
39
|
-
hidden_dim (int, optional): The dimensionality of the hidden layers. Defaults to 35.
|
|
40
|
-
"""
|
|
41
|
-
super().__init__()
|
|
42
|
-
|
|
43
|
-
# Init object variables
|
|
44
|
-
self.n_inputs = n_inputs
|
|
45
|
-
self.n_outputs = n_outputs
|
|
46
|
-
self.n_hidden_layers = n_hidden_layers
|
|
47
|
-
self.hidden_dim = hidden_dim
|
|
48
|
-
|
|
49
|
-
# Set up the components of our model
|
|
50
|
-
self.input = Linear(self.n_inputs, self.hidden_dim)
|
|
51
|
-
self.hidden = Sequential(
|
|
52
|
-
*(
|
|
53
|
-
self.linear(self.hidden_dim, self.hidden_dim)
|
|
54
|
-
for _ in range(n_hidden_layers)
|
|
55
|
-
)
|
|
56
|
-
)
|
|
57
|
-
self.out = Linear(self.hidden_dim, self.n_outputs)
|
|
58
|
-
|
|
59
|
-
def forward(self, X):
|
|
60
|
-
"""
|
|
61
|
-
Performs a forward pass through the network.
|
|
62
|
-
|
|
63
|
-
Args:
|
|
64
|
-
X (Tensor): The input tensor to be passed through the network.
|
|
65
|
-
|
|
66
|
-
Returns:
|
|
67
|
-
dict: A dictionary containing the 'input' (original input) and
|
|
68
|
-
'output' (predicted output) of the network.
|
|
69
|
-
"""
|
|
70
|
-
output = self.out(self.hidden(self.input(X)))
|
|
71
|
-
|
|
72
|
-
return {"input": X, "output": output}
|
|
73
|
-
|
|
74
|
-
@staticmethod
|
|
75
|
-
def linear(in_features, out_features):
|
|
76
|
-
"""
|
|
77
|
-
Creates a basic linear block with a linear transformation followed
|
|
78
|
-
by a ReLU activation function.
|
|
79
|
-
|
|
80
|
-
Args:
|
|
81
|
-
in_features (int): The number of input features.
|
|
82
|
-
out_features (int): The number of output features.
|
|
83
|
-
|
|
84
|
-
Returns:
|
|
85
|
-
nn.Module: A sequential module consisting of a Linear layer and ReLU activation.
|
|
86
|
-
"""
|
|
87
|
-
return Sequential(
|
|
88
|
-
Linear(in_features, out_features),
|
|
89
|
-
ReLU(),
|
|
90
|
-
)
|
congrads-0.2.0.dist-info/LICENSE
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
Copyright 2024 DTAI - KU Leuven
|
|
2
|
-
|
|
3
|
-
Redistribution and use in source and binary forms, with or without modification,
|
|
4
|
-
are permitted provided that the following conditions are met:
|
|
5
|
-
|
|
6
|
-
1. Redistributions of source code must retain the above copyright notice,
|
|
7
|
-
this list of conditions and the following disclaimer.
|
|
8
|
-
|
|
9
|
-
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
10
|
-
this list of conditions and the following disclaimer in the documentation
|
|
11
|
-
and/or other materials provided with the distribution.
|
|
12
|
-
|
|
13
|
-
3. Neither the name of the copyright holder nor the names of its
|
|
14
|
-
contributors may be used to endorse or promote products derived from
|
|
15
|
-
this software without specific prior written permission.
|
|
16
|
-
|
|
17
|
-
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS “AS IS”
|
|
18
|
-
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
19
|
-
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
20
|
-
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
|
21
|
-
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
22
|
-
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
23
|
-
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
24
|
-
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
25
|
-
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
26
|
-
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|