Module Design: Training Core¶
1. Responsibility¶
The training core defines objectives, split gain, leaf weights, tree structure, and
the boosting state machine. It depends only on abstract ComputeBackend, not
Python, Metal objects, cache paths, or the file system.
2. Single Mathematical Semantics¶
Squared error:
g_i = prediction_i - label_i
h_i = 1
score(G, H) = G² / (H + λ)
weight(G, H) = -G / (H + λ)
gain = 0.5 × (score_left + score_right - score_parent) - γ
3. Tree Model¶
Flat nodes contain feature index, threshold bin, left/right child indices, leaf value, gain, and flags. A flag distinguishes leaves; do not use special floating values. Validate all indices on creation and loading.
Stable tie-break order: 1. larger gain; 2. smaller feature index; 3. smaller threshold bin; 4. retain the first candidate when all other conditions are identical.
Even for nearby floating values, use frozen comparison rules and never thread
completion order. The frozen rule is strict FP64 gain >; enter feature/bin
tie-break only when bit-level results are equal, without scale-dependent epsilon.
Candidate gain must be strictly positive; zero or negative values remain leaves.
Binned values bin <= threshold_bin go left; all others go right.
Training parameters require min_samples_leaf >= 1, min_child_weight >= 0,
reg_lambda >= 0, and gamma >= 0; every floating parameter is finite. Both
children meet minimum samples, minimum Hessian, and strictly positive Hessian;
violating candidates never enter gain comparison.
4. Backend Interface¶
ComputeBackend
├── compute_gradients(...)
├── build_histograms(...)
├── update_predictions(...)
├── synchronize()
└── diagnostics()
5. State Machine¶
Created → Validated → Quantized → BackendReady
→ Iterating → ModelFinalized → Completed
↘ Failed
Failed must not export a model;
- the estimator atomically receives a model only after Completed;
- the training session owns all temporary resources and uniformly releases exception paths.
6. Tree Growth¶
Version 0.2.0 grows depth-limited trees level by level: 1. obtain active nodes in the current level; 2. build node histograms; 3. select splits by stable rules; 4. check minimum samples and Hessian; 5. partition samples; 6. create the next level or freeze leaves; 7. update training predictions after the tree completes.
The level-wise strategy facilitates batching multiple nodes and is the sole default strategy; do not retain another unspecified depth-first production path.
7. CPU Oracle¶
The CPU backend prioritizes clarity and determinism and accumulates FP64 as the
oracle. It is not a hidden fallback. After a user chooses mps, unavailable
backends fail; the core may let CPU handle control flow by specified policy, but must
not replace the entire GPU hot path and still report successful mps.
The CPU histogram accumulates each bin's count/G/H in supplied row-index order,
and tree nodes are written breadth-first to a flat array. Tree-growth control flow
exists only in core; the CPU backend builds histograms only and must not copy split
selection, partitioning, or node assembly.
8. Acceptance¶
- Hand-calculated small trees agree node by node;
- prediction updates across multiple boosting rounds are correct;
- repeated training with identical parameters satisfies deterministic constraints;
- backend exceptions do not produce partial models;
- core tests need neither Python nor a real GPU; GPU integration is verified separately with real hardware.