Stacking¶
Bayesian model stacking and ensemble prediction.
trade_study.stack_bayesian(compare_dict, *, method='stacking')
¶
Bayesian stacking via arviz.compare.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
compare_dict
|
dict[str, Any]
|
Dictionary mapping model names to arviz DataTree or ELPDData objects (must contain log_likelihood group). |
required |
method
|
str
|
Weighting method. One of "stacking", "BB-pseudo-BMA", "pseudo-BMA". |
'stacking'
|
Returns:
| Type | Description |
|---|---|
dict[str, float]
|
Dictionary mapping model names to stacking weights. |
Source code in src/trade_study/stacking.py
trade_study.stack_scores(score_matrix, *, maximize=False)
¶
Optimize stacking weights from a score matrix.
For non-Bayesian models where log-likelihoods aren't available. The objective is linear in the supplied model scores, so the solution puts weight only on models with the best mean score. Exactly equal computed best means split weight uniformly; near ties are not treated as equal. Positive changes of score units preserve the optimum, subject to floating precision. No iterative optimizer or SciPy dependency is needed. This does not optimize the score of a mixture distribution or the loss of an averaged prediction.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
score_matrix
|
NDArray[floating[Any]]
|
Non-empty finite array of shape (n_models, n_test_points). Each entry is the score of model i on test point j. |
required |
maximize
|
bool
|
If True, maximize the weighted score; if False, minimize. |
False
|
Returns:
| Type | Description |
|---|---|
NDArray[floating[Any]]
|
Non-negative float64 weights, shape (n_models,), summing to 1. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If scores are empty, non-finite, or not two-dimensional. |
FloatingPointError
|
If model means cannot be represented numerically. |
Examples:
>>> weights = stack_scores(np.array([[1.0, 1.0], [3.0, 3.0]]))
>>> weights.tolist()
[1.0, 0.0]
>>> stack_scores(1e6 * np.array([[1.0, 1.0], [3.0, 3.0]])).tolist()
[1.0, 0.0]
>>> stack_scores(np.array([[1.0], [1.0], [3.0]])).tolist()
[0.5, 0.5, 0.0]
Source code in src/trade_study/stacking.py
trade_study.stack_proportional(score_matrix, *, maximize=False, temperature=1.0)
¶
Weight models proportionally to exponential score utilities.
Mean scores are transformed using a direction-aware softmax. Near-tied models receive comparable weights in either direction, including when scores are zero or negative. These are heuristic ensemble weights, rather than Bayesian stacking weights or calibrated probabilities.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
score_matrix
|
NDArray[floating[Any]]
|
Finite array of shape (n_models, n_test_points). |
required |
maximize
|
bool
|
Whether higher scores are better. Default is minimize. |
False
|
temperature
|
float
|
Positive, finite scale in score units. Larger values spread weight more evenly; smaller values favor the best model. The default is 1.0. Scale this with the scores when changing their units to preserve the same weights. |
1.0
|
Returns:
| Type | Description |
|---|---|
NDArray[floating[Any]]
|
Non-negative float64 weights summing to 1, shape (n_models,). |
NDArray[floating[Any]]
|
Exactly equal mean scores receive uniform weights. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If scores are empty, non-finite, or not two-dimensional, or temperature is not positive and finite. |
Source code in src/trade_study/stacking.py
trade_study.ensemble_predict(predictions, weights)
¶
Weighted ensemble of model predictions.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
predictions
|
list[NDArray[floating[Any]]]
|
List of prediction arrays, one per model. Each should have the same shape. |
required |
weights
|
NDArray[floating[Any]]
|
Stacking weights, shape (n_models,). Normalization leaves the supplied array and its backing storage unchanged. Read-only inputs and views are supported. |
required |
Returns:
| Type | Description |
|---|---|
NDArray[floating[Any]]
|
Weighted average prediction array. |
Examples:
>>> import numpy as np
>>> predictions = [np.array([1.0, 2.0]), np.array([3.0, 4.0])]
>>> ensemble_predict(predictions, np.array([0.25, 0.75])).tolist()
[2.5, 3.5]
>>> weights = np.array([1.0, 3.0])
>>> weights.setflags(write=False)
>>> ensemble_predict(predictions, weights).tolist(), weights.tolist()
([2.5, 3.5], [1.0, 3.0])