AbstractIntegratedModule 1.2.5__tar.gz → 1.2.6__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.
- {abstractintegratedmodule-1.2.5 → abstractintegratedmodule-1.2.6}/AbstractIntegratedModule.egg-info/PKG-INFO +1 -1
- {abstractintegratedmodule-1.2.5 → abstractintegratedmodule-1.2.6}/AbstractIntegratedModule.py +102 -21
- {abstractintegratedmodule-1.2.5 → abstractintegratedmodule-1.2.6}/AbstractOptimizedModules.c +200 -200
- {abstractintegratedmodule-1.2.5 → abstractintegratedmodule-1.2.6}/PKG-INFO +1 -1
- {abstractintegratedmodule-1.2.5 → abstractintegratedmodule-1.2.6}/README.md +107 -40
- {abstractintegratedmodule-1.2.5 → abstractintegratedmodule-1.2.6}/pyproject.toml +1 -1
- {abstractintegratedmodule-1.2.5 → abstractintegratedmodule-1.2.6}/setup.py +1 -1
- {abstractintegratedmodule-1.2.5 → abstractintegratedmodule-1.2.6}/AbstractIntegratedModule.egg-info/SOURCES.txt +0 -0
- {abstractintegratedmodule-1.2.5 → abstractintegratedmodule-1.2.6}/AbstractIntegratedModule.egg-info/dependency_links.txt +0 -0
- {abstractintegratedmodule-1.2.5 → abstractintegratedmodule-1.2.6}/AbstractIntegratedModule.egg-info/requires.txt +0 -0
- {abstractintegratedmodule-1.2.5 → abstractintegratedmodule-1.2.6}/AbstractIntegratedModule.egg-info/top_level.txt +0 -0
- {abstractintegratedmodule-1.2.5 → abstractintegratedmodule-1.2.6}/AbstractOptimizedModules.pyx +0 -0
- {abstractintegratedmodule-1.2.5 → abstractintegratedmodule-1.2.6}/MANIFEST.in +0 -0
- {abstractintegratedmodule-1.2.5 → abstractintegratedmodule-1.2.6}/abstract_model_storage/Cargo.toml +0 -0
- {abstractintegratedmodule-1.2.5 → abstractintegratedmodule-1.2.6}/abstract_model_storage/pyproject.toml +0 -0
- {abstractintegratedmodule-1.2.5 → abstractintegratedmodule-1.2.6}/abstract_model_storage/src/lib.rs +0 -0
- {abstractintegratedmodule-1.2.5 → abstractintegratedmodule-1.2.6}/abstract_model_storage/target/debug/build/libsqlite3-sys-ed07b882cd2aa5e2/out/bindgen.rs +0 -0
- {abstractintegratedmodule-1.2.5 → abstractintegratedmodule-1.2.6}/abstract_model_storage/target/debug/build/serde_core-ebc15f2e9cad7f5f/out/private.rs +0 -0
- {abstractintegratedmodule-1.2.5 → abstractintegratedmodule-1.2.6}/abstract_model_storage/target/debug/build/target-lexicon-08527f45de28143d/out/host.rs +0 -0
- {abstractintegratedmodule-1.2.5 → abstractintegratedmodule-1.2.6}/abstract_model_storage/target/release/build/libsqlite3-sys-bf0400df4523274c/out/bindgen.rs +0 -0
- {abstractintegratedmodule-1.2.5 → abstractintegratedmodule-1.2.6}/abstract_model_storage/target/release/build/serde_core-5cdb76131825e4af/out/private.rs +0 -0
- {abstractintegratedmodule-1.2.5 → abstractintegratedmodule-1.2.6}/abstract_model_storage/target/release/build/target-lexicon-43eb95a0588bf457/out/host.rs +0 -0
- {abstractintegratedmodule-1.2.5 → abstractintegratedmodule-1.2.6}/setup.cfg +0 -0
{abstractintegratedmodule-1.2.5 → abstractintegratedmodule-1.2.6}/AbstractIntegratedModule.py
RENAMED
|
@@ -1825,9 +1825,11 @@ class SNNNetwork:
|
|
|
1825
1825
|
optimizer.step(self.layers)
|
|
1826
1826
|
return loss, logits
|
|
1827
1827
|
|
|
1828
|
-
def predict(self, input_spikes):
|
|
1828
|
+
def predict(self, input_spikes, task='classification'):
|
|
1829
1829
|
self.eval()
|
|
1830
1830
|
logits = self.forward(input_spikes)
|
|
1831
|
+
if task == 'regression':
|
|
1832
|
+
return logits[:, 0], logits
|
|
1831
1833
|
return np.argmax(logits, axis=1), logits
|
|
1832
1834
|
|
|
1833
1835
|
def firing_rates(self):
|
|
@@ -20651,9 +20653,9 @@ class SNNUtility:
|
|
|
20651
20653
|
# SNN Network Build
|
|
20652
20654
|
#-----------------
|
|
20653
20655
|
def build_snn_network(n_in, n_hidden, n_classes, rng, decay=0.95,
|
|
20654
|
-
threshold=0.1, input_noise_std=0.0, reduction='mean'):
|
|
20656
|
+
threshold=0.1, input_noise_std=0.0, reduction='mean', p=0.2):
|
|
20655
20657
|
layer1 = LIFDenseLayer(n_in, n_hidden, decay=decay, threshold=threshold, rng=rng)
|
|
20656
|
-
drop1 = SpikeDropout(p=
|
|
20658
|
+
drop1 = SpikeDropout(p=p, rng=rng)
|
|
20657
20659
|
readout = ReadoutLayer(n_hidden, n_classes, decay=decay, rng=rng)
|
|
20658
20660
|
net = SNNNetwork([layer1, drop1, readout], readout_reduction=reduction,
|
|
20659
20661
|
input_noise_std=input_noise_std, rng=rng)
|
|
@@ -21117,23 +21119,69 @@ def print_confidence_report(results, top_k=3, max_print_threshold=50):
|
|
|
21117
21119
|
f"|| Top-{top_k}: [{top_str}]")
|
|
21118
21120
|
return pred_cache
|
|
21119
21121
|
|
|
21122
|
+
def initialize_snn_network(X=None, y=None, label_map=None, n_hidden=64, n_in=None, n_classes=None, seed=0, random_state=42):
|
|
21123
|
+
try:
|
|
21124
|
+
utility = SNNUtility()
|
|
21125
|
+
rng = utility.seed_everything(seed)
|
|
21126
|
+
if n_in is not None and n_classes is not None:
|
|
21127
|
+
net, hidden_layer = build_snn_network(n_in, n_hidden, n_classes, rng)
|
|
21128
|
+
else:
|
|
21129
|
+
X_train, X_test, y_train, y_test, X_val, y_val = _prepare_train_val_split(X=X, y=y, random_state=random_state)
|
|
21130
|
+
n_in = X_train.shape[1]
|
|
21131
|
+
n_classes = max(len(label_map), int(y_train.max() + 1))
|
|
21132
|
+
net, hidden_layer = build_snn_network(n_in, n_hidden, n_classes, rng)
|
|
21120
21133
|
|
|
21134
|
+
print(f'[>] Initialized SNN Network with hidden dim: {n_hidden}')
|
|
21135
|
+
return net, hidden_layer, utility
|
|
21136
|
+
except Exception as e:
|
|
21137
|
+
print(f'[>] Error initializing SNN Network and hidden layer: {e}')
|
|
21138
|
+
return None, None, None
|
|
21121
21139
|
|
|
21122
|
-
def train_snn_network(X=None, y=None, net=None, hidden_layer=None, label_map=None,
|
|
21140
|
+
def train_snn_network(X=None, y=None, net=None, hidden_layer=None, utility=None, task='classification', label_map=None,
|
|
21123
21141
|
epochs=50, batch_size=32, n_steps=20,
|
|
21124
21142
|
n_hidden=64, lr=2e-3, seed=0, pretrain_steps=200, unsupervised_stdp=False,
|
|
21125
|
-
random_state=42):
|
|
21143
|
+
random_state=42, ):
|
|
21126
21144
|
tracker = DiagnosticsTracker()
|
|
21127
|
-
utility = SNNUtility()
|
|
21128
21145
|
cache = {}
|
|
21146
|
+
reg = (task == 'regression')
|
|
21147
|
+
if utility is None:
|
|
21148
|
+
utility = SNNUtility()
|
|
21129
21149
|
|
|
21130
21150
|
rng = utility.seed_everything(seed)
|
|
21131
|
-
|
|
21151
|
+
if reg:
|
|
21152
|
+
X = np.asarray(X, dtype=np.float64)
|
|
21153
|
+
y = np.asarray(y, dtype=np.float64)
|
|
21154
|
+
if X.ndim > 2:
|
|
21155
|
+
X = X.reshape(len(X), -1) # (N, W, F) -> (N, W*F)
|
|
21156
|
+
if y.ndim == 1:
|
|
21157
|
+
y = y.reshape(-1, 1)
|
|
21158
|
+
if len(X) != len(y):
|
|
21159
|
+
raise ValueError(f'X has {len(X)} samples but y has {len(y)}')
|
|
21160
|
+
n = len(X)
|
|
21161
|
+
a, b = int(0.70 * n), int(0.85 * n) # chronological: never shuffle a time series
|
|
21162
|
+
X_train, X_val, X_test = X[:a], X[a:b], X[b:]
|
|
21163
|
+
y_train, y_val, y_test = y[:a], y[a:b], y[b:]
|
|
21164
|
+
lo, hi = X_train.min(0), X_train.max(0) # [0,1] scaling for spike encoding (train stats)
|
|
21165
|
+
span = np.where(hi - lo < 1e-9, 1.0, hi - lo)
|
|
21166
|
+
scale_x = lambda A: np.clip((A - lo) / span, 0.0, 1.0)
|
|
21167
|
+
X_train, X_val, X_test = scale_x(X_train), scale_x(X_val), scale_x(X_test)
|
|
21168
|
+
y_mu, y_sd = y_train.mean(0), y_train.std(0) + 1e-9 # per-output standardisation
|
|
21169
|
+
y_train_net = (y_train - y_mu) / y_sd
|
|
21170
|
+
n_classes = y.shape[1] # readout width = number of regression outputs
|
|
21171
|
+
loss_fn = mse_loss
|
|
21172
|
+
else:
|
|
21173
|
+
|
|
21174
|
+
X_train, X_test, y_train, y_test, X_val, y_val = _prepare_train_val_split(X=X, y=y, random_state=random_state)
|
|
21175
|
+
y_train_net = y_train
|
|
21176
|
+
n_classes = max(len(label_map), int(y_train.max() + 1))
|
|
21177
|
+
|
|
21132
21178
|
n_in = X_train.shape[1]
|
|
21133
|
-
|
|
21134
|
-
if net is None and hidden_layer is None:
|
|
21179
|
+
if net is None or hidden_layer is None:
|
|
21135
21180
|
net, hidden_layer = build_snn_network(n_in, n_hidden, n_classes, rng)
|
|
21136
21181
|
|
|
21182
|
+
if reg:
|
|
21183
|
+
net.regression_scalers = {'lo': lo, 'span': span, 'y_mu': y_mu, 'y_sd': y_sd}
|
|
21184
|
+
|
|
21137
21185
|
encoder = PoissonEncoder(n_steps=n_steps, max_rate=1.0, rng=rng)
|
|
21138
21186
|
optimizer = Adam(lr=lr, weight_decay=1e-5)
|
|
21139
21187
|
homeostasis = ThresholdHomeostasis(target_rate=0.15, adjust_rate=0.05)
|
|
@@ -21169,16 +21217,28 @@ def train_snn_network(X=None, y=None, net=None, hidden_layer=None, label_map=Non
|
|
|
21169
21217
|
|
|
21170
21218
|
# Evaluation
|
|
21171
21219
|
net.eval()
|
|
21172
|
-
|
|
21173
|
-
|
|
21174
|
-
|
|
21175
|
-
|
|
21176
|
-
|
|
21177
|
-
|
|
21178
|
-
|
|
21179
|
-
|
|
21180
|
-
|
|
21181
|
-
|
|
21220
|
+
preds, _ = net.predict(encoder.encode(X_test), task=task)
|
|
21221
|
+
train_preds, _ = net.predict(encoder.encode(X_train), task=task)
|
|
21222
|
+
if reg:
|
|
21223
|
+
p_te = np.asarray(preds).reshape(len(X_test), -1) * y_sd + y_mu # back to original units
|
|
21224
|
+
p_tr = np.asarray(train_preds).reshape(len(X_train), -1) * y_sd + y_mu
|
|
21225
|
+
test_rmse = float(np.sqrt(np.mean((p_te - y_test) ** 2)))
|
|
21226
|
+
test_mae = float(np.mean(np.abs(p_te - y_test)))
|
|
21227
|
+
train_rmse = float(np.sqrt(np.mean((p_tr - y_train) ** 2)))
|
|
21228
|
+
r2 = float(1.0 - np.sum((p_te - y_test) ** 2) / (np.sum((y_test - y_train.mean(0)) ** 2) + 1e-12))
|
|
21229
|
+
print(f"[=] Epoch {epoch:2d} || train_loss={np.mean(epoch_losses):.4f} train_rmse={train_rmse:,.1f} || "
|
|
21230
|
+
f"test_rmse={test_rmse:,.1f} test_mae={test_mae:,.1f} R2={r2:.3f} || "
|
|
21231
|
+
f"hidden_threshold={hidden_layer.threshold:.3f}")
|
|
21232
|
+
test_score = r2
|
|
21233
|
+
else:
|
|
21234
|
+
test_acc = utility.accuracy(preds, y_test)
|
|
21235
|
+
train_acc = utility.accuracy(train_preds, y_train)
|
|
21236
|
+
print(f"[=] Epoch {epoch:2d} || train_loss={np.mean(epoch_losses):.4f} "
|
|
21237
|
+
f"train_acc={train_acc*100:5.1f} || test_acc={test_acc*100:5.1f}% || "
|
|
21238
|
+
f"hidden_threshold={hidden_layer.threshold:.3f}")
|
|
21239
|
+
test_score = test_acc
|
|
21240
|
+
|
|
21241
|
+
tracker.record(net, epoch, loss=loss, test_acc=test_score)
|
|
21182
21242
|
|
|
21183
21243
|
report = network_report(net)
|
|
21184
21244
|
print_report(report)
|
|
@@ -21188,8 +21248,25 @@ def train_snn_network(X=None, y=None, net=None, hidden_layer=None, label_map=Non
|
|
|
21188
21248
|
|
|
21189
21249
|
return encoder, net, report, warnings
|
|
21190
21250
|
|
|
21251
|
+
def _snn_predict_regression(X, net, encoder, n_mc=20):
|
|
21252
|
+
sc = getattr(net, 'regression_scalers', None)
|
|
21253
|
+
if sc is None:
|
|
21254
|
+
raise ValueError('[>] net has no regression_scalers: train it with train_snn_network(task="regression") first')
|
|
21255
|
+
X = np.asarray(X, dtype=np.float64)
|
|
21256
|
+
X = X.reshape(len(X), -1) # (N, W*F)
|
|
21257
|
+
Xs = np.clip((X - sc['lo']) / sc['span'], 0.0, 1.0)
|
|
21258
|
+
|
|
21259
|
+
# the Poisson encoder is stochastic, its repeated to get a prediction and a spread
|
|
21260
|
+
outs = np.stack([net.predict(encoder.encode(Xs), task='regression')[1] for _ in range(n_mc)]) # (n_mc, N, n_out)
|
|
21261
|
+
mean = outs.mean(0) * sc['y_sd'] + sc['y_mu']
|
|
21262
|
+
std = outs.std(0) * sc['y_sd']
|
|
21263
|
+
|
|
21264
|
+
if mean.shape[1] == 1:
|
|
21265
|
+
mean, std = mean[:, 0], std[:, 0]
|
|
21266
|
+
return {'prediction': mean, 'std': std}
|
|
21267
|
+
|
|
21191
21268
|
|
|
21192
|
-
def snn_predict(X=None, y=None, label_map=None, encoder=None, net=None, random_state=42, max_print_threshold=50):
|
|
21269
|
+
def snn_predict(X=None, y=None, task='classification', label_map=None, encoder=None, net=None, random_state=42, max_print_threshold=50):
|
|
21193
21270
|
utility = SNNUtility()
|
|
21194
21271
|
reverse_map = None
|
|
21195
21272
|
|
|
@@ -21223,9 +21300,13 @@ def snn_predict(X=None, y=None, label_map=None, encoder=None, net=None, random_s
|
|
|
21223
21300
|
if label_map and isinstance(label_map, dict):
|
|
21224
21301
|
reverse_map = {v: k for k, v in label_map.items()}
|
|
21225
21302
|
|
|
21303
|
+
if task == 'regression':
|
|
21304
|
+
result = _snn_predict_regression(X, net, encoder)
|
|
21305
|
+
return result
|
|
21306
|
+
|
|
21226
21307
|
try:
|
|
21227
21308
|
test_spikes = encoder.encode(X)
|
|
21228
|
-
preds, logits = net.predict(test_spikes)
|
|
21309
|
+
preds, logits = net.predict(test_spikes, task=task)
|
|
21229
21310
|
if reverse_map is not None:
|
|
21230
21311
|
# SNN-specific: uncertainty from the encoder's own stochasticity
|
|
21231
21312
|
mc_results = mc_confidence(net, encoder, X, n_samples=20, class_names=reverse_map)
|