AbstractIntegratedModule 1.0.9__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.
Files changed (23) hide show
  1. {abstractintegratedmodule-1.0.9 → abstractintegratedmodule-1.1.0}/AbstractIntegratedModule.egg-info/PKG-INFO +1 -1
  2. {abstractintegratedmodule-1.0.9 → abstractintegratedmodule-1.1.0}/AbstractIntegratedModule.py +83 -12
  3. {abstractintegratedmodule-1.0.9 → abstractintegratedmodule-1.1.0}/AbstractOptimizedModules.c +200 -200
  4. {abstractintegratedmodule-1.0.9 → abstractintegratedmodule-1.1.0}/PKG-INFO +1 -1
  5. {abstractintegratedmodule-1.0.9 → abstractintegratedmodule-1.1.0}/README.md +4 -4
  6. {abstractintegratedmodule-1.0.9 → abstractintegratedmodule-1.1.0}/pyproject.toml +1 -1
  7. {abstractintegratedmodule-1.0.9 → abstractintegratedmodule-1.1.0}/setup.py +1 -1
  8. {abstractintegratedmodule-1.0.9 → abstractintegratedmodule-1.1.0}/AbstractIntegratedModule.egg-info/SOURCES.txt +0 -0
  9. {abstractintegratedmodule-1.0.9 → abstractintegratedmodule-1.1.0}/AbstractIntegratedModule.egg-info/dependency_links.txt +0 -0
  10. {abstractintegratedmodule-1.0.9 → abstractintegratedmodule-1.1.0}/AbstractIntegratedModule.egg-info/requires.txt +0 -0
  11. {abstractintegratedmodule-1.0.9 → abstractintegratedmodule-1.1.0}/AbstractIntegratedModule.egg-info/top_level.txt +0 -0
  12. {abstractintegratedmodule-1.0.9 → abstractintegratedmodule-1.1.0}/AbstractOptimizedModules.pyx +0 -0
  13. {abstractintegratedmodule-1.0.9 → abstractintegratedmodule-1.1.0}/MANIFEST.in +0 -0
  14. {abstractintegratedmodule-1.0.9 → abstractintegratedmodule-1.1.0}/abstract_model_storage/Cargo.toml +0 -0
  15. {abstractintegratedmodule-1.0.9 → abstractintegratedmodule-1.1.0}/abstract_model_storage/pyproject.toml +0 -0
  16. {abstractintegratedmodule-1.0.9 → abstractintegratedmodule-1.1.0}/abstract_model_storage/src/lib.rs +0 -0
  17. {abstractintegratedmodule-1.0.9 → abstractintegratedmodule-1.1.0}/abstract_model_storage/target/debug/build/libsqlite3-sys-ed07b882cd2aa5e2/out/bindgen.rs +0 -0
  18. {abstractintegratedmodule-1.0.9 → abstractintegratedmodule-1.1.0}/abstract_model_storage/target/debug/build/serde_core-ebc15f2e9cad7f5f/out/private.rs +0 -0
  19. {abstractintegratedmodule-1.0.9 → abstractintegratedmodule-1.1.0}/abstract_model_storage/target/debug/build/target-lexicon-08527f45de28143d/out/host.rs +0 -0
  20. {abstractintegratedmodule-1.0.9 → abstractintegratedmodule-1.1.0}/abstract_model_storage/target/release/build/libsqlite3-sys-bf0400df4523274c/out/bindgen.rs +0 -0
  21. {abstractintegratedmodule-1.0.9 → abstractintegratedmodule-1.1.0}/abstract_model_storage/target/release/build/serde_core-5cdb76131825e4af/out/private.rs +0 -0
  22. {abstractintegratedmodule-1.0.9 → abstractintegratedmodule-1.1.0}/abstract_model_storage/target/release/build/target-lexicon-43eb95a0588bf457/out/host.rs +0 -0
  23. {abstractintegratedmodule-1.0.9 → abstractintegratedmodule-1.1.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: AbstractIntegratedModule
3
- Version: 1.0.9
3
+ Version: 1.1.0
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>
@@ -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
- # gradient clipping — clipped by value
1858
- np.clip(dW, -clip_value, clip_value, out=dW)
1859
- np.clip(db, -clip_value, clip_value, out=db)
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:
@@ -13242,6 +13250,59 @@ class IntegratedPipeline:
13242
13250
  x = np.fromiter((v for v in clean_str.split() if v not in skip_values), dtype=float)
13243
13251
 
13244
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
+
13245
13306
 
13246
13307
  def transformer_utilities(self, X_provided= None, X_raw=None, y_true=None, rules=None,
13247
13308
  datasets=None, label_map=None, batch_size=2, min_signal=1e-3,
@@ -13275,7 +13336,7 @@ class IntegratedPipeline:
13275
13336
  if X_provided is None:
13276
13337
  sequence_inputs = self.sequence_encoding(datasets, label_map=label_map)
13277
13338
  else:
13278
- sequence_inputs = self._features_to_sequence(X_provided)
13339
+ sequence_inputs = self._features_to_sequence(X_provided, d_model=self.transformer_d_model)
13279
13340
 
13280
13341
  unsuitable_training = self.training_necessary_condition(sequence_inputs, X_raw)
13281
13342
  lr = self.model2.transformer_lr if self.model2 else self.transformer_lr
@@ -13348,7 +13409,7 @@ class IntegratedPipeline:
13348
13409
  weak_rows = np.where(row_sums < min_signal)[0]
13349
13410
  weak_ratio = len(weak_rows) / len(X_raw_features)
13350
13411
 
13351
- print(f'[!] Zero ratio in samples: {weak_ratio * 100}')
13412
+ print(f'[!] Zero ratio in samples: {weak_ratio * 100}%')
13352
13413
  if weak_ratio > 0.3: # more than 30% zero rows means vocab mismatch
13353
13414
  if isinstance(X_raw_generation[0], str):
13354
13415
  print(f'[= ! =] High zero-row ratio ({weak_ratio:.0%}), refitting on current batch')
@@ -13408,11 +13469,11 @@ class IntegratedPipeline:
13408
13469
  n_heads=self.transformer_heads,
13409
13470
  num_classes=n_classes
13410
13471
  )
13472
+
13411
13473
  if self.use_transformer:
13412
13474
  self.model2.train(sequence_inputs, y_true, epochs=self.transformer_training_epochs, mode=mode, lr=lr, embedded=True, batch_size=batch_size)
13413
-
13414
- X = self.shape_adaptation(hybrid_X, input_dim)
13415
-
13475
+
13476
+ X = self.shape_adaptation(hybrid_X, input_dim)
13416
13477
  self.initialize_model_(X, input_dim, n_classes)
13417
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)
13418
13479
  self.lstm_setup_inference(X, y, input_ids=sequence_inputs)
@@ -17144,6 +17205,18 @@ class PipelinePredictionManager:
17144
17205
  X_train, X_val, y_train, y_val = self._prepare_train_val_split(
17145
17206
  X, y, min_val_per_class=5, min_frac=0.1, max_frac=0.3
17146
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
17147
17220
 
17148
17221
  X_mean = X_train.mean(axis=0)
17149
17222
  X_std = X_train.std(axis=0) + 1e-8
@@ -17258,9 +17331,7 @@ class PipelinePredictionManager:
17258
17331
  X = X_gen
17259
17332
  if X is not None and len(X) > 0:
17260
17333
  X = np.asarray(X)
17261
- if X_val is not None and len(X_val) > 0:
17262
- X = np.asarray(X_val)
17263
-
17334
+
17264
17335
  # MLP forward pass
17265
17336
  if hasattr(self.pipeline.mlp, 'predict_proba'):
17266
17337
  mlp_probs = self.pipeline.model3.predict_proba(X)