AbstractIntegratedModule 1.0.8__tar.gz → 1.1.0__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.0.8 → abstractintegratedmodule-1.1.0}/AbstractIntegratedModule.egg-info/PKG-INFO +1 -1
- {abstractintegratedmodule-1.0.8 → abstractintegratedmodule-1.1.0}/AbstractIntegratedModule.py +192 -99
- {abstractintegratedmodule-1.0.8 → abstractintegratedmodule-1.1.0}/AbstractOptimizedModules.c +200 -200
- {abstractintegratedmodule-1.0.8 → abstractintegratedmodule-1.1.0}/PKG-INFO +1 -1
- {abstractintegratedmodule-1.0.8 → abstractintegratedmodule-1.1.0}/README.md +4 -6
- {abstractintegratedmodule-1.0.8 → abstractintegratedmodule-1.1.0}/pyproject.toml +1 -1
- {abstractintegratedmodule-1.0.8 → abstractintegratedmodule-1.1.0}/setup.py +1 -1
- {abstractintegratedmodule-1.0.8 → abstractintegratedmodule-1.1.0}/AbstractIntegratedModule.egg-info/SOURCES.txt +0 -0
- {abstractintegratedmodule-1.0.8 → abstractintegratedmodule-1.1.0}/AbstractIntegratedModule.egg-info/dependency_links.txt +0 -0
- {abstractintegratedmodule-1.0.8 → abstractintegratedmodule-1.1.0}/AbstractIntegratedModule.egg-info/requires.txt +0 -0
- {abstractintegratedmodule-1.0.8 → abstractintegratedmodule-1.1.0}/AbstractIntegratedModule.egg-info/top_level.txt +0 -0
- {abstractintegratedmodule-1.0.8 → abstractintegratedmodule-1.1.0}/AbstractOptimizedModules.pyx +0 -0
- {abstractintegratedmodule-1.0.8 → abstractintegratedmodule-1.1.0}/MANIFEST.in +0 -0
- {abstractintegratedmodule-1.0.8 → abstractintegratedmodule-1.1.0}/abstract_model_storage/Cargo.toml +0 -0
- {abstractintegratedmodule-1.0.8 → abstractintegratedmodule-1.1.0}/abstract_model_storage/pyproject.toml +0 -0
- {abstractintegratedmodule-1.0.8 → abstractintegratedmodule-1.1.0}/abstract_model_storage/src/lib.rs +0 -0
- {abstractintegratedmodule-1.0.8 → abstractintegratedmodule-1.1.0}/abstract_model_storage/target/debug/build/libsqlite3-sys-ed07b882cd2aa5e2/out/bindgen.rs +0 -0
- {abstractintegratedmodule-1.0.8 → abstractintegratedmodule-1.1.0}/abstract_model_storage/target/debug/build/serde_core-ebc15f2e9cad7f5f/out/private.rs +0 -0
- {abstractintegratedmodule-1.0.8 → abstractintegratedmodule-1.1.0}/abstract_model_storage/target/debug/build/target-lexicon-08527f45de28143d/out/host.rs +0 -0
- {abstractintegratedmodule-1.0.8 → abstractintegratedmodule-1.1.0}/abstract_model_storage/target/release/build/libsqlite3-sys-bf0400df4523274c/out/bindgen.rs +0 -0
- {abstractintegratedmodule-1.0.8 → abstractintegratedmodule-1.1.0}/abstract_model_storage/target/release/build/serde_core-5cdb76131825e4af/out/private.rs +0 -0
- {abstractintegratedmodule-1.0.8 → abstractintegratedmodule-1.1.0}/abstract_model_storage/target/release/build/target-lexicon-43eb95a0588bf457/out/host.rs +0 -0
- {abstractintegratedmodule-1.0.8 → abstractintegratedmodule-1.1.0}/setup.cfg +0 -0
{abstractintegratedmodule-1.0.8 → abstractintegratedmodule-1.1.0}/AbstractIntegratedModule.py
RENAMED
|
@@ -869,10 +869,10 @@ class Transformer:
|
|
|
869
869
|
if _OPT_AVAILABLE:
|
|
870
870
|
B, S, D = batch_size, seq_len, d_model
|
|
871
871
|
M = D // self.n_heads
|
|
872
|
-
|
|
873
872
|
Q = optimized_project_heads(x, W_q_mix, B, S, self.n_heads, D, M)
|
|
874
873
|
K = optimized_project_heads(x, W_k_mix, B, S, self.n_heads, D, M)
|
|
875
874
|
V = optimized_project_heads(x, W_v_mix, B, S, self.n_heads, D, M)
|
|
875
|
+
|
|
876
876
|
else:
|
|
877
877
|
Q = np.einsum('bsd,hdm->bhsm', x, W_q_mix)
|
|
878
878
|
K = np.einsum('bsd,hdm->bhsm', x, W_k_mix)
|
|
@@ -1854,9 +1854,15 @@ class Dense:
|
|
|
1854
1854
|
db = np.sum(dz, axis=0, keepdims=True) / batch_size
|
|
1855
1855
|
dx = np.dot(dz, self.W.T)
|
|
1856
1856
|
|
|
1857
|
-
#
|
|
1858
|
-
|
|
1859
|
-
|
|
1857
|
+
# global norm clipping.
|
|
1858
|
+
# Preserves gradient DIRECTION, only scales magnitude down when
|
|
1859
|
+
# the total norm exceeds clip_value — avoided the frozen-equilibrium
|
|
1860
|
+
# pattern that per-element clipping can produce.
|
|
1861
|
+
total_norm = np.sqrt(np.sum(dW ** 2) + np.sum(db ** 2))
|
|
1862
|
+
if total_norm > clip_value:
|
|
1863
|
+
scale = clip_value / (total_norm + eps)
|
|
1864
|
+
dW *= scale
|
|
1865
|
+
db *= scale
|
|
1860
1866
|
|
|
1861
1867
|
self.W -= lr * dW
|
|
1862
1868
|
self.b -= lr * db
|
|
@@ -2144,6 +2150,7 @@ class MLP:
|
|
|
2144
2150
|
print(f'[!] Cant adapt shape of Y sample arrays due to: {e}')
|
|
2145
2151
|
return y_pred, y_true
|
|
2146
2152
|
|
|
2153
|
+
|
|
2147
2154
|
def train(self, X, y, epochs=1000, lr=0.01, verbose=True, max_samples_for_focused_fit=500):
|
|
2148
2155
|
X = self._sanitize_string_chars(X)
|
|
2149
2156
|
y = self._sanitize_string_chars(y)
|
|
@@ -2168,6 +2175,7 @@ class MLP:
|
|
|
2168
2175
|
y_pred = self.focused_forward(X, AME=AME, anisotropy=anisotropy)
|
|
2169
2176
|
|
|
2170
2177
|
y_pred, y_true = self.adapt_predict_shape(y_pred, y)
|
|
2178
|
+
|
|
2171
2179
|
loss = Loss.categorical_crossentropy(y_true, y_pred)
|
|
2172
2180
|
grad = Loss.softmax_crossentropy_derivative(y_true, y_pred)
|
|
2173
2181
|
if focused_fit_condition:
|
|
@@ -11589,7 +11597,6 @@ class IntegratedPipeline:
|
|
|
11589
11597
|
batch_probs = [None] * batch_size
|
|
11590
11598
|
fresh_probs = None # explicit init, no UnboundLocalError
|
|
11591
11599
|
|
|
11592
|
-
|
|
11593
11600
|
for i in range(batch_size):
|
|
11594
11601
|
probs = self.model_probability_gate(
|
|
11595
11602
|
batch_input_ids[i:i+1],
|
|
@@ -11601,92 +11608,96 @@ class IntegratedPipeline:
|
|
|
11601
11608
|
|
|
11602
11609
|
needs_prediction = [i for i, p in enumerate(batch_probs) if p is None]
|
|
11603
11610
|
|
|
11604
|
-
|
|
11605
|
-
|
|
11606
|
-
|
|
11611
|
+
try:
|
|
11612
|
+
if needs_prediction:
|
|
11613
|
+
fresh_input_ids = batch_input_ids[needs_prediction]
|
|
11614
|
+
fresh_X = batch_X[needs_prediction]
|
|
11607
11615
|
|
|
11608
|
-
|
|
11609
|
-
|
|
11616
|
+
transformer_pred, fresh_probs, attn_weights = self.model2.predict(fresh_input_ids)
|
|
11617
|
+
mlp_pred = self.mlp.forward(fresh_X)
|
|
11610
11618
|
|
|
11611
|
-
|
|
11612
|
-
|
|
11613
|
-
|
|
11619
|
+
# coerce indices to int
|
|
11620
|
+
mlp_pred_indices = np.argmax(mlp_pred, axis=1).astype(int)
|
|
11621
|
+
trans_pred_indices = np.argmax(fresh_probs, axis=1).astype(int)
|
|
11614
11622
|
|
|
11615
|
-
|
|
11623
|
+
for i, idx in enumerate(needs_prediction):
|
|
11616
11624
|
|
|
11617
|
-
|
|
11618
|
-
|
|
11619
|
-
|
|
11625
|
+
# validate indices in range before use
|
|
11626
|
+
mlp_cls = int(mlp_pred_indices[i])
|
|
11627
|
+
trans_cls = int(trans_pred_indices[i])
|
|
11620
11628
|
|
|
11621
|
-
|
|
11622
|
-
|
|
11623
|
-
|
|
11624
|
-
if mlp_cls != trans_cls:
|
|
11625
|
-
calibrated = self._calibrate_probs(
|
|
11626
|
-
fresh_probs[i:i+1],
|
|
11627
|
-
[mlp_cls],
|
|
11628
|
-
attn_weights[i:i+1] if attn_weights is not None else None,
|
|
11629
|
-
fresh_input_ids[i:i+1]
|
|
11630
|
-
)
|
|
11631
|
-
# validate calibrated output shape
|
|
11632
|
-
row = np.asarray(calibrated[0])
|
|
11633
|
-
if row.shape[0] != num_classes:
|
|
11634
|
-
aligned = np.zeros(num_classes)
|
|
11635
|
-
aligned[:min(row.shape[0], num_classes)] = row[:num_classes]
|
|
11636
|
-
row = aligned
|
|
11637
|
-
batch_probs[idx] = row
|
|
11629
|
+
mlp_cls = mlp_cls if 0 <= mlp_cls < num_classes else 0
|
|
11630
|
+
trans_cls = trans_cls if 0 <= trans_cls < num_classes else 0
|
|
11638
11631
|
|
|
11639
|
-
|
|
11640
|
-
|
|
11641
|
-
|
|
11642
|
-
|
|
11643
|
-
|
|
11644
|
-
|
|
11645
|
-
|
|
11646
|
-
|
|
11647
|
-
|
|
11648
|
-
|
|
11649
|
-
|
|
11650
|
-
|
|
11651
|
-
|
|
11652
|
-
|
|
11653
|
-
)
|
|
11654
|
-
self._prob_save_count = getattr(self, '_prob_save_count', 0) + 1
|
|
11632
|
+
if mlp_cls != trans_cls:
|
|
11633
|
+
calibrated = self._calibrate_probs(
|
|
11634
|
+
fresh_probs[i:i+1],
|
|
11635
|
+
[mlp_cls],
|
|
11636
|
+
attn_weights[i:i+1] if attn_weights is not None else None,
|
|
11637
|
+
fresh_input_ids[i:i+1]
|
|
11638
|
+
)
|
|
11639
|
+
# validate calibrated output shape
|
|
11640
|
+
row = np.asarray(calibrated[0])
|
|
11641
|
+
if row.shape[0] != num_classes:
|
|
11642
|
+
aligned = np.zeros(num_classes)
|
|
11643
|
+
aligned[:min(row.shape[0], num_classes)] = row[:num_classes]
|
|
11644
|
+
row = aligned
|
|
11645
|
+
batch_probs[idx] = row
|
|
11655
11646
|
|
|
11656
|
-
|
|
11657
|
-
|
|
11647
|
+
else:
|
|
11648
|
+
# models agree — boost confidence on agreed class
|
|
11649
|
+
probs_i = fresh_probs[i].copy() if i < len(fresh_probs) else fresh_probs[0]
|
|
11650
|
+
probs_i[trans_cls] = min(probs_i[trans_cls] * 1.2, 0.95)
|
|
11651
|
+
row_sum = probs_i.sum()
|
|
11652
|
+
probs_i /= row_sum if row_sum > 1e-8 else 1.0
|
|
11653
|
+
batch_probs[idx] = probs_i
|
|
11654
|
+
|
|
11655
|
+
# instance-level save counter, not local idx_total
|
|
11656
|
+
if getattr(self, '_prob_save_count', 0) < 2:
|
|
11657
|
+
self.modular_probability_saving(
|
|
11658
|
+
fresh_input_ids[i:i+1],
|
|
11659
|
+
fresh_X[i:i+1],
|
|
11660
|
+
np.array([batch_probs[idx]])
|
|
11661
|
+
)
|
|
11662
|
+
self._prob_save_count = getattr(self, '_prob_save_count', 0) + 1
|
|
11658
11663
|
|
|
11659
|
-
# safe final assembly with consistent shape
|
|
11660
|
-
valid_probs = []
|
|
11661
|
-
for i, p in enumerate(batch_probs):
|
|
11662
|
-
if p is None:
|
|
11663
|
-
valid_probs.append(zero_row.copy())
|
|
11664
|
-
elif isinstance(p, list):
|
|
11665
|
-
arr = np.array(p, dtype=np.float64)
|
|
11666
|
-
if arr.shape[0] != num_classes:
|
|
11667
|
-
aligned = np.zeros(num_classes)
|
|
11668
|
-
aligned[:min(arr.shape[0], num_classes)] = arr[:num_classes]
|
|
11669
|
-
arr = aligned
|
|
11670
|
-
valid_probs.append(arr)
|
|
11671
|
-
elif isinstance(p, np.ndarray):
|
|
11672
|
-
if p.shape[0] != num_classes:
|
|
11673
|
-
aligned = np.zeros(num_classes)
|
|
11674
|
-
aligned[:min(p.shape[0], num_classes)] = p[:num_classes]
|
|
11675
|
-
p = aligned
|
|
11676
|
-
valid_probs.append(p)
|
|
11677
11664
|
else:
|
|
11678
|
-
|
|
11679
|
-
|
|
11680
|
-
|
|
11681
|
-
|
|
11682
|
-
|
|
11665
|
+
raise Warning('[!] Data is None before batching!')
|
|
11666
|
+
|
|
11667
|
+
# safe final assembly with consistent shape
|
|
11668
|
+
valid_probs = []
|
|
11669
|
+
for i, p in enumerate(batch_probs):
|
|
11670
|
+
if p is None:
|
|
11683
11671
|
valid_probs.append(zero_row.copy())
|
|
11684
|
-
|
|
11685
|
-
|
|
11686
|
-
|
|
11687
|
-
|
|
11688
|
-
|
|
11689
|
-
|
|
11672
|
+
elif isinstance(p, list):
|
|
11673
|
+
arr = np.array(p, dtype=np.float64)
|
|
11674
|
+
if arr.shape[0] != num_classes:
|
|
11675
|
+
aligned = np.zeros(num_classes)
|
|
11676
|
+
aligned[:min(arr.shape[0], num_classes)] = arr[:num_classes]
|
|
11677
|
+
arr = aligned
|
|
11678
|
+
valid_probs.append(arr)
|
|
11679
|
+
elif isinstance(p, np.ndarray):
|
|
11680
|
+
if p.shape[0] != num_classes:
|
|
11681
|
+
aligned = np.zeros(num_classes)
|
|
11682
|
+
aligned[:min(p.shape[0], num_classes)] = p[:num_classes]
|
|
11683
|
+
p = aligned
|
|
11684
|
+
valid_probs.append(p)
|
|
11685
|
+
else:
|
|
11686
|
+
if output_memory is not None:
|
|
11687
|
+
print('[=] Unexpected Sample type in batch probability, Using previous memory to fill gaps in Samples Ambiguity')
|
|
11688
|
+
valid_probs.append(output_memory)
|
|
11689
|
+
else:
|
|
11690
|
+
print(f'[⚠️] Unexpected Sample type in batch_probs[{i}]: {type(p)} — using zeros to fill in valid probability')
|
|
11691
|
+
valid_probs.append(zero_row.copy())
|
|
11692
|
+
|
|
11693
|
+
try:
|
|
11694
|
+
return np.stack(valid_probs)
|
|
11695
|
+
except ValueError as e:
|
|
11696
|
+
print(f'[⚠️] Stack failed: {e} — shapes: {[p.shape for p in valid_probs]}')
|
|
11697
|
+
return valid_probs
|
|
11698
|
+
except Exception as e:
|
|
11699
|
+
print(f'[⚠️] Error occured in probabilities batching: {e}')
|
|
11700
|
+
return None
|
|
11690
11701
|
|
|
11691
11702
|
|
|
11692
11703
|
def hybrid_prediction(self, rules, input_ids, dataset, X=None, y=None, use_embedded=True):
|
|
@@ -11851,6 +11862,13 @@ class IntegratedPipeline:
|
|
|
11851
11862
|
self.temporary_id.append(self.agent_id)
|
|
11852
11863
|
id_history = self.temporary_id
|
|
11853
11864
|
|
|
11865
|
+
if input_ids is None and X is not None:
|
|
11866
|
+
logits = self.model3.forward(X)
|
|
11867
|
+
return self.model3._softmax(logits)
|
|
11868
|
+
|
|
11869
|
+
if input_ids is None and X is None:
|
|
11870
|
+
raise Warning('[!] X and input indices are None! cannot proceed with Batching probabilities!')
|
|
11871
|
+
|
|
11854
11872
|
if self.use_transformer:
|
|
11855
11873
|
is_batch = len(input_ids.shape) == 2 and input_ids.shape[0] > 1
|
|
11856
11874
|
else:
|
|
@@ -11910,8 +11928,11 @@ class IntegratedPipeline:
|
|
|
11910
11928
|
self.peer_assistance_threshold -= 0.2
|
|
11911
11929
|
print('[+] Both Models agree, Normalizing prediction with confidence boost...')
|
|
11912
11930
|
for i, target in enumerate(mlp_pred_indices):
|
|
11913
|
-
|
|
11914
|
-
|
|
11931
|
+
if i < len(probs):
|
|
11932
|
+
probs[i, target] = min(probs[i, target] * 1.2, 0.95)
|
|
11933
|
+
probs[i] /= probs[i].sum()
|
|
11934
|
+
else:
|
|
11935
|
+
probs /= probs.sum()
|
|
11915
11936
|
|
|
11916
11937
|
|
|
11917
11938
|
if not agreement and probs_memory is not None:
|
|
@@ -13229,6 +13250,59 @@ class IntegratedPipeline:
|
|
|
13229
13250
|
x = np.fromiter((v for v in clean_str.split() if v not in skip_values), dtype=float)
|
|
13230
13251
|
|
|
13231
13252
|
return x
|
|
13253
|
+
|
|
13254
|
+
def _validate_onehot(self, y_true, context="train()"):
|
|
13255
|
+
"""
|
|
13256
|
+
Robust one-hot validation for y_true, going beyond a simple .any() check.
|
|
13257
|
+
Catches: out-of-range values, negative values, non-binary floats,
|
|
13258
|
+
rows that don't sum to 1, and all-zero rows — each with a distinct,
|
|
13259
|
+
actionable error message instead of a generic failure.
|
|
13260
|
+
"""
|
|
13261
|
+
y_true = np.asarray(y_true, dtype=np.float64)
|
|
13262
|
+
|
|
13263
|
+
if y_true.ndim == 1:
|
|
13264
|
+
y_true = y_true[np.newaxis, :]
|
|
13265
|
+
|
|
13266
|
+
issues = []
|
|
13267
|
+
|
|
13268
|
+
# 1. Values outside [0, 1] — catches your [5,3,1,4,3,2] case directly
|
|
13269
|
+
out_of_range = (y_true < 0) | (y_true > 1)
|
|
13270
|
+
if out_of_range.any():
|
|
13271
|
+
bad_rows = np.where(out_of_range.any(axis=1))[0]
|
|
13272
|
+
issues.append(
|
|
13273
|
+
f"values outside [0,1] at rows {bad_rows.tolist()[:5]} "
|
|
13274
|
+
f"(sample values: {y_true[bad_rows[0]].tolist() if len(bad_rows) else []}) "
|
|
13275
|
+
f"— looks like raw label indices, not one-hot"
|
|
13276
|
+
)
|
|
13277
|
+
|
|
13278
|
+
# 2. Non-binary values (e.g. soft labels or corrupted floats like 0.5, 0.999999)
|
|
13279
|
+
# Only check this if values ARE in [0,1] — no point double-reporting.
|
|
13280
|
+
in_range = ~out_of_range
|
|
13281
|
+
non_binary = in_range & (~np.isclose(y_true, 0, atol=1e-6)) & (~np.isclose(y_true, 1, atol=1e-6))
|
|
13282
|
+
if non_binary.any():
|
|
13283
|
+
bad_rows = np.where(non_binary.any(axis=1))[0]
|
|
13284
|
+
issues.append(
|
|
13285
|
+
f"non-binary values at rows {bad_rows.tolist()[:5]} "
|
|
13286
|
+
f"(sample values: {y_true[bad_rows[0]].tolist() if len(bad_rows) else []}) "
|
|
13287
|
+
f"— expected exactly 0 or 1 per class slot"
|
|
13288
|
+
)
|
|
13289
|
+
|
|
13290
|
+
# 3. Row sums must be exactly 1 (each sample has exactly one true class)
|
|
13291
|
+
row_sums = y_true.sum(axis=1)
|
|
13292
|
+
bad_sum_rows = np.where(~np.isclose(row_sums, 1.0, atol=1e-3))[0]
|
|
13293
|
+
if len(bad_sum_rows) > 0:
|
|
13294
|
+
issues.append(
|
|
13295
|
+
f"rows not summing to 1 at indices {bad_sum_rows.tolist()[:5]} "
|
|
13296
|
+
f"(sums: {row_sums[bad_sum_rows[:5]].tolist()}) "
|
|
13297
|
+
f"— either multi-label rows, all-zero rows, or raw indices"
|
|
13298
|
+
)
|
|
13299
|
+
|
|
13300
|
+
if issues:
|
|
13301
|
+
print(f"[WARNING] [{context}] y_true failed one-hot validation, one-hot encoding y sample...")
|
|
13302
|
+
return True
|
|
13303
|
+
|
|
13304
|
+
return False
|
|
13305
|
+
|
|
13232
13306
|
|
|
13233
13307
|
def transformer_utilities(self, X_provided= None, X_raw=None, y_true=None, rules=None,
|
|
13234
13308
|
datasets=None, label_map=None, batch_size=2, min_signal=1e-3,
|
|
@@ -13262,7 +13336,7 @@ class IntegratedPipeline:
|
|
|
13262
13336
|
if X_provided is None:
|
|
13263
13337
|
sequence_inputs = self.sequence_encoding(datasets, label_map=label_map)
|
|
13264
13338
|
else:
|
|
13265
|
-
sequence_inputs = self._features_to_sequence(X_provided)
|
|
13339
|
+
sequence_inputs = self._features_to_sequence(X_provided, d_model=self.transformer_d_model)
|
|
13266
13340
|
|
|
13267
13341
|
unsuitable_training = self.training_necessary_condition(sequence_inputs, X_raw)
|
|
13268
13342
|
lr = self.model2.transformer_lr if self.model2 else self.transformer_lr
|
|
@@ -13335,7 +13409,7 @@ class IntegratedPipeline:
|
|
|
13335
13409
|
weak_rows = np.where(row_sums < min_signal)[0]
|
|
13336
13410
|
weak_ratio = len(weak_rows) / len(X_raw_features)
|
|
13337
13411
|
|
|
13338
|
-
print(f'[!] Zero ratio in samples: {weak_ratio * 100}')
|
|
13412
|
+
print(f'[!] Zero ratio in samples: {weak_ratio * 100}%')
|
|
13339
13413
|
if weak_ratio > 0.3: # more than 30% zero rows means vocab mismatch
|
|
13340
13414
|
if isinstance(X_raw_generation[0], str):
|
|
13341
13415
|
print(f'[= ! =] High zero-row ratio ({weak_ratio:.0%}), refitting on current batch')
|
|
@@ -13395,11 +13469,11 @@ class IntegratedPipeline:
|
|
|
13395
13469
|
n_heads=self.transformer_heads,
|
|
13396
13470
|
num_classes=n_classes
|
|
13397
13471
|
)
|
|
13472
|
+
|
|
13398
13473
|
if self.use_transformer:
|
|
13399
13474
|
self.model2.train(sequence_inputs, y_true, epochs=self.transformer_training_epochs, mode=mode, lr=lr, embedded=True, batch_size=batch_size)
|
|
13400
|
-
|
|
13401
|
-
X = self.shape_adaptation(hybrid_X, input_dim)
|
|
13402
|
-
|
|
13475
|
+
|
|
13476
|
+
X = self.shape_adaptation(hybrid_X, input_dim)
|
|
13403
13477
|
self.initialize_model_(X, input_dim, n_classes)
|
|
13404
13478
|
self.model3.train(X, y, epochs=self.mlp_training_epochs, lr=self.mlp_lr, max_samples_for_focused_fit=max_samples_for_focused_fit)
|
|
13405
13479
|
self.lstm_setup_inference(X, y, input_ids=sequence_inputs)
|
|
@@ -16252,10 +16326,12 @@ class PipelinePredictionManager:
|
|
|
16252
16326
|
|
|
16253
16327
|
# Forward pass through MLP
|
|
16254
16328
|
if hasattr(self.pipeline.mlp, 'predict_proba'):
|
|
16255
|
-
|
|
16329
|
+
if X_tfidf is None:
|
|
16330
|
+
X_tfidf = X
|
|
16331
|
+
mlp_probs = self.pipeline.model3.predict_proba(X)
|
|
16256
16332
|
else:
|
|
16257
16333
|
# Fallback if predict_proba not available
|
|
16258
|
-
logits = self.pipeline.
|
|
16334
|
+
logits = self.pipeline.model3.forward(X)
|
|
16259
16335
|
mlp_probs = self.pipeline._softmax(logits)
|
|
16260
16336
|
|
|
16261
16337
|
# Validate all MLP predictions at once
|
|
@@ -16560,7 +16636,7 @@ class PipelinePredictionManager:
|
|
|
16560
16636
|
else:
|
|
16561
16637
|
input_datasets = self.pipeline._features_to_sequence(X)
|
|
16562
16638
|
|
|
16563
|
-
pred_probs = self.pipeline.predict_proba(input_datasets, X_raw, type='Hybrid')[0]
|
|
16639
|
+
pred_probs = self.pipeline.predict_proba(input_datasets, X_raw, type='Hybrid', embedded=True)[0]
|
|
16564
16640
|
try:
|
|
16565
16641
|
pred_result = self.pipeline.hybrid_prediction(rules, input_datasets, datasets, X=X, y=y, use_embedded=True)
|
|
16566
16642
|
except:
|
|
@@ -16658,9 +16734,16 @@ class PipelinePredictionManager:
|
|
|
16658
16734
|
confidence = final_probs[i, class_idx]
|
|
16659
16735
|
else:
|
|
16660
16736
|
if isinstance(final_probs[i], (list, np.ndarray)):
|
|
16661
|
-
|
|
16737
|
+
if i < len(final_probs):
|
|
16738
|
+
confidence = final_probs[i][class_idx]
|
|
16739
|
+
else:
|
|
16740
|
+
confidence = np.mean(final_probs[class_idx])
|
|
16662
16741
|
else:
|
|
16663
|
-
|
|
16742
|
+
if i < len(final_probs):
|
|
16743
|
+
confidence = float(final_probs[i]) # Single value
|
|
16744
|
+
else:
|
|
16745
|
+
confidence = float(np.mean(final_probs))
|
|
16746
|
+
|
|
16664
16747
|
|
|
16665
16748
|
if confidence > best_confidence:
|
|
16666
16749
|
best_idx = i
|
|
@@ -17122,6 +17205,18 @@ class PipelinePredictionManager:
|
|
|
17122
17205
|
X_train, X_val, y_train, y_val = self._prepare_train_val_split(
|
|
17123
17206
|
X, y, min_val_per_class=5, min_frac=0.1, max_frac=0.3
|
|
17124
17207
|
)
|
|
17208
|
+
|
|
17209
|
+
onehot_validation = self.pipeline._validate_onehot(y_train)
|
|
17210
|
+
if onehot_validation:
|
|
17211
|
+
if num_classes != len(label_map):
|
|
17212
|
+
num_classes = len(label_map)
|
|
17213
|
+
if num_classes > np.max(y_train):
|
|
17214
|
+
y_train = np.eye(num_classes)[np.asarray(y_train)]
|
|
17215
|
+
y_val = np.eye(num_classes)[np.asarray(y_val)]
|
|
17216
|
+
else:
|
|
17217
|
+
print('[⚠️] Warning: Y onehot encoding fails, Returning y samples as is, This may cause Exploding Gradient in MLP Training!')
|
|
17218
|
+
y_train = y_train
|
|
17219
|
+
y_val = y_val
|
|
17125
17220
|
|
|
17126
17221
|
X_mean = X_train.mean(axis=0)
|
|
17127
17222
|
X_std = X_train.std(axis=0) + 1e-8
|
|
@@ -17197,7 +17292,7 @@ class PipelinePredictionManager:
|
|
|
17197
17292
|
AME = self.pipeline.model2.AME_Encoder(input_ids)
|
|
17198
17293
|
|
|
17199
17294
|
trans_probs, attn_weights = self.pipeline.model2.forward(input_ids, AME=AME, embedded=use_embedded)
|
|
17200
|
-
|
|
17295
|
+
|
|
17201
17296
|
else:
|
|
17202
17297
|
print("\n[⚡] Running MLP-only predictions")
|
|
17203
17298
|
print("[⚡] Note: Transformer not available, so Transformer results will be replaced with MLP results.")
|
|
@@ -17236,12 +17331,10 @@ class PipelinePredictionManager:
|
|
|
17236
17331
|
X = X_gen
|
|
17237
17332
|
if X is not None and len(X) > 0:
|
|
17238
17333
|
X = np.asarray(X)
|
|
17239
|
-
|
|
17240
|
-
X = np.asarray(X_val)
|
|
17241
|
-
|
|
17334
|
+
|
|
17242
17335
|
# MLP forward pass
|
|
17243
17336
|
if hasattr(self.pipeline.mlp, 'predict_proba'):
|
|
17244
|
-
mlp_probs = self.pipeline.
|
|
17337
|
+
mlp_probs = self.pipeline.model3.predict_proba(X)
|
|
17245
17338
|
else:
|
|
17246
17339
|
logits = self.pipeline.mlp.forward(X)
|
|
17247
17340
|
mlp_probs = self.pipeline._softmax(logits)
|
|
@@ -17257,7 +17350,7 @@ class PipelinePredictionManager:
|
|
|
17257
17350
|
# Replace invalid indices with argmax within valid range
|
|
17258
17351
|
for i in range(len(mlp_pred_indices)):
|
|
17259
17352
|
valid_probs = mlp_probs[i][:num_classes] if num_classes > 0 else mlp_probs[i]
|
|
17260
|
-
if len(valid_probs) > 0:
|
|
17353
|
+
if len(valid_probs) > 0 and i < len(mlp_pred_indices):
|
|
17261
17354
|
mlp_pred_indices[i] = int(np.argmax(valid_probs))
|
|
17262
17355
|
else:
|
|
17263
17356
|
mlp_pred_indices[i] = 0 # Default to first class
|