Regression Combiners
Regression combiners are the C-Step strategies that turn the F-Step prediction matrix into one final numeric prediction.
The C-Step receives:
where each row is one sample and each column is the prediction produced by one divergence-specific F-Step model family.
Conceptually:
F-Step predictions
│
▼
┌──────────────────────────────┐
│ euclidean gkl logistic ... │
├──────────────────────────────┤
│ 12.4 12.8 12.1 │
│ 20.7 21.0 20.4 │
│ 8.3 8.1 8.5 │
└──────────────────────────────┘
│
▼
regression combiner
│
▼
final prediction
The current source registers five regression combiners:
| Registry name | Implementation |
|---|---|
mean |
MeanCombiner |
weighted_mean |
WeightedMeanCombiner |
stacking_regressor |
StackingRegressorCombiner |
gradientcobra |
GradientCOBRACombiner |
mixcobra |
MixCOBRACombiner |
Choosing a regression combiner
The five strategies fall into three broad groups.
-
Fixed averaging
meanUses the same weight for every prediction column.
-
Learned meta-models
weighted_meanstacking_regressorLearn how F-Step prediction columns map to the target.
-
COBRA-style aggregation
gradientcobramixcobraUse the F-Step prediction matrix as precomputed prediction-space input.
mean
MeanCombiner is the simplest regression consensus strategy.
It is registered as:
and computes the arithmetic mean across prediction columns.
For one sample:
The implementation is:
Fit behavior
MeanCombiner is stateless.
Its fit() method simply returns:
and does not use the target vector.
Input validation
combine() converts the input with:
and requires a two-dimensional matrix.
If:
it raises:
Direct example
import numpy as np
from kfc_procedure.core.combiner.regression import (
MeanCombiner,
)
P = np.array([
[10.0, 12.0, 11.0],
[20.0, 19.0, 22.0],
])
combiner = MeanCombiner()
combiner.fit(P)
prediction = combiner.predict(P)
print(prediction)
Conceptually:
KFC example
from kfc_procedure import KFCRegressor
from kfc_procedure.core.combiner.regression import (
MeanCombiner,
)
model = KFCRegressor(
divergences=["euclidean"],
local_model="ridge",
combiner=MeanCombiner(),
random_state=42,
)
Using an instance is important in the current source because of the C-Step
random_state forwarding issue described later on this page.
weighted_mean
WeightedMeanCombiner is registered as:
Despite the name, the current implementation is not a constrained weighted average.
It fits:
on the F-Step prediction matrix.
The model is:
With an intercept enabled:
Constructor
The only constructor parameter is:
with default:
Internally:
Fit behavior
The input is converted using:
and must be two-dimensional.
Then:
is called.
Prediction
combine() delegates directly to:
Important interpretation
The learned coefficients are not constrained.
The implementation does not enforce:
and does not enforce:
So the learned model can use:
This is ordinary least-squares combination.
Direct example
from kfc_procedure.core.combiner.regression import (
WeightedMeanCombiner,
)
combiner = WeightedMeanCombiner(
fit_intercept=False,
)
combiner.fit(
P_train,
y_train,
)
y_pred = combiner.predict(
P_test
)
Inspect learned coefficients
and:
If F-Step columns are ordered as:
then the coefficient vector follows the same matrix-column order.
KFC example
from kfc_procedure import KFCRegressor
from kfc_procedure.core.combiner.regression import (
WeightedMeanCombiner,
)
model = KFCRegressor(
divergences=["euclidean"],
local_model="ridge",
combiner=WeightedMeanCombiner(
fit_intercept=False,
),
random_state=42,
)
stacking_regressor
StackingRegressorCombiner is registered as:
It learns a second-level regression model from the F-Step prediction matrix.
Conceptually:
Default meta-model
If no model is supplied, the constructor uses:
The constructor is:
with:
Fit behavior
Before fitting, the configured meta-model is cloned:
Then:
is called.
The fitted clone is stored as:
Why clone?
The source deliberately keeps:
as the configuration object and:
as the fitted object.
This follows standard scikit-learn fitted-state conventions.
Fitted-state check
The implementation also stores:
after training.
Calling combine() before fitting raises:
Direct example
from kfc_procedure.core.combiner.regression import (
StackingRegressorCombiner,
)
combiner = StackingRegressorCombiner()
combiner.fit(
P_train,
y_train,
)
y_pred = combiner.predict(
P_test
)
Custom meta-regressor
from sklearn.ensemble import RandomForestRegressor
combiner = StackingRegressorCombiner(
meta_model=RandomForestRegressor(
n_estimators=200,
random_state=42,
)
)
The fitted version is then available as:
KFC example
from kfc_procedure import KFCRegressor
from kfc_procedure.core.combiner.regression import (
StackingRegressorCombiner,
)
model = KFCRegressor(
divergences=["euclidean"],
local_model="ridge",
combiner=StackingRegressorCombiner(),
random_state=42,
)
gradientcobra
GradientCOBRACombiner is registered as:
It wraps the package's:
estimator.
The constructor is:
and internally creates:
KFC integration
The important implementation detail is the fit call:
Here X is the F-Step prediction matrix.
Therefore GradientCOBRA does not fit a new set of base estimators when used as a C-Step wrapper.
It receives the divergence-level F-Step predictions directly as its prediction-space representation.
Prediction
The wrapper delegates to:
Example
from kfc_procedure import KFCRegressor
model = KFCRegressor(
divergences=["euclidean"],
local_model="ridge",
combiner="gradientcobra",
combiner_params={
"distance": "euclidean",
"kernel": "rbf",
"n_cv": 5,
},
random_state=42,
)
Because the wrapper accepts:
the random_state keyword injected by C-Step is accepted and forwarded to
GradientCOBRA.
Inspect the fitted wrapper
After fitting:
The wrapped estimator is:
For example:
Fitted GradientCOBRA attributes depend on the selected configuration.
For the algorithm and bandwidth optimization behavior, see:
mixcobra
MixCOBRACombiner is registered as:
It wraps:
The constructor is:
and creates:
KFC integration
The wrapper fits MixCOBRA using:
Again, X is the F-Step prediction matrix.
This is a specific KFC integration path.
Important distinction from standalone MixCOBRA
Standalone MixCOBRA is organized around input-space and prediction-space information.
Inside the KFC C-Step wrapper, the F-Step prediction matrix is supplied as precomputed predictions using:
So this wrapper should be understood as KFC feeding its divergence-level prediction representation into MixCOBRA's precomputed-prediction mode.
For the standalone algorithm, see:
Example
from kfc_procedure import KFCRegressor
model = KFCRegressor(
divergences=["euclidean"],
local_model="ridge",
combiner="mixcobra",
combiner_params={
"distance": "euclidean",
"kernel": "rbf",
"n_cv": 5,
},
random_state=42,
)
Inspect the fitted wrapper
The wrapper itself adds no additional learned state beyond the underlying
MixCOBRARegressor.
Comparison
| Combiner | Uses target during fit() |
Learned object | Main operation |
|---|---|---|---|
mean |
No | none | arithmetic mean |
weighted_mean |
Yes | LinearRegression |
linear coefficients |
stacking_regressor |
Yes | cloned meta-regressor | second-level regression |
gradientcobra |
Yes | GradientCOBRA |
prediction-space kernel aggregation |
mixcobra |
Yes | MixCOBRARegressor |
MixCOBRA precomputed-prediction aggregation |
Current C-Step random_state issue
The current C-Step builds string-based combiners with:
params = dict(
self.combiner_params
)
if "random_state" not in params:
params["random_state"] = self.random_state
and then:
This means every string-based combiner receives a random_state keyword.
Affected regression combiners
These constructors do not accept random_state:
Therefore the current string-based C-Step path can attempt calls equivalent to:
or even:
and raise:
COBRA wrappers are not affected
These constructors accept arbitrary keyword arguments:
So:
remain compatible with the current C-Step parameter forwarding design.
Workaround for simple combiners
Pass a pre-instantiated combiner object instead of a string.
Mean
from kfc_procedure.core.combiner.regression import (
MeanCombiner,
)
model = KFCRegressor(
divergences=["euclidean"],
local_model="ridge",
combiner=MeanCombiner(),
random_state=42,
)
Weighted mean
from kfc_procedure.core.combiner.regression import (
WeightedMeanCombiner,
)
model = KFCRegressor(
divergences=["euclidean"],
local_model="ridge",
combiner=WeightedMeanCombiner(
fit_intercept=False,
),
random_state=42,
)
Stacking
from kfc_procedure.core.combiner.regression import (
StackingRegressorCombiner,
)
model = KFCRegressor(
divergences=["euclidean"],
local_model="ridge",
combiner=StackingRegressorCombiner(),
random_state=42,
)
For a non-string object, C-Step returns it directly:
so the automatic constructor keyword injection is bypassed.
Direct combiner use
The regression combiners can also be used outside the full KFC pipeline.
Suppose:
already contains model predictions.
Then:
followed by:
uses the same combiner API as C-Step.
Example prediction matrix
import numpy as np
P_train = np.array([
[10.1, 10.4, 10.0],
[12.0, 12.2, 11.8],
[18.5, 18.0, 18.8],
[25.1, 24.7, 25.4],
])
y_train = np.array([
10.2,
12.1,
18.4,
25.0,
])
Then any regression combiner can consume:
where the three columns represent three prediction sources.
Inspect the C-Step prediction matrix
For a fitted KFC regressor:
clusters = model.kstep_.predict(
X_test
)
P_test = model.fstep_.predict(
X_test,
clusters,
)
print(
P_test.shape
)
print(
P_test[:5]
)
The column names can be recovered with:
Interpret weighted coefficients
If:
and:
then the learned model corresponds to:
when fit_intercept=False.
This illustrates why weighted_mean should not be interpreted as a convex
average.
Inspect stacking state
For a fitted stacking strategy:
If the default LinearRegression is used:
You can compare these coefficients with the F-Step column order.
Inspect COBRA state
For either COBRA regression wrapper:
The exact fitted attributes belong to the underlying COBRA estimator.
For example, depending on the implementation and mode:
may expose optimization information after fitting.
Refer to the dedicated concept pages for algorithm-specific details rather than assuming both COBRA classes expose identical fitted state.
Input shape requirements
mean, weighted_mean, and stacking_regressor explicitly validate their
training or combination input as a two-dimensional array.
Expected shape:
For KFC:
A one-dimensional input such as:
is not accepted by these strategies.
One divergence
A KFC model can use a single divergence:
Then the C-Step matrix has shape:
With mean, the one input column is returned unchanged numerically.
With learned combiners, the strategy can still fit a transformation from that single column to the target.
Several divergences
With:
the C-Step receives:
This allows the combiner to aggregate or learn relationships across the four divergence-specific predictions.
Learned combiners train on the KFC aggregation subset
KFCProcedure.fit() internally separates the data into:
The K-Step and F-Step are fitted using:
Then D_l is passed through the fitted K/F stages to create:
and the C-Step is fitted with:
Therefore learned regression combiners are trained on prediction vectors generated for the aggregation subset.
Which combiner is simplest?
The source itself does not rank the combiners.
Their behavior differs as follows:
mean
fixed arithmetic rule
weighted_mean
fitted linear rule
stacking_regressor
fitted customizable regression rule
gradientcobra
fitted GradientCOBRA rule
mixcobra
fitted MixCOBRA rule
Use the strategy that matches the aggregation behavior you want to evaluate.
Custom regression combiner
You can implement a custom strategy by subclassing:
and registering it under:
Example:
import numpy as np
from kfc_procedure.core.combiner.base import (
BaseCombiner,
)
from kfc_procedure.core.combiner import (
CombinerFactory,
)
@CombinerFactory.register(
"median",
categories={"regression"},
)
class MedianCombiner(
BaseCombiner
):
def __init__(
self,
random_state=None,
):
self.random_state = random_state
def fit(
self,
X,
y=None,
):
return self
def combine(
self,
X,
):
X = np.asarray(X)
return np.median(
X,
axis=1,
)
The random_state parameter is included because the current C-Step injects it
for every string-based combiner.
Debugging regression consensus
Inspect the selected strategy
Inspect F-Step input
Check for missing values
For numeric regression predictions:
Learned combiners may fail if upstream predictions contain NaN or infinity.
Check column order
This is especially important when interpreting learned linear coefficients.
Check weighted-mean coefficients
Check stacking meta-model
Check COBRA wrapper
Quick reference
| Name | Constructor | Stateless? | Current string-path compatibility |
|---|---|---|---|
mean |
MeanCombiner() |
Yes | affected by random_state injection |
weighted_mean |
WeightedMeanCombiner(fit_intercept=False) |
No | affected |
stacking_regressor |
StackingRegressorCombiner(meta_model=None) |
No | affected |
gradientcobra |
GradientCOBRACombiner(**cobra_params) |
No | compatible |
mixcobra |
MixCOBRACombiner(**cobra_params) |
No | compatible |
Mental model
Regression consensus answers one question: given several divergence-specific numeric predictions, how should they become one final number?
The current source provides a fixed arithmetic rule, two learned meta-model approaches, and two COBRA wrappers.