AbstractIntegratedModule 1.1.2__tar.gz → 1.1.4__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.1.2 → abstractintegratedmodule-1.1.4}/AbstractIntegratedModule.egg-info/PKG-INFO +1 -1
- {abstractintegratedmodule-1.1.2 → abstractintegratedmodule-1.1.4}/AbstractIntegratedModule.py +271 -47
- {abstractintegratedmodule-1.1.2 → abstractintegratedmodule-1.1.4}/AbstractOptimizedModules.c +209 -201
- {abstractintegratedmodule-1.1.2 → abstractintegratedmodule-1.1.4}/PKG-INFO +1 -1
- {abstractintegratedmodule-1.1.2 → abstractintegratedmodule-1.1.4}/README.md +63 -16
- {abstractintegratedmodule-1.1.2 → abstractintegratedmodule-1.1.4}/pyproject.toml +1 -1
- {abstractintegratedmodule-1.1.2 → abstractintegratedmodule-1.1.4}/setup.py +1 -1
- {abstractintegratedmodule-1.1.2 → abstractintegratedmodule-1.1.4}/AbstractIntegratedModule.egg-info/SOURCES.txt +0 -0
- {abstractintegratedmodule-1.1.2 → abstractintegratedmodule-1.1.4}/AbstractIntegratedModule.egg-info/dependency_links.txt +0 -0
- {abstractintegratedmodule-1.1.2 → abstractintegratedmodule-1.1.4}/AbstractIntegratedModule.egg-info/requires.txt +0 -0
- {abstractintegratedmodule-1.1.2 → abstractintegratedmodule-1.1.4}/AbstractIntegratedModule.egg-info/top_level.txt +0 -0
- {abstractintegratedmodule-1.1.2 → abstractintegratedmodule-1.1.4}/AbstractOptimizedModules.pyx +0 -0
- {abstractintegratedmodule-1.1.2 → abstractintegratedmodule-1.1.4}/MANIFEST.in +0 -0
- {abstractintegratedmodule-1.1.2 → abstractintegratedmodule-1.1.4}/abstract_model_storage/Cargo.toml +0 -0
- {abstractintegratedmodule-1.1.2 → abstractintegratedmodule-1.1.4}/abstract_model_storage/pyproject.toml +0 -0
- {abstractintegratedmodule-1.1.2 → abstractintegratedmodule-1.1.4}/abstract_model_storage/src/lib.rs +0 -0
- {abstractintegratedmodule-1.1.2 → abstractintegratedmodule-1.1.4}/abstract_model_storage/target/debug/build/libsqlite3-sys-ed07b882cd2aa5e2/out/bindgen.rs +0 -0
- {abstractintegratedmodule-1.1.2 → abstractintegratedmodule-1.1.4}/abstract_model_storage/target/debug/build/serde_core-ebc15f2e9cad7f5f/out/private.rs +0 -0
- {abstractintegratedmodule-1.1.2 → abstractintegratedmodule-1.1.4}/abstract_model_storage/target/debug/build/target-lexicon-08527f45de28143d/out/host.rs +0 -0
- {abstractintegratedmodule-1.1.2 → abstractintegratedmodule-1.1.4}/abstract_model_storage/target/release/build/libsqlite3-sys-bf0400df4523274c/out/bindgen.rs +0 -0
- {abstractintegratedmodule-1.1.2 → abstractintegratedmodule-1.1.4}/abstract_model_storage/target/release/build/serde_core-5cdb76131825e4af/out/private.rs +0 -0
- {abstractintegratedmodule-1.1.2 → abstractintegratedmodule-1.1.4}/abstract_model_storage/target/release/build/target-lexicon-43eb95a0588bf457/out/host.rs +0 -0
- {abstractintegratedmodule-1.1.2 → abstractintegratedmodule-1.1.4}/setup.cfg +0 -0
{abstractintegratedmodule-1.1.2 → abstractintegratedmodule-1.1.4}/AbstractIntegratedModule.py
RENAMED
|
@@ -485,12 +485,12 @@ class GeometricWeightShaping:
|
|
|
485
485
|
subnet = x[:min(10, x.shape[0]), :min(10, x.shape[1])]
|
|
486
486
|
gradient = np.gradient(subnet.flatten())
|
|
487
487
|
|
|
488
|
-
|
|
488
|
+
mean_vector_mag = np.mean(np.linalg.norm(gradient, axis=-1))
|
|
489
489
|
X_mag = np.mean(np.linalg.norm(X, axis=-1))
|
|
490
490
|
# Regular AME Equations, higher AME provides capabilities for the model to experience errors during abstraction
|
|
491
491
|
# Lower AME means lower chance for un optimal abstraction.
|
|
492
492
|
|
|
493
|
-
AME = np.log1p(X_mag) * np.log1p(
|
|
493
|
+
AME = np.log1p(X_mag) * np.log1p(mean_vector_mag)
|
|
494
494
|
return AME
|
|
495
495
|
|
|
496
496
|
# anisotropy provides the model the standard complexity of the data geometry, allowing it to know how complex the data needs to be processed.
|
|
@@ -1920,6 +1920,48 @@ class MLP:
|
|
|
1920
1920
|
|
|
1921
1921
|
return self.softmax.forward(x)
|
|
1922
1922
|
|
|
1923
|
+
def k_fold_split(self, X, y, k=5, seed=42, min_fold_size=2):
|
|
1924
|
+
X = np.asarray(X)
|
|
1925
|
+
y = np.asarray(y)
|
|
1926
|
+
n = len(X)
|
|
1927
|
+
|
|
1928
|
+
# adapt k downward for small datasets, never produce
|
|
1929
|
+
# folds smaller than min_fold_size
|
|
1930
|
+
effective_k = min(k, max(2, n // min_fold_size))
|
|
1931
|
+
if effective_k < k:
|
|
1932
|
+
print(f'[⚠️] k_fold_split: reduced k from {k} to {effective_k} '
|
|
1933
|
+
f'for n={n} samples, to avoid folds smaller than '
|
|
1934
|
+
f'{min_fold_size} samples')
|
|
1935
|
+
|
|
1936
|
+
rng = np.random.default_rng(seed)
|
|
1937
|
+
idx = rng.permutation(n)
|
|
1938
|
+
folds = np.array_split(idx, effective_k)
|
|
1939
|
+
|
|
1940
|
+
for i in range(effective_k):
|
|
1941
|
+
val_idx = folds[i]
|
|
1942
|
+
train_idx = np.concatenate([folds[j] for j in range(effective_k) if j != i])
|
|
1943
|
+
yield X[train_idx], y[train_idx], X[val_idx], y[val_idx]
|
|
1944
|
+
|
|
1945
|
+
|
|
1946
|
+
def confusion_matrix(self, y_true, y_pred, num_classes):
|
|
1947
|
+
y_true = np.asarray(y_true)
|
|
1948
|
+
y_pred = np.asarray(y_pred)
|
|
1949
|
+
|
|
1950
|
+
cm = np.zeros((num_classes, num_classes), dtype=int)
|
|
1951
|
+
|
|
1952
|
+
# Convert to label arrays: use argmax only if input is one-hot/prob (2D+),
|
|
1953
|
+
# otherwise need to treat as already being class labels.
|
|
1954
|
+
true_labels = np.argmax(y_true, axis=1) if y_true.ndim > 1 else y_true
|
|
1955
|
+
pred_labels = np.argmax(y_pred, axis=1) if y_pred.ndim > 1 else y_pred
|
|
1956
|
+
|
|
1957
|
+
for t, p in zip(true_labels, pred_labels):
|
|
1958
|
+
if 0 <= t < num_classes and 0 <= p < num_classes:
|
|
1959
|
+
cm[t, p] += 1
|
|
1960
|
+
else:
|
|
1961
|
+
print(f'[⚠️] confusion_matrix: label out of range '
|
|
1962
|
+
f'(true={t}, pred={p}, num_classes={num_classes}) — skipped')
|
|
1963
|
+
return cm
|
|
1964
|
+
|
|
1923
1965
|
def performance_calculation(self, x, AME=None, anisotropy=None):
|
|
1924
1966
|
eps = 1e-5
|
|
1925
1967
|
standard_low_error_mean = eps
|
|
@@ -1943,7 +1985,7 @@ class MLP:
|
|
|
1943
1985
|
|
|
1944
1986
|
return performance_score
|
|
1945
1987
|
|
|
1946
|
-
def forward(self, x, AME=None, anisotropy=None):
|
|
1988
|
+
def forward(self, x, y=None, AME=None, anisotropy=None, condition=None):
|
|
1947
1989
|
eps = 1e-5
|
|
1948
1990
|
performance_score = self.performance_calculation(x, AME=AME, anisotropy=anisotropy)
|
|
1949
1991
|
|
|
@@ -1951,6 +1993,11 @@ class MLP:
|
|
|
1951
1993
|
x = layer.forward(x, performance_score)
|
|
1952
1994
|
|
|
1953
1995
|
output = self.softmax.forward(x)
|
|
1996
|
+
if not condition == 'training' and y is not None:
|
|
1997
|
+
if y.shape == output.shape:
|
|
1998
|
+
acc = np.mean(np.argmax(output, axis=1) == np.argmax(y, axis=1))
|
|
1999
|
+
loss = Loss.categorical_crossentropy(y, output)
|
|
2000
|
+
print(f"[=] MLP Forward validation score: | loss: {loss:.4f} | Acc: {acc:.2%}")
|
|
1954
2001
|
|
|
1955
2002
|
return output
|
|
1956
2003
|
|
|
@@ -2175,7 +2222,7 @@ class MLP:
|
|
|
2175
2222
|
print(f'[+] MLP Training started with: {parameters} Parameters.')
|
|
2176
2223
|
for epoch in range(epochs):
|
|
2177
2224
|
if not focused_fit_condition:
|
|
2178
|
-
y_pred = self.forward(X, AME=AME, anisotropy=anisotropy)
|
|
2225
|
+
y_pred = self.forward(X, y=y, AME=AME, anisotropy=anisotropy, condition='training')
|
|
2179
2226
|
else:
|
|
2180
2227
|
y_pred = self.focused_forward(X, AME=AME, anisotropy=anisotropy)
|
|
2181
2228
|
|
|
@@ -3402,7 +3449,7 @@ class WeightedEnsemblePredictor:
|
|
|
3402
3449
|
AME = self.pipeline.model2.AME_Encoder(input_ids)
|
|
3403
3450
|
|
|
3404
3451
|
trans_probs, attn_weights = self.pipeline.model2.forward(input_ids, AME=AME, embedded=embedded)
|
|
3405
|
-
mlp_probs = self.pipeline.model3.forward(X_mlp)
|
|
3452
|
+
mlp_probs = self.pipeline.model3.forward(X_mlp, y=y_true)
|
|
3406
3453
|
lstm_probs, lstm_weight_hint = self._get_lstm_probs(input_ids, X_mlp, label_bins=label_bins)
|
|
3407
3454
|
|
|
3408
3455
|
established_agreement = self.query_node._establish_node_connection("PredictEnsemble")
|
|
@@ -4447,9 +4494,8 @@ class ExplainabilityModule:
|
|
|
4447
4494
|
print('[=] Note: Very little Consistency meaning Transformer attention quality is Healthy and focused')
|
|
4448
4495
|
|
|
4449
4496
|
if isinstance(final_conf, np.ndarray):
|
|
4450
|
-
final_conf = 1.0 / (1.0 + np.
|
|
4451
|
-
#
|
|
4452
|
-
# with real covariance of distribution from the data.
|
|
4497
|
+
final_conf = 1.0 / (1.0 + np.exp(-final_conf))
|
|
4498
|
+
# Apply a sigmoid transformation to ensure the confidence is between 0 and 1
|
|
4453
4499
|
|
|
4454
4500
|
if np.isnan(final_conf).any() or np.isinf(final_conf).any():
|
|
4455
4501
|
final_conf = self.pipeline.confidence_threshold
|
|
@@ -5944,10 +5990,13 @@ class ModelStorage:
|
|
|
5944
5990
|
|
|
5945
5991
|
try:
|
|
5946
5992
|
weights = result
|
|
5947
|
-
|
|
5948
|
-
|
|
5949
|
-
|
|
5950
|
-
self.pipeline.network_model.
|
|
5993
|
+
if isinstance(weights, str):
|
|
5994
|
+
weights = json.loads(weights)
|
|
5995
|
+
|
|
5996
|
+
self.pipeline.network_model.cell.W = np.array(weights.get('lstm_W'))
|
|
5997
|
+
self.pipeline.network_model.cell.b = np.array(weights.get('lstm_b'))
|
|
5998
|
+
self.pipeline.network_model.Wy = np.array(weights.get('Wy')) if weights.get('Wy') else None
|
|
5999
|
+
self.pipeline.network_model.by = np.array(weights.get('by'))
|
|
5951
6000
|
self.pipeline.lstm_engine.residual_mean = weights.get('residual_mean', 0.0)
|
|
5952
6001
|
self.pipeline.lstm_engine.residual_std = weights.get('residual_std', 1.0)
|
|
5953
6002
|
self.pipeline.lstm_engine.n_samples = weights.get('n_samples', self.pipeline.lstm_engine.n_samples)
|
|
@@ -5963,6 +6012,7 @@ class ModelStorage:
|
|
|
5963
6012
|
|
|
5964
6013
|
except Exception as e:
|
|
5965
6014
|
print(f'[!] Cant load any Weights due to: {e}')
|
|
6015
|
+
traceback.print_exc()
|
|
5966
6016
|
|
|
5967
6017
|
|
|
5968
6018
|
def load_transformer_dict(self, memory_name):
|
|
@@ -9544,6 +9594,10 @@ class IntegratedPipeline:
|
|
|
9544
9594
|
self.lstm_lr = 5e-2
|
|
9545
9595
|
self.lstm_hidden_dim = 64
|
|
9546
9596
|
|
|
9597
|
+
self.unsuitable_tolerance = False
|
|
9598
|
+
self.unsuitable_conditions = False
|
|
9599
|
+
self.unsuitable_peer_request = False
|
|
9600
|
+
|
|
9547
9601
|
# Main component setup
|
|
9548
9602
|
self.standard_scaler = StandardScaler()
|
|
9549
9603
|
self.tfidf = TfidfVectorizer(max_features=70)
|
|
@@ -9818,6 +9872,133 @@ class IntegratedPipeline:
|
|
|
9818
9872
|
f"Unexpected memory type: {type(memory).__name__}",
|
|
9819
9873
|
"Clear and reinitialize memory")
|
|
9820
9874
|
|
|
9875
|
+
def k_fold_cross_validate(self, X, y, input_dim, n_classes, k=5, seed=42,
|
|
9876
|
+
epochs=None, lr=None, log_to_diagnostics=True):
|
|
9877
|
+
"""
|
|
9878
|
+
Orchestrates init → train → predict across k folds. Each fold gets
|
|
9879
|
+
a FRESH model (no weight carryover between folds), and the model
|
|
9880
|
+
that existed before k-fold started is restored afterward — k-fold
|
|
9881
|
+
here is purely an evaluation procedure, not a permanent side effect.
|
|
9882
|
+
"""
|
|
9883
|
+
X = np.asarray(X)
|
|
9884
|
+
y = np.asarray(y)
|
|
9885
|
+
|
|
9886
|
+
# preserve pre-existing model, restore it once CV is done
|
|
9887
|
+
original_model = getattr(self, 'model3', None)
|
|
9888
|
+
|
|
9889
|
+
recorder = None
|
|
9890
|
+
if log_to_diagnostics:
|
|
9891
|
+
try:
|
|
9892
|
+
from abstract_diagnostics import get_recorder
|
|
9893
|
+
recorder = get_recorder(self.memory_name)
|
|
9894
|
+
except ImportError:
|
|
9895
|
+
pass # diagnostics package not installed — silently skip, no crash
|
|
9896
|
+
|
|
9897
|
+
aggregate_cm = np.zeros((n_classes, n_classes), dtype=int)
|
|
9898
|
+
fold_accuracies = []
|
|
9899
|
+
|
|
9900
|
+
for fold_idx, (X_tr, y_tr, X_val, y_val) in enumerate(
|
|
9901
|
+
self.model3.k_fold_split(X, y, k=k, seed=seed)
|
|
9902
|
+
):
|
|
9903
|
+
# FRESH model every fold — this is the load-bearing line
|
|
9904
|
+
self.initialize_model_(X_tr, input_dim, n_classes)
|
|
9905
|
+
self.model3.train(X_tr, y_tr,
|
|
9906
|
+
epochs=epochs or self.mlp_training_epochs,
|
|
9907
|
+
lr=lr or self.mlp_lr)
|
|
9908
|
+
|
|
9909
|
+
y_pred = self.model3.forward(X_val)
|
|
9910
|
+
cm = self.model3.confusion_matrix(y_val, y_pred, n_classes)
|
|
9911
|
+
aggregate_cm += cm
|
|
9912
|
+
|
|
9913
|
+
fold_acc = np.trace(cm) / max(cm.sum(), 1)
|
|
9914
|
+
fold_accuracies.append(fold_acc)
|
|
9915
|
+
print(f'[=] Fold {fold_idx + 1}/{k}: accuracy={fold_acc:.2%}')
|
|
9916
|
+
|
|
9917
|
+
if recorder:
|
|
9918
|
+
recorder.log_scalar('mlp/kfold_accuracy', fold_acc, step=fold_idx)
|
|
9919
|
+
|
|
9920
|
+
self.model3 = original_model # restore — CV was evaluation only
|
|
9921
|
+
|
|
9922
|
+
mean_acc, std_acc = float(np.mean(fold_accuracies)), float(np.std(fold_accuracies))
|
|
9923
|
+
print(f'[=] K-Fold CV complete: {mean_acc:.2%} ± {std_acc:.2%}')
|
|
9924
|
+
|
|
9925
|
+
if recorder:
|
|
9926
|
+
recorder.log_scalar('mlp/kfold_mean_accuracy', mean_acc)
|
|
9927
|
+
recorder.log_scalar('mlp/kfold_std_accuracy', std_acc)
|
|
9928
|
+
|
|
9929
|
+
return {
|
|
9930
|
+
'fold_accuracies': fold_accuracies,
|
|
9931
|
+
'mean_accuracy': mean_acc,
|
|
9932
|
+
'std_accuracy': std_acc,
|
|
9933
|
+
'confusion_matrix': aggregate_cm,
|
|
9934
|
+
}
|
|
9935
|
+
|
|
9936
|
+
def evaluate_mlp_performance(self, X, y, label_map, k=5, seed=42):
|
|
9937
|
+
"""
|
|
9938
|
+
input_dim and n_classes are ALWAYS derived from the actual X/y
|
|
9939
|
+
given to this call — never accepted as separate parameters that
|
|
9940
|
+
could silently drift out of sync with the real data (the exact
|
|
9941
|
+
bug class this whole session was about).
|
|
9942
|
+
"""
|
|
9943
|
+
X = np.asarray(X)
|
|
9944
|
+
y = np.asarray(y)
|
|
9945
|
+
|
|
9946
|
+
if X.ndim == 1:
|
|
9947
|
+
X = X.reshape(-1, 1)
|
|
9948
|
+
|
|
9949
|
+
# derived input_dim directly from X, matching this call's
|
|
9950
|
+
# ACTUAL data.
|
|
9951
|
+
input_dim = X.shape[1]
|
|
9952
|
+
model_classes = self._get_num_classes()
|
|
9953
|
+
|
|
9954
|
+
#derived n_classes the same authoritative way used
|
|
9955
|
+
# throughout the rest of the pipeline (_get_num_classes as
|
|
9956
|
+
# primary source, cross-checked against y itself)
|
|
9957
|
+
|
|
9958
|
+
y_arr = np.asarray(y)
|
|
9959
|
+
|
|
9960
|
+
onehot_validation = self._validate_onehot(y)
|
|
9961
|
+
if onehot_validation:
|
|
9962
|
+
if model_classes != len(label_map):
|
|
9963
|
+
model_classes = len(label_map)
|
|
9964
|
+
if model_classes > np.max(y):
|
|
9965
|
+
y = np.eye(model_classes)[np.asarray(y)]
|
|
9966
|
+
else:
|
|
9967
|
+
print('[⚠️] Warning: Proper Y onehot encoding fails, modifying number of classes to exactly match Y values to do one final one hot encoding...')
|
|
9968
|
+
try:
|
|
9969
|
+
model_classes = np.max(y) + 1
|
|
9970
|
+
y = np.eye(model_classes)[np.asarray(y)]
|
|
9971
|
+
except:
|
|
9972
|
+
print('[!] Error: One hot encoding failed, please check your Y values and label map for consistency, passing raw Y and skipping MLP Training...')
|
|
9973
|
+
unsuitable = True
|
|
9974
|
+
y = y.copy() # fallback to raw y if one-hot fails
|
|
9975
|
+
|
|
9976
|
+
if y_arr.ndim > 1:
|
|
9977
|
+
n_classes_from_y = y_arr.shape[1]
|
|
9978
|
+
else:
|
|
9979
|
+
n_classes_from_y = int(y_arr.max()) + 1
|
|
9980
|
+
|
|
9981
|
+
if model_classes is not None and model_classes != n_classes_from_y:
|
|
9982
|
+
print(f'[⚠️] evaluate_mlp_performance: n_classes mismatch — '
|
|
9983
|
+
f'model reports {model_classes}, y data implies '
|
|
9984
|
+
f'{n_classes_from_y}. Using y-derived value ({n_classes_from_y}) '
|
|
9985
|
+
f'since k-fold must match the ACTUAL labels being evaluated.')
|
|
9986
|
+
n_classes = n_classes_from_y
|
|
9987
|
+
|
|
9988
|
+
print(f'[=] evaluate_mlp_performance: derived input_dim={input_dim}, '
|
|
9989
|
+
f'n_classes={n_classes} from provided X/y (shapes: '
|
|
9990
|
+
f'X={X.shape}, y={y_arr.shape})')
|
|
9991
|
+
|
|
9992
|
+
result = self.k_fold_cross_validate(X, y, input_dim, n_classes, k=k, seed=seed)
|
|
9993
|
+
|
|
9994
|
+
print('========= MLP Performance Evaluation Summary ============')
|
|
9995
|
+
print(f'[=>] MLP performance evaluation complete: mean accuracy={result["mean_accuracy"]:.2%}, '
|
|
9996
|
+
f'std accuracy={result["std_accuracy"]:.2%}')
|
|
9997
|
+
print(f'[=>] Confusion matrix:\n{result["confusion_matrix"]}')
|
|
9998
|
+
print(f'[=>] Fold accuracies: {result["fold_accuracies"]}')
|
|
9999
|
+
print(f'[=>] K-Fold CV complete: {result["mean_accuracy"]:.2%} ± {result["std_accuracy"]:.2%}')
|
|
10000
|
+
return result
|
|
10001
|
+
|
|
9821
10002
|
|
|
9822
10003
|
def _validate_tuple_memory(self, memory: tuple, num_classes: int) -> tuple:
|
|
9823
10004
|
"""
|
|
@@ -11501,7 +11682,7 @@ class IntegratedPipeline:
|
|
|
11501
11682
|
method='dynamic', embedded=embedded
|
|
11502
11683
|
)
|
|
11503
11684
|
else:
|
|
11504
|
-
fresh_probs = self.model3.forward(fresh_X_raw)
|
|
11685
|
+
fresh_probs = self.model3.forward(fresh_X_raw, y=y_true)
|
|
11505
11686
|
try:
|
|
11506
11687
|
fresh_trans_probs, _ = self.model2.forward(fresh_input_ids, embedded=False)
|
|
11507
11688
|
except:
|
|
@@ -12102,9 +12283,12 @@ class IntegratedPipeline:
|
|
|
12102
12283
|
calibrated[i, mlp_target_int] * (1.5 * (1.0 - abstract_score)), 0.95
|
|
12103
12284
|
)
|
|
12104
12285
|
else:
|
|
12105
|
-
|
|
12106
|
-
calibrated[mlp_target_int]
|
|
12107
|
-
|
|
12286
|
+
if mlp_target_int < len(calibrated):
|
|
12287
|
+
calibrated[mlp_target_int] = min(
|
|
12288
|
+
calibrated[mlp_target_int] * (1.5 * (1.0 - abstract_score)), 0.95
|
|
12289
|
+
)
|
|
12290
|
+
else:
|
|
12291
|
+
calibrated = min(calibrated * (1.5 * (1.0 - abstract_score)), 0.95)
|
|
12108
12292
|
|
|
12109
12293
|
if i <= len(calibrated):
|
|
12110
12294
|
try:
|
|
@@ -12513,7 +12697,7 @@ class IntegratedPipeline:
|
|
|
12513
12697
|
lengths.add(1)
|
|
12514
12698
|
|
|
12515
12699
|
if len(lengths) > 1:
|
|
12516
|
-
# RAGGED — pad to uniform length
|
|
12700
|
+
# RAGGED — pad to uniform length.
|
|
12517
12701
|
max_len = max(lengths)
|
|
12518
12702
|
print(f'[=] AME_Encoder: ragged input detected '
|
|
12519
12703
|
f'(lengths: {lengths}) — padding to {max_len}')
|
|
@@ -12871,6 +13055,7 @@ class IntegratedPipeline:
|
|
|
12871
13055
|
|
|
12872
13056
|
return float(np.asarray(arr).flat[-1]) # ultimate fallback, never crashes
|
|
12873
13057
|
|
|
13058
|
+
|
|
12874
13059
|
def _get_ensemble_confidence_for_true_class(self, X, Y, input_ids=None, eps=1e-3):
|
|
12875
13060
|
"""
|
|
12876
13061
|
Computes, per sample, how confident the MLP + Transformer ensemble
|
|
@@ -12914,7 +13099,7 @@ class IntegratedPipeline:
|
|
|
12914
13099
|
if X.shape != self.model3.layers[0].W.shape:
|
|
12915
13100
|
X = np.reshape(X, (n_samples, self.model3.layers[0].W.shape[0]))
|
|
12916
13101
|
|
|
12917
|
-
mlp_probs = np.asarray(self.model3.forward(X), dtype=np.float64)
|
|
13102
|
+
mlp_probs = np.asarray(self.model3.forward(X, y=Y), dtype=np.float64)
|
|
12918
13103
|
if mlp_probs.ndim == 1:
|
|
12919
13104
|
mlp_probs = mlp_probs.reshape(1, -1)
|
|
12920
13105
|
except Exception as e:
|
|
@@ -12980,6 +13165,7 @@ class IntegratedPipeline:
|
|
|
12980
13165
|
|
|
12981
13166
|
return confidences
|
|
12982
13167
|
|
|
13168
|
+
|
|
12983
13169
|
def lstm_setup_inference(self, raw_X, raw_Y, input_ids=None):
|
|
12984
13170
|
print("\n" + "=" * 55)
|
|
12985
13171
|
print("===== LSTM SETUP INFERENCE =====")
|
|
@@ -13086,6 +13272,10 @@ class IntegratedPipeline:
|
|
|
13086
13272
|
unsuitable_training = False
|
|
13087
13273
|
|
|
13088
13274
|
probs = self.model_memory_gate(input_ids, x)
|
|
13275
|
+
cache = self.accurate_cache_lookup.lookup(
|
|
13276
|
+
x_mlp=x,
|
|
13277
|
+
input_ids=input_ids)
|
|
13278
|
+
cached = cache is not None and cache['similarity'] >= 0.95
|
|
13089
13279
|
|
|
13090
13280
|
anisotropy = self.anisotropy_measurement(input_ids)
|
|
13091
13281
|
AME = self.AME_Encoder(input_ids)
|
|
@@ -13104,11 +13294,15 @@ class IntegratedPipeline:
|
|
|
13104
13294
|
# AMR is guaranteed to give sufficient ratio on how modelling error error could be sufficient enough to guarantee the model successful training
|
|
13105
13295
|
# (not too high that it shows unstability, not too low that it shows rigidity), high anisotropy correlates to a much complex non linearity that the model will have a hard time adjusting
|
|
13106
13296
|
# Too high AAC means the model is likely to be in a regime where training could lead to overfitting or divergence due to insufficient modelling capacity relative to the complexity of the data, especially if the confidence score is also low, indicating that the model is not currently confident in its predictions and may not benefit from further training on this data.
|
|
13107
|
-
unsuitable_tolerance = probs is not None or AAC > 0.75
|
|
13297
|
+
unsuitable_tolerance = probs is not None and cached or AAC > 0.75
|
|
13108
13298
|
unsuitable_conditions = anisotropy > 0.85 or final_conf > confidence_threshold or self.froze_learning
|
|
13109
13299
|
unsuitable_peer_request = probs is not None and self.peer_assistance_threshold > self.confidence_threshold
|
|
13110
13300
|
|
|
13111
|
-
|
|
13301
|
+
self.unsuitable_tolerance = unsuitable_tolerance
|
|
13302
|
+
self.unsuitable_conditions = unsuitable_conditions
|
|
13303
|
+
self.unsuitable_peer_request = unsuitable_peer_request
|
|
13304
|
+
|
|
13305
|
+
if self.unsuitable_tolerance or self.unsuitable_conditions or self.unsuitable_peer_request:
|
|
13112
13306
|
print(f'[==] Unsuitable training condition detected! Tolerance: {unsuitable_tolerance} || Unsuitable Conditions: {unsuitable_conditions}')
|
|
13113
13307
|
print(f'[==] Peer assistance condition: {unsuitable_peer_request} || Peer assistance threshold: {self.peer_assistance_threshold}')
|
|
13114
13308
|
unsuitable_training = True
|
|
@@ -13174,6 +13368,8 @@ class IntegratedPipeline:
|
|
|
13174
13368
|
if sequence_inputs.shape[1] == 1:
|
|
13175
13369
|
print('[=] transformer_pooled_features: single-timestep input, '
|
|
13176
13370
|
'std_pool will be all zeros (no variance across T=1)')
|
|
13371
|
+
print('[=] Reshaping sequence inputs to 2 dimension...')
|
|
13372
|
+
sequence_inputs = sequence_inputs.reshape(-1, 1)
|
|
13177
13373
|
|
|
13178
13374
|
mean_pool = np.mean(sequence_inputs, axis=1)
|
|
13179
13375
|
max_pool = np.max(sequence_inputs, axis=1)
|
|
@@ -13207,6 +13403,7 @@ class IntegratedPipeline:
|
|
|
13207
13403
|
|
|
13208
13404
|
if isinstance(X_provided, (str, np.str_)):
|
|
13209
13405
|
X_provided = _safe_parse_string(X_provided)
|
|
13406
|
+
|
|
13210
13407
|
|
|
13211
13408
|
if isinstance(X_provided, np.ndarray) and np.issubdtype(X_provided.dtype, np.character):
|
|
13212
13409
|
joined = ' '.join(X_provided.astype(str).flatten())
|
|
@@ -13299,7 +13496,7 @@ class IntegratedPipeline:
|
|
|
13299
13496
|
|
|
13300
13497
|
issues = []
|
|
13301
13498
|
|
|
13302
|
-
# 1. Values outside [0, 1]
|
|
13499
|
+
# 1. Values outside [0, 1].
|
|
13303
13500
|
out_of_range = (y_true < 0) | (y_true > 1)
|
|
13304
13501
|
if out_of_range.any():
|
|
13305
13502
|
bad_rows = np.where(out_of_range.any(axis=1))[0]
|
|
@@ -13332,7 +13529,7 @@ class IntegratedPipeline:
|
|
|
13332
13529
|
)
|
|
13333
13530
|
|
|
13334
13531
|
if issues:
|
|
13335
|
-
print(f"[
|
|
13532
|
+
print(f"[>] [{context}] y sample is not properly one-hot encoded, one-hot encoding y sample...")
|
|
13336
13533
|
return True
|
|
13337
13534
|
|
|
13338
13535
|
return False
|
|
@@ -13341,6 +13538,7 @@ class IntegratedPipeline:
|
|
|
13341
13538
|
def transformer_utilities(self, X_provided= None, X_raw=None, y_true=None, rules=None,
|
|
13342
13539
|
datasets=None, label_map=None, batch_size=2, min_signal=1e-3,
|
|
13343
13540
|
max_samples_for_focused_fit=500):
|
|
13541
|
+
unsuitable = False
|
|
13344
13542
|
if X_provided is not None:
|
|
13345
13543
|
X_raw = X_provided
|
|
13346
13544
|
|
|
@@ -13443,7 +13641,7 @@ class IntegratedPipeline:
|
|
|
13443
13641
|
weak_rows = np.where(row_sums < min_signal)[0]
|
|
13444
13642
|
weak_ratio = len(weak_rows) / len(X_raw_features)
|
|
13445
13643
|
|
|
13446
|
-
print(f'[
|
|
13644
|
+
print(f'[>] Zero ratio in samples: {weak_ratio * 100}%')
|
|
13447
13645
|
if weak_ratio > 0.3: # more than 30% zero rows means vocab mismatch
|
|
13448
13646
|
if isinstance(X_raw_generation[0], str):
|
|
13449
13647
|
print(f'[= ! =] High zero-row ratio ({weak_ratio:.0%}), refitting on current batch')
|
|
@@ -13503,8 +13701,14 @@ class IntegratedPipeline:
|
|
|
13503
13701
|
if n_classes > np.max(y):
|
|
13504
13702
|
y = np.eye(n_classes)[np.asarray(y)]
|
|
13505
13703
|
else:
|
|
13506
|
-
print('[⚠️] Warning: Y onehot encoding fails,
|
|
13507
|
-
|
|
13704
|
+
print('[⚠️] Warning: Proper Y onehot encoding fails, modifying number of classes to exactly match Y values to do one final one hot encoding...')
|
|
13705
|
+
try:
|
|
13706
|
+
n_classes = np.max(y) + 1
|
|
13707
|
+
y = np.eye(n_classes)[np.asarray(y)]
|
|
13708
|
+
except:
|
|
13709
|
+
print('[!] Error: One hot encoding failed, please check your Y values and label map for consistency, passing raw Y and skipping MLP Training...')
|
|
13710
|
+
unsuitable = True
|
|
13711
|
+
y = y.copy() # fallback to raw y if one-hot fails
|
|
13508
13712
|
|
|
13509
13713
|
if self.model2 is None:
|
|
13510
13714
|
self.model2 = Transformer(
|
|
@@ -13517,9 +13721,15 @@ class IntegratedPipeline:
|
|
|
13517
13721
|
if self.use_transformer:
|
|
13518
13722
|
self.model2.train(sequence_inputs, y_true, epochs=self.transformer_training_epochs, mode=mode, lr=lr, embedded=True, batch_size=batch_size)
|
|
13519
13723
|
|
|
13520
|
-
X = self.shape_adaptation(hybrid_X, input_dim)
|
|
13724
|
+
X = self.shape_adaptation(hybrid_X, input_dim)
|
|
13725
|
+
|
|
13726
|
+
|
|
13521
13727
|
self.initialize_model_(X, input_dim, n_classes)
|
|
13522
|
-
|
|
13728
|
+
if not unsuitable:
|
|
13729
|
+
self.model3.train(X, y, epochs=self.mlp_training_epochs, lr=self.mlp_lr, max_samples_for_focused_fit=max_samples_for_focused_fit)
|
|
13730
|
+
else:
|
|
13731
|
+
print('[->] MLP Training skipped due to unproper Y samples.')
|
|
13732
|
+
|
|
13523
13733
|
self.lstm_setup_inference(X, y, input_ids=sequence_inputs)
|
|
13524
13734
|
if self.lstm_engine:
|
|
13525
13735
|
self.storage.save_weights(self.memory_name, model_type='Pipeline')
|
|
@@ -13527,7 +13737,7 @@ class IntegratedPipeline:
|
|
|
13527
13737
|
print('🎉 All Model Trained!')
|
|
13528
13738
|
else:
|
|
13529
13739
|
print(f'[=] No suitable condition for training!')
|
|
13530
|
-
print('[
|
|
13740
|
+
print('[>] Loading Weights for prediction...')
|
|
13531
13741
|
|
|
13532
13742
|
num_classes = self._get_num_classes(label_map=label_map) if label_map else (y_true.shape[1] if y_true.ndim > 1 else len(np.unique(y_true)))
|
|
13533
13743
|
|
|
@@ -16369,15 +16579,8 @@ class PipelinePredictionManager:
|
|
|
16369
16579
|
X_tfidf = X
|
|
16370
16580
|
|
|
16371
16581
|
# Forward pass through MLP
|
|
16372
|
-
|
|
16373
|
-
|
|
16374
|
-
X_tfidf = X
|
|
16375
|
-
mlp_probs = self.pipeline.model3.predict_proba(X)
|
|
16376
|
-
else:
|
|
16377
|
-
# Fallback if predict_proba not available
|
|
16378
|
-
logits = self.pipeline.model3.forward(X)
|
|
16379
|
-
mlp_probs = self.pipeline._softmax(logits)
|
|
16380
|
-
|
|
16582
|
+
mlp_probs = self.pipeline.model3.forward(X, y=y)
|
|
16583
|
+
|
|
16381
16584
|
# Validate all MLP predictions at once
|
|
16382
16585
|
mlp_pred_indices = np.argmax(mlp_probs, axis=1)
|
|
16383
16586
|
if num_classes <= 0:
|
|
@@ -17414,12 +17617,8 @@ class PipelinePredictionManager:
|
|
|
17414
17617
|
X = np.asarray(X)
|
|
17415
17618
|
|
|
17416
17619
|
# MLP forward pass
|
|
17417
|
-
|
|
17418
|
-
|
|
17419
|
-
else:
|
|
17420
|
-
logits = self.pipeline.model3.forward(X)
|
|
17421
|
-
mlp_probs = self.pipeline._softmax(logits)
|
|
17422
|
-
|
|
17620
|
+
mlp_probs = self.pipeline.model3.forward(X, y=y_val)
|
|
17621
|
+
|
|
17423
17622
|
# Validate all MLP predictions at once
|
|
17424
17623
|
mlp_pred_indices = np.argmax(mlp_probs, axis=1)
|
|
17425
17624
|
if num_classes <= 0:
|
|
@@ -17554,7 +17753,9 @@ class PipelinePredictionManager:
|
|
|
17554
17753
|
|
|
17555
17754
|
# Transformer prediction and blending
|
|
17556
17755
|
if trans_probs is not None and attn_weights is not None:
|
|
17557
|
-
|
|
17756
|
+
if i < len(trans_probs):
|
|
17757
|
+
trans_probs_i = trans_probs[i]
|
|
17758
|
+
|
|
17558
17759
|
trans_class_idx = np.argmax(trans_probs_i)
|
|
17559
17760
|
if isinstance(trans_probs_i, float):
|
|
17560
17761
|
trans_confidence = target_confidence
|
|
@@ -17632,7 +17833,10 @@ class PipelinePredictionManager:
|
|
|
17632
17833
|
agreement = mlp_class_idx == trans_class_idx
|
|
17633
17834
|
|
|
17634
17835
|
else:
|
|
17635
|
-
|
|
17836
|
+
if i < len(mlp_probs):
|
|
17837
|
+
final_probs = mlp_probs[i]
|
|
17838
|
+
else:
|
|
17839
|
+
final_probs = mlp_probs[0]
|
|
17636
17840
|
|
|
17637
17841
|
final_class_idx = target_class_idx
|
|
17638
17842
|
final_confidence = target_confidence[0] if isinstance(target_confidence, np.ndarray) else target_confidence
|
|
@@ -17817,9 +18021,11 @@ class PipelinePredictionManager:
|
|
|
17817
18021
|
'X_samples': X,
|
|
17818
18022
|
'input_ids': input_ids
|
|
17819
18023
|
}
|
|
18024
|
+
print('[=] Displaying Test Performance Results....')
|
|
17820
18025
|
if titles is not None and len(titles) > 0:
|
|
17821
18026
|
correct, sec_correct = self.display_hybrid_results(payload, final_class_idx, results, top_k, verbose=True)
|
|
17822
|
-
|
|
18027
|
+
|
|
18028
|
+
|
|
17823
18029
|
return results, chosen_label, confidence
|
|
17824
18030
|
|
|
17825
18031
|
else:
|
|
@@ -18105,6 +18311,7 @@ class PipelinePredictionManager:
|
|
|
18105
18311
|
else:
|
|
18106
18312
|
print(f'[⚡] Final Prediction: {chosen_label} with confidence: {confidence:.1%}')
|
|
18107
18313
|
chosen_label = chosen_label
|
|
18314
|
+
|
|
18108
18315
|
|
|
18109
18316
|
# delete pipelines cache
|
|
18110
18317
|
print('[🔍] Pipelines Cache Cleaned!')
|
|
@@ -18167,7 +18374,9 @@ class PipelinePredictionManager:
|
|
|
18167
18374
|
|
|
18168
18375
|
except Exception as e:
|
|
18169
18376
|
print(f'[!] Cant check and calibrate probs based on penalty due to: {e}')
|
|
18170
|
-
traceback.print_exc()
|
|
18377
|
+
traceback.print_exc()
|
|
18378
|
+
|
|
18379
|
+
|
|
18171
18380
|
|
|
18172
18381
|
return final_probs
|
|
18173
18382
|
|
|
@@ -20284,6 +20493,21 @@ def PermissiveTest():
|
|
|
20284
20493
|
("Watching Slack", "communication"),
|
|
20285
20494
|
("Programming in Visual Studio Code", "focused_work"),
|
|
20286
20495
|
("Watching netflix.com - Chrome", "break"),
|
|
20496
|
+
("Listening to Spotify", "entertainment"),
|
|
20497
|
+
("Playing Steam Game", "gaming"),
|
|
20498
|
+
("Checking Discord messages", "communication"),
|
|
20499
|
+
("Reading documentation on StackOverflow", "research"),
|
|
20500
|
+
("Downloading files from Google Drive", "file_work"),
|
|
20501
|
+
("Using Terminal to run scripts", "system_work"),
|
|
20502
|
+
("Analyzing data in Excel", "data_work"),
|
|
20503
|
+
("Attending Zoom meeting", "communication"),
|
|
20504
|
+
("Designing in Photoshop", "creative"),
|
|
20505
|
+
("Learning from Coursera course", "learning"),
|
|
20506
|
+
("Using Calculator utility", "utility"),
|
|
20507
|
+
("Browsing Facebook on Chrome", "social_media"),
|
|
20508
|
+
("Reading an eBook in PDF format", "reading"),
|
|
20509
|
+
("Listening to a podcast", "audio_learning"),
|
|
20510
|
+
("Using Google Translate", "utility"),
|
|
20287
20511
|
]
|
|
20288
20512
|
rules = [
|
|
20289
20513
|
# === WORK / PRODUCTIVITY ===
|