AbstractIntegratedModule 1.1.5__tar.gz → 1.1.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.
Files changed (23) hide show
  1. {abstractintegratedmodule-1.1.5 → abstractintegratedmodule-1.1.6}/AbstractIntegratedModule.egg-info/PKG-INFO +1 -1
  2. {abstractintegratedmodule-1.1.5 → abstractintegratedmodule-1.1.6}/AbstractIntegratedModule.py +165 -67
  3. {abstractintegratedmodule-1.1.5 → abstractintegratedmodule-1.1.6}/AbstractOptimizedModules.c +1173 -1164
  4. {abstractintegratedmodule-1.1.5 → abstractintegratedmodule-1.1.6}/AbstractOptimizedModules.pyx +6 -4
  5. {abstractintegratedmodule-1.1.5 → abstractintegratedmodule-1.1.6}/PKG-INFO +1 -1
  6. {abstractintegratedmodule-1.1.5 → abstractintegratedmodule-1.1.6}/README.md +79 -9
  7. {abstractintegratedmodule-1.1.5 → abstractintegratedmodule-1.1.6}/pyproject.toml +1 -1
  8. {abstractintegratedmodule-1.1.5 → abstractintegratedmodule-1.1.6}/setup.py +1 -1
  9. {abstractintegratedmodule-1.1.5 → abstractintegratedmodule-1.1.6}/AbstractIntegratedModule.egg-info/SOURCES.txt +0 -0
  10. {abstractintegratedmodule-1.1.5 → abstractintegratedmodule-1.1.6}/AbstractIntegratedModule.egg-info/dependency_links.txt +0 -0
  11. {abstractintegratedmodule-1.1.5 → abstractintegratedmodule-1.1.6}/AbstractIntegratedModule.egg-info/requires.txt +0 -0
  12. {abstractintegratedmodule-1.1.5 → abstractintegratedmodule-1.1.6}/AbstractIntegratedModule.egg-info/top_level.txt +0 -0
  13. {abstractintegratedmodule-1.1.5 → abstractintegratedmodule-1.1.6}/MANIFEST.in +0 -0
  14. {abstractintegratedmodule-1.1.5 → abstractintegratedmodule-1.1.6}/abstract_model_storage/Cargo.toml +0 -0
  15. {abstractintegratedmodule-1.1.5 → abstractintegratedmodule-1.1.6}/abstract_model_storage/pyproject.toml +0 -0
  16. {abstractintegratedmodule-1.1.5 → abstractintegratedmodule-1.1.6}/abstract_model_storage/src/lib.rs +0 -0
  17. {abstractintegratedmodule-1.1.5 → abstractintegratedmodule-1.1.6}/abstract_model_storage/target/debug/build/libsqlite3-sys-ed07b882cd2aa5e2/out/bindgen.rs +0 -0
  18. {abstractintegratedmodule-1.1.5 → abstractintegratedmodule-1.1.6}/abstract_model_storage/target/debug/build/serde_core-ebc15f2e9cad7f5f/out/private.rs +0 -0
  19. {abstractintegratedmodule-1.1.5 → abstractintegratedmodule-1.1.6}/abstract_model_storage/target/debug/build/target-lexicon-08527f45de28143d/out/host.rs +0 -0
  20. {abstractintegratedmodule-1.1.5 → abstractintegratedmodule-1.1.6}/abstract_model_storage/target/release/build/libsqlite3-sys-bf0400df4523274c/out/bindgen.rs +0 -0
  21. {abstractintegratedmodule-1.1.5 → abstractintegratedmodule-1.1.6}/abstract_model_storage/target/release/build/serde_core-5cdb76131825e4af/out/private.rs +0 -0
  22. {abstractintegratedmodule-1.1.5 → abstractintegratedmodule-1.1.6}/abstract_model_storage/target/release/build/target-lexicon-43eb95a0588bf457/out/host.rs +0 -0
  23. {abstractintegratedmodule-1.1.5 → abstractintegratedmodule-1.1.6}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: AbstractIntegratedModule
3
- Version: 1.1.5
3
+ Version: 1.1.6
4
4
  Summary: Integrated Pipeline with Specialized Non-LLM AI Agent Framework for ARM64 architecture
5
5
  Author: Micro-Novelty
6
6
  Author-email: Micro-Novelty <hernikpuspita5@gmail.com>
@@ -2981,7 +2981,7 @@ class LSTMEngine:
2981
2981
  boundaries = np.percentile(non_dominant, percentiles)
2982
2982
 
2983
2983
  if labels is None:
2984
- labels = ["Base"] + [f"Level_{i+1}" for i in range(n_bins-1)]
2984
+ labels = ["Base"] + [f"Level_{i+1}" for i in range(n_bins-1)]
2985
2985
 
2986
2986
  base_lo = float(value_range[0]) if value_range else -1e-6
2987
2987
  bins = {"Base": (base_lo, float(boundaries[0]))}
@@ -3584,6 +3584,7 @@ class WeightedEnsemblePredictor:
3584
3584
  def _dynamic_weighted_ensemble(self, trans_probs, mlp_probs, attn_weights,
3585
3585
  input_ids, lstm_probs=None, lstm_weight_hint=0.0):
3586
3586
  # normalize all inputs to guaranteed 2D float64
3587
+ mean_pred_counts = np.mean(self.pipeline.model3.pred_counts)
3587
3588
  try:
3588
3589
  trans_probs = np.asarray(trans_probs, dtype=np.float64)
3589
3590
  mlp_probs = np.asarray(mlp_probs, dtype=np.float64)
@@ -3635,7 +3636,8 @@ class WeightedEnsemblePredictor:
3635
3636
  np.ascontiguousarray(lstm_probs),
3636
3637
  np.ascontiguousarray(lstm_weight_hints),
3637
3638
  float(self.pipeline.confidence_threshold),
3638
- has_lstm
3639
+ has_lstm,
3640
+ mean_pred_counts
3639
3641
  )
3640
3642
  except Exception as e:
3641
3643
  print(f'[=] Error in optimized dynamic weighted ensemble: {e}, using regular dynamic ensemble method.')
@@ -3666,7 +3668,7 @@ class WeightedEnsemblePredictor:
3666
3668
  mlp_cf = 1.0 / (1.0 + mlp_entropy)
3667
3669
 
3668
3670
  tw = trans_cf * (1.0 + agreement) / 2.0
3669
- mw = mlp_cf * (1.0 + agreement) / 2.0
3671
+ mw = mlp_cf * mean_pred_counts * (1.0 + agreement) / 2.0
3670
3672
 
3671
3673
  if has_lstm:
3672
3674
  lstm_row = np.zeros(n_classes)
@@ -3693,6 +3695,7 @@ class WeightedEnsemblePredictor:
3693
3695
 
3694
3696
 
3695
3697
  def _attention_weighted_ensemble(self, trans_probs, mlp_probs, attn_weights):
3698
+ mean_pred_counts = np.mean(self.pipeline.model3.pred_counts)
3696
3699
  if attn_weights is None:
3697
3700
  return (trans_probs + mlp_probs) / 2
3698
3701
 
@@ -3730,12 +3733,12 @@ class WeightedEnsemblePredictor:
3730
3733
  trans_trust = attn_limit * (1.0 - anisotropy)
3731
3734
 
3732
3735
  # MLP gets the rest
3733
- mlp_trust = 1.0 - trans_trust
3736
+ mlp_trust = (1.0 - trans_trust) * mean_pred_counts
3734
3737
 
3735
3738
  try:
3736
- ensemble[i] = trans_trust * trans_row + mlp_trust * mlp_row
3739
+ ensemble[i] = trans_trust * trans_row + mlp_trust * mlp_row
3737
3740
  except:
3738
- ensemble = trans_trust * trans_row + mlp_trust * mlp_row
3741
+ ensemble = trans_trust * trans_row + mlp_trust * mlp_row
3739
3742
 
3740
3743
  return ensemble
3741
3744
 
@@ -4207,7 +4210,7 @@ class ExplainabilityModule:
4207
4210
  if choice.lower() == 'skip':
4208
4211
  return None
4209
4212
  elif choice.lower() == 'explain':
4210
- print(explanation)
4213
+ print(f"Explanation: {explanation}")
4211
4214
  return self._ask_for_feedback(text, result, explanation)
4212
4215
  elif choice == '4':
4213
4216
  history = self.get_decision_history(limit=10)
@@ -4255,11 +4258,11 @@ class ExplainabilityModule:
4255
4258
  if zero_ratio > threshold:
4256
4259
  print(f'[!] {len(zero_rows)} zero rows ({zero_ratio:.0%}), refitting on current batch')
4257
4260
  if isinstance(texts, str):
4258
- self.tfidf.fit(texts)
4259
- X_features = self.tfidf.transform(texts).toarray()
4261
+ self.tfidf.fit([texts])
4262
+ X_features = self.tfidf.transform([texts]).toarray()
4260
4263
  elif isinstance(texts[0], str):
4261
- self.tfidf.fit(texts[0])
4262
- X_features = self.tfidf.transform(texts[0]).toarray()
4264
+ self.tfidf.fit([texts[0]])
4265
+ X_features = self.tfidf.transform([texts[0]]).toarray()
4263
4266
  else:
4264
4267
  X_features = X_features
4265
4268
 
@@ -4482,10 +4485,10 @@ class ExplainabilityModule:
4482
4485
 
4483
4486
  if mlp_conf > trans_conf:
4484
4487
  final_pred = mlp_pred
4485
- final_conf = mlp_conf * (1.0 - trans_conf) * (1.0 - np.mean(AAT)) + eps
4488
+ consensus_conf = mlp_conf * (1.0 - trans_conf) * (1.0 - np.mean(AAT)) + eps
4486
4489
  else:
4487
4490
  final_pred = trans_pred
4488
- final_conf = trans_conf * (1.0 - mlp_conf) * np.mean(AAT) + eps
4491
+ consensus_conf = trans_conf * (1.0 - mlp_conf) * np.mean(AAT) + eps
4489
4492
 
4490
4493
  print('='*50)
4491
4494
  print('===== ABSTRACTION LAYER ======')
@@ -4495,10 +4498,12 @@ class ExplainabilityModule:
4495
4498
  print(f'[= ABSTRACTION =] Sigmoid growth of Attention weight consistency: {np.std(sigmoid_growth)}')
4496
4499
  print('[=] Note: Very little Consistency meaning Transformer attention quality is Healthy and focused')
4497
4500
 
4498
- if isinstance(final_conf, np.ndarray):
4499
- final_conf = 1.0 / (1.0 + np.exp(-final_conf))
4501
+ if isinstance(consensus_conf, np.ndarray):
4502
+ consensus_conf = 1.0 / (1.0 + np.exp(-final_conf))
4500
4503
  # Apply a sigmoid transformation to ensure the confidence is between 0 and 1
4501
4504
 
4505
+ # averaged all confidences to get the final confidence.
4506
+ final_conf = mlp_conf + trans_conf + final_conf / 3
4502
4507
  if np.isnan(final_conf).any() or np.isinf(final_conf).any():
4503
4508
  final_conf = self.pipeline.confidence_threshold
4504
4509
 
@@ -9584,6 +9589,7 @@ class IntegratedPipeline:
9584
9589
  self.max_size = 500
9585
9590
  self.error_decay = 0.85
9586
9591
  self.performance_result = 1.0
9592
+ self.max_ram_allowed = 150
9587
9593
 
9588
9594
  # === TRAINING SETUP ===
9589
9595
  self.mlp_training_epochs = 1000
@@ -12168,11 +12174,11 @@ class IntegratedPipeline:
12168
12174
  if zero_ratio > threshold:
12169
12175
  print(f'[!] {len(zero_rows)} zero rows ({zero_ratio:.0%}), refitting on current batch')
12170
12176
  if isinstance(texts, str):
12171
- self.tfidf.fit(texts)
12172
- X_features = self.tfidf.transform(texts).toarray()
12177
+ self.tfidf.fit([texts])
12178
+ X_features = self.tfidf.transform([texts]).toarray()
12173
12179
  elif isinstance(texts[0], str):
12174
- self.tfidf.fit(texts[0])
12175
- X_features = self.tfidf.transform(texts[0]).toarray()
12180
+ self.tfidf.fit([texts[0]])
12181
+ X_features = self.tfidf.transform([texts[0]]).toarray()
12176
12182
  else:
12177
12183
  X_features = X_features
12178
12184
 
@@ -12418,33 +12424,6 @@ class IntegratedPipeline:
12418
12424
  pass
12419
12425
 
12420
12426
 
12421
- def utility_MLP_set(self, X, y):
12422
- if not self.autonomous:
12423
- try:
12424
- joblib.dump(self.mlp, 'analyzer_model.pkl')
12425
- joblib.dump(self.model2, 'analyzer_agent.pkl')
12426
- print("🎉 Model trained and saved!")
12427
- except Exception as e:
12428
- print(f'|| Failed to joblib dump file! : {e}, User Manual filepath suggestion needed...')
12429
-
12430
- permission = input('|| Insert Filepath? [Y/N]: ')
12431
- if permission == 'Y':
12432
- suggested_path = input('|| Filepath suggestion: ')
12433
- if suggested_path:
12434
- self.safe_pickle_save_with_feedback(self.mlp, suggested_path)
12435
- self.safe_pickle_save_with_feedback(self.model2, suggested_path)
12436
- print(" || Model saved!")
12437
- else:
12438
- print('|| Failed to dump Your model! ')
12439
- pass
12440
- else:
12441
- print('|| Failed to dump Your model! ')
12442
- pass
12443
-
12444
- else:
12445
- pass
12446
-
12447
-
12448
12427
  def auto_generate_labels_from_texts(self, rules, texts):
12449
12428
  y_raw = []
12450
12429
  self.rules = rules
@@ -13065,7 +13044,7 @@ class IntegratedPipeline:
13065
13044
  is in that sample's OWN true class — used as a genuine continuous
13066
13045
  LSTM training target instead of the raw class index.
13067
13046
 
13068
- X : hybrid_X after shape_adaptation — same format self.mlp
13047
+ X : hybrid_X after shape_adaptation — same format self.mlp
13069
13048
  (self.model3) and self.model3.train() already consume.
13070
13049
  Y : raw class indices, shape (n_samples,) or (n_samples, 1)
13071
13050
  input_ids : sequence_inputs — same format self.model2 (Transformer)
@@ -13073,7 +13052,7 @@ class IntegratedPipeline:
13073
13052
  confidence is used if not provided or Transformer
13074
13053
  is unavailable.
13075
13054
 
13076
- Returns : (n_samples,) float64 array, each value in (eps, 1.0]
13055
+ Returns : (n_samples,) float64 array, each value in (eps, 1.0]
13077
13056
  — never exactly 0, to avoid degenerate regression
13078
13057
  targets downstream (consistent with the eps-floor
13079
13058
  pattern used elsewhere in this codebase).
@@ -13150,8 +13129,9 @@ class IntegratedPipeline:
13150
13129
  sample_confs.append(float(mlp_probs[i, true_class]))
13151
13130
  else:
13152
13131
  print(f'[⚠️] Sample {i}: true_class={true_class} out of '
13153
- f'range for MLP output width {n_cls} — skipping '
13132
+ f'range for MLP output width {n_cls} — skipping Most '
13154
13133
  f'MLP contribution for this sample')
13134
+ sample_confs.append(float(mlp_probs[i, n_cls - 1]))
13155
13135
 
13156
13136
  if trans_probs is not None:
13157
13137
  n_cls = trans_probs.shape[1]
@@ -13160,7 +13140,8 @@ class IntegratedPipeline:
13160
13140
  else:
13161
13141
  print(f'[⚠️] Sample {i}: true_class={true_class} out of '
13162
13142
  f'range for Transformer output width {n_cls} — '
13163
- f'skipping Transformer contribution for this sample')
13143
+ f'skipping Most Transformer contribution for this sample')
13144
+ sample_confs.append(float(trans_probs[i, n_cls - 1]))
13164
13145
 
13165
13146
  if sample_confs:
13166
13147
  confidences[i] = max(np.mean(sample_confs), eps)
@@ -13461,7 +13442,7 @@ class IntegratedPipeline:
13461
13442
  sequence_inputs = np.where(flat_mask, sequence_inputs + noise, sequence_inputs)
13462
13443
 
13463
13444
  # ---- 6. Hard safety net: guarantee finite output no matter what happened above ----
13464
- if not np.isfinite(sequence_inputs).all():
13445
+ if not np.isfinite(sequence_inputs).all() or not np.isfinite(sequence_inputs.std(axis=-1)).all():
13465
13446
  n_bad = (~np.isfinite(sequence_inputs)).sum()
13466
13447
  print(f"[!] _features_to_sequence: FINAL sanitize caught {n_bad} non-finite values "
13467
13448
  f"(this should be rare — investigate if it triggers often)")
@@ -13473,6 +13454,7 @@ class IntegratedPipeline:
13473
13454
 
13474
13455
  return sequence_inputs
13475
13456
 
13457
+
13476
13458
  def _sanitize_string_chars(self, x):
13477
13459
  if isinstance(x, (str, np.str_)):
13478
13460
  clean_str = str(x).replace('[', '').replace(']', '').replace('...', '').strip()
@@ -13538,11 +13520,63 @@ class IntegratedPipeline:
13538
13520
 
13539
13521
  return False
13540
13522
 
13523
+ def _should_train_transformer(self, sequence_inputs, X_raw,
13524
+ min_seq_len=3, min_anisotropy=0.35,
13525
+ min_samples=10, ram_headroom_mb=80):
13526
+ """
13527
+ Decides whether Transformer training is worth its RAM/compute cost
13528
+ for THIS data, reusing existing AME/anisotropy signals rather than
13529
+ adding new expensive computation. Built specifically for
13530
+ memory-constrained edge deployment (e.g. Raspberry Pi Zero).
13531
+
13532
+ Returns (should_train: bool, reason: str) so callers can log why should_train.
13533
+
13534
+ """
13535
+ sequence_inputs = np.asarray(sequence_inputs)
13536
+ n_samples = sequence_inputs.shape[0] if sequence_inputs.ndim > 0 else 0
13537
+ T = sequence_inputs.shape[1] if sequence_inputs.ndim > 1 else 1
13538
+
13539
+ # ── Check 1: sample count ────────────────────────────────
13540
+ if n_samples < min_samples:
13541
+ return False, (f'only {n_samples} samples (need >= {min_samples}) — '
13542
+ f'too little data to justify Transformer parameter count')
13543
+
13544
+ # ── Check 2: sequence length ─────────────────────────────
13545
+ if T < min_seq_len:
13546
+ return False, (f'sequence length T={T} (need >= {min_seq_len}) — '
13547
+ f'attention has too few positions to model '
13548
+ f'meaningful relationships')
13549
+
13550
+ # ── Check 3: anisotropy ──
13551
+ # ── zero new computation cost ──
13552
+ anisotropy = self.anisotropy_measurement(sequence_inputs)
13553
+ if anisotropy < min_anisotropy:
13554
+ return False, (f'anisotropy={anisotropy:.4f} (need >= {min_anisotropy}) — '
13555
+ f'data lacks directional/sequential structure; '
13556
+ f'MLP alone is the appropriate model for this '
13557
+ f'geometry (same finding as make_moons earlier)')
13558
+
13559
+ # ── Check 4: RAM headrooms, optional, graceful if unavailable ──
13560
+ if ram_headroom_mb is not None:
13561
+ try:
13562
+ available_mb = psutil.virtual_memory().available / (1024 * 1024)
13563
+ if available_mb < ram_headroom_mb:
13564
+ return False, (f'only {available_mb:.0f}MB RAM available '
13565
+ f'(need >= {ram_headroom_mb}MB headroom) — '
13566
+ f'skipping Transformer to protect device stability')
13567
+ except ImportError:
13568
+ pass # psutil not installed — skip memory check silently,
13569
+
13570
+
13571
+ return True, (f'n={n_samples}, T={T}, anisotropy={anisotropy:.4f} — '
13572
+ f'sufficient structure and data to justify Transformer training')
13541
13573
 
13542
13574
  def transformer_utilities(self, X_provided= None, X_raw=None, y_true=None, rules=None,
13543
13575
  datasets=None, label_map=None, batch_size=2, min_signal=1e-3,
13544
- max_samples_for_focused_fit=500):
13576
+ max_samples_for_focused_fit=500, max_ram_used=80):
13545
13577
  unsuitable = False
13578
+ max_ram_used = self.max_ram_allowed if max_ram_used is None else max_ram_used
13579
+
13546
13580
  if X_provided is not None:
13547
13581
  X_raw = X_provided
13548
13582
 
@@ -13721,13 +13755,14 @@ class IntegratedPipeline:
13721
13755
  n_heads=self.transformer_heads,
13722
13756
  num_classes=n_classes
13723
13757
  )
13724
-
13725
- if self.use_transformer:
13758
+
13759
+ should_train_transformer, reason = self._should_train_transformer(sequence_inputs, X_raw, min_seq_len=3, min_anisotropy=0.35, min_samples=10, ram_headroom_mb=max_ram_used)
13760
+ if self.use_transformer and should_train_transformer:
13761
+ print(f'[=] Transformer Training allowed, Reason: {reason}')
13726
13762
  self.model2.train(sequence_inputs, y_true, epochs=self.transformer_training_epochs, mode=mode, lr=lr, embedded=True, batch_size=batch_size)
13727
13763
 
13728
13764
  X = self.shape_adaptation(hybrid_X, input_dim)
13729
13765
 
13730
-
13731
13766
  self.initialize_model_(X, input_dim, n_classes)
13732
13767
  if not unsuitable:
13733
13768
  self.model3.train(X, y, epochs=self.mlp_training_epochs, lr=self.mlp_lr, max_samples_for_focused_fit=max_samples_for_focused_fit)
@@ -13798,8 +13833,7 @@ class IntegratedPipeline:
13798
13833
  print(f"\n🚀 Separate Modular MLP Pipeline:")
13799
13834
  print(f" Samples: {len(self.X)}")
13800
13835
 
13801
- y_true = self.initialize_model_encoding(self.X, y_raw)
13802
- self.utility_MLP_set(self.X, y_true)
13836
+ y_true = self.initialize_model_encoding(self.X, y_raw)
13803
13837
  print('✅ Done Training MLP Model! ')
13804
13838
 
13805
13839
 
@@ -17465,6 +17499,51 @@ class PipelinePredictionManager:
17465
17499
 
17466
17500
  return need_ensemble
17467
17501
 
17502
+ def _check_for_transformer_sequences(self, sequence_inputs, min_seq_len=3,
17503
+ min_samples=10, min_AME=0.5, min_anisotropy=0.5):
17504
+ score = 0
17505
+ sequence_inputs = np.asarray(sequence_inputs)
17506
+ n_samples = sequence_inputs.shape[0] if sequence_inputs.ndim > 0 else 0
17507
+ T = sequence_inputs.shape[1] if sequence_inputs.ndim > 1 else 1
17508
+
17509
+ # ── Check 1: sample count ────────────────────────────────
17510
+ if n_samples < min_samples:
17511
+ score += 1
17512
+ print(f'[=] only {n_samples} samples (need >= {min_samples}) — '
17513
+ f'too little data to justify Transformer parameter count')
17514
+
17515
+ # ── Check 2: sequence length ─────────────────────────────
17516
+ if T < min_seq_len:
17517
+ score += 1
17518
+ print(f'[=] sequence length T={T} (need >= {min_seq_len}) — '
17519
+ f'attention has too few positions to model '
17520
+ f'meaningful relationships')
17521
+
17522
+ # ── Check 3: anisotropy ──
17523
+ # ── zero new computation cost ──
17524
+ anisotropy = self.pipeline.anisotropy_measurement(sequence_inputs)
17525
+ if anisotropy < min_anisotropy:
17526
+ score += 1
17527
+ print(f'[=] anisotropy={anisotropy:.4f} (need >= {min_anisotropy}) — '
17528
+ f'data lacks directional/sequential structure; '
17529
+ f'MLP alone is the appropriate model for this '
17530
+ f'geometry.')
17531
+
17532
+
17533
+ AME = self.pipeline.AME_Encoder(sequence_inputs)
17534
+ if AME > min_AME:
17535
+ score += 1
17536
+ print(f'[=] Result of Abstract Modelling Error is High, Complexity in samples is High.')
17537
+
17538
+ error_counts = np.mean(self.pipeline.model3.error_counts)
17539
+ if error_counts > 0.5:
17540
+ score += 1
17541
+ print('[=] MLP Experienced lots of Errors, Considering to use Transformer Prediction.')
17542
+
17543
+ propriate_single_transformer = score == 5
17544
+ print(f'[+] Transformer Prediction allowed: {propriate_single_transformer}')
17545
+ return propriate_single_transformer
17546
+
17468
17547
  def advanced_prediction_method(self, titles=None, label_map=None, rules=None,
17469
17548
  X=None, y=None,
17470
17549
  show_proba=False, top_k=3,
@@ -17493,8 +17572,10 @@ class PipelinePredictionManager:
17493
17572
 
17494
17573
  X_gen = None
17495
17574
  sec_chosen_label = None
17575
+
17496
17576
  sec_confidence = 0.0
17497
17577
  final_confidence = 0.0
17578
+ min_signal = 1e-3
17498
17579
 
17499
17580
  correct = 0
17500
17581
  sec_correct= 0
@@ -17586,9 +17667,18 @@ class PipelinePredictionManager:
17586
17667
 
17587
17668
  if dataset is not None:
17588
17669
  input_ids, _ = self.pipeline.input_encoding(dataset)
17670
+ elif dataset is not None and X_train is not None:
17671
+ input_ids, _ = self.pipeline.input_encoding(dataset)
17672
+ row_sums = input_ids.sum(axis=1)
17673
+ weak_rows = np.where(row_sums < min_signal)[0]
17674
+ weak_ratio = len(weak_rows) / len(input_ids)
17675
+ if weak_ratio > 0.3:
17676
+ print(f'[=] Zero rows abundant in Input indices: {weak_ratio:.1%}, using input indices from X samples...')
17677
+ input_ids = self.pipeline._features_to_sequence(X_train)
17589
17678
  else:
17590
17679
  input_ids = self.pipeline._features_to_sequence(X_train)
17591
17680
 
17681
+
17592
17682
  if len(input_ids) == 0:
17593
17683
  print('[⚠️] input_encoding produced no samples — skipping '
17594
17684
  'transformer training/prediction for this call and transformer results will be Replaced by MLP or LSTM.')
@@ -17980,12 +18070,20 @@ class PipelinePredictionManager:
17980
18070
 
17981
18071
  else:
17982
18072
  print("[=] Initiating Continuous sample prediction without Titles.")
17983
- n_samples = mlp_probs.shape[0]
18073
+
18074
+ transformer_takes = self._check_for_transformer_sequences(input_ids, min_seq_len=3,
18075
+ min_samples=10, min_AME=0.5, min_anisotropy=0.5)
18076
+ if not transformer_takes:
18077
+ n_samples = mlp_probs.shape[0]
18078
+ chosen_probs = mlp_probs.copy()
18079
+ else:
18080
+ n_samples = trans_probs.shape[0]
18081
+ chosen_probs = trans_probs.copy()
17984
18082
 
17985
18083
  lstm_pred_indices = np.argmax(lstm_probs, axis=1) if lstm_probs is not None else None
17986
18084
  for i in range(n_samples):
17987
18085
  outcome = self._compute_sample_prediction(
17988
- i, mlp_probs, target_probs, target_pred_indices,
18086
+ i, chosen_probs, target_probs, target_pred_indices,
17989
18087
  trans_probs=trans_probs, lstm_probs=lstm_probs,
17990
18088
  lstm_pred_indices=lstm_pred_indices,
17991
18089
  attn_weights=attn_weights, input_ids=input_ids,
@@ -18066,14 +18164,6 @@ class PipelinePredictionManager:
18066
18164
  confidence = (confidence + trans_confidence / 2) + 1e-5
18067
18165
  print(f'[=] Calibrating confidence around: {confidence:.1%}')
18068
18166
 
18069
- if isinstance(chosen_label, str) and chosen_label.startswith("unknown") or float(confidence) < self.pipeline.confidence_threshold:
18070
- if chosen_label is None or chosen_label.startswith('unknown'):
18071
- chosen_label = 'Unknown'
18072
- confidence = 1.0 - confidence #Invert confidence for unknown class
18073
- print(f"\n[⚠️] Final prediction is {chosen_label} with uncertain confidence: {confidence:.1%}. Consider more consistent data for the model to learn from.")
18074
- else:
18075
- print(f"\n[🎯] Predicted label: {chosen_label} || With Certain Confidence: {confidence:.1%}")
18076
-
18077
18167
  payload = {
18078
18168
  'X_samples': X,
18079
18169
  'input_ids': input_ids
@@ -18082,6 +18172,14 @@ class PipelinePredictionManager:
18082
18172
  if titles is not None and len(titles) > 0:
18083
18173
  correct, sec_correct = self.display_hybrid_results(payload, final_class_idx, results, top_k, verbose=True)
18084
18174
 
18175
+ if isinstance(chosen_label, str) and chosen_label.startswith("unknown") or float(confidence) < self.pipeline.confidence_threshold:
18176
+ if chosen_label is None or chosen_label.startswith('unknown'):
18177
+ chosen_label = 'Unknown'
18178
+ confidence = 1.0 - confidence #Invert confidence for unknown class
18179
+ print(f"\n[⚠️] Final prediction is {chosen_label} with uncertain confidence: {confidence:.1%}. Consider more consistent data for the model to learn from.")
18180
+ else:
18181
+ print(f"\n[🎯] Predicted label: {chosen_label} || With Certain Confidence: {confidence:.1%}")
18182
+
18085
18183
  return results, chosen_label, confidence
18086
18184
 
18087
18185
  else: