3
3
from typing_extensions import Self
4
4
5
5
import numpy as np
6
- from sklearn .linear_model import LinearRegression , QuantileRegressor
6
+ from sklearn .linear_model import LinearRegression
7
7
from sklearn .base import RegressorMixin , clone
8
8
from sklearn .model_selection import BaseCrossValidator
9
+ from sklearn .pipeline import Pipeline
9
10
10
11
from mapie .subsample import Subsample
11
12
from mapie ._typing import ArrayLike , NDArray
12
13
from mapie .conformity_scores import BaseRegressionScore
13
- from mapie .regression import MapieRegressor
14
+ from mapie .regression import MapieRegressor , MapieQuantileRegressor
14
15
from mapie .utils import check_estimator_fit_predict
15
16
from mapie_v1 .conformity_scores ._utils import (
16
17
check_and_select_regression_conformity_score ,
@@ -833,43 +834,54 @@ def predict(
833
834
834
835
class ConformalizedQuantileRegressor :
835
836
"""
836
- A conformal quantile regression model that generates prediction intervals
837
- using quantile regression as the base estimator .
837
+ A model that combines quantile regression with conformal prediction to
838
+ generate reliable prediction intervals with specified coverage levels .
838
839
839
- This approach provides prediction intervals by leveraging
840
- quantile predictions and applying conformal adjustments to ensure coverage.
840
+ The `ConformalizedQuantileRegressor` leverages quantile regression as its
841
+ base estimator to predict conditional quantiles of the target variable,
842
+ and applies conformal adjustments to ensure prediction intervals achieve
843
+ the desired confidence levels. This approach is particularly useful in
844
+ uncertainty quantification for regression tasks.
841
845
842
846
Parameters
843
847
----------
844
- estimator : RegressorMixin, default=QuantileRegressor()
845
- The base quantile regression estimator used to generate point and
846
- interval predictions.
847
-
848
- confidence_level : Union[float, List[float]], default=0.9
848
+ estimator : Union[`RegressorMixin`, `Pipeline`, \
849
+ `List[Union[RegressorMixin, Pipeline]]`]
850
+ The base quantile regression model(s) for estimating target quantiles.
851
+
852
+ - When `prefit=False` (default):
853
+ A single quantile regression estimator (e.g., `QuantileRegressor`)
854
+ or a pipeline that combines preprocessing and regression.
855
+ Supported Regression estimators:
856
+
857
+ - ``sklearn.linear_model.QuantileRegressor``
858
+ - ``sklearn.ensemble.GradientBoostingRegressor``
859
+ - ``sklearn.ensemble.HistGradientBoostingRegressor``
860
+ - ``lightgbm.LGBMRegressor``
861
+
862
+ - When `prefit=True`:
863
+ A list of three fitted quantile regression estimators corresponding
864
+ to lower, upper, and median quantiles. These estimators should be
865
+ pre-trained with consistent quantile settings:
866
+
867
+ * ``lower quantile = 1 - confidence_level / 2``
868
+ * ``upper quantile = confidence_level / 2``
869
+ * ``median quantile = 0.5``
870
+
871
+ confidence_level : float default=0.9
849
872
The confidence level(s) for the prediction intervals, indicating the
850
- desired coverage probability of the prediction intervals. If a float
851
- is provided, it represents a single confidence level. If a list,
852
- multiple prediction intervals for each specified confidence level
853
- are returned.
873
+ desired coverage probability of the prediction intervals.
854
874
855
- conformity_score : Union[str, BaseRegressionScore], default="absolute"
856
- The conformity score method used to calculate the conformity error.
857
- Valid options: TODO : reference here the valid options, once the list
858
- has been be created during the implementation.
859
- See: TODO : reference conformity score classes or documentation
860
-
861
- A custom score function inheriting from BaseRegressionScore may also
862
- be provided.
863
-
864
- random_state : Optional[Union[int, np.random.RandomState]], default=None
865
- A seed or random state instance to ensure reproducibility in any random
866
- operations within the regressor.
875
+ prefit : bool, default=False
876
+ If `True`, assumes the base estimators are already fitted.
877
+ When set to `True`, the `fit` method cannot be called and the
878
+ provided estimators should be pre-trained.
867
879
868
880
Methods
869
881
-------
870
882
fit(X_train, y_train, fit_params=None) -> Self
871
- Fits the base estimator to the training data and initializes internal
872
- parameters required for conformal prediction .
883
+ Trains the base quantile regression estimator on the provided data.
884
+ Not applicable if `prefit=True` .
873
885
874
886
conformalize(X_conf, y_conf, predict_params=None) -> Self
875
887
Calibrates the model on provided data, adjusting the prediction
@@ -904,12 +916,29 @@ class ConformalizedQuantileRegressor:
904
916
905
917
def __init__ (
906
918
self ,
907
- estimator : RegressorMixin = QuantileRegressor (),
908
- confidence_level : Union [float , List [float ]] = 0.9 ,
909
- conformity_score : Union [str , BaseRegressionScore ] = "absolute" ,
910
- random_state : Optional [Union [int , np .random .RandomState ]] = None ,
919
+ estimator : Optional [
920
+ Union [
921
+ RegressorMixin ,
922
+ Pipeline ,
923
+ List [Union [RegressorMixin , Pipeline ]]
924
+ ]
925
+ ] = None ,
926
+ confidence_level : float = 0.9 ,
927
+ prefit : bool = False ,
911
928
) -> None :
912
- pass
929
+
930
+ self ._alpha = 1 - confidence_level
931
+ self .prefit = prefit
932
+
933
+ cv : str = "prefit" if prefit else "split"
934
+ self ._mapie_quantile_regressor = MapieQuantileRegressor (
935
+ estimator = estimator ,
936
+ method = "quantile" ,
937
+ cv = cv ,
938
+ alpha = self ._alpha ,
939
+ )
940
+
941
+ self ._sample_weight : Optional [NDArray ] = None
913
942
914
943
def fit (
915
944
self ,
@@ -937,6 +966,27 @@ def fit(
937
966
Self
938
967
The fitted ConformalizedQuantileRegressor instance.
939
968
"""
969
+
970
+ if self .prefit :
971
+ raise ValueError (
972
+ "The estimators are already fitted, the .fit() method should"
973
+ " not be called with prefit=True."
974
+ )
975
+
976
+ if fit_params :
977
+ fit_params_ = copy .deepcopy (fit_params )
978
+ self ._sample_weight = fit_params_ .pop ("sample_weight" , None )
979
+ else :
980
+ fit_params_ = {}
981
+
982
+ self ._mapie_quantile_regressor ._initialize_fit_conformalize ()
983
+ self ._mapie_quantile_regressor ._fit_estimators (
984
+ X = X_train ,
985
+ y = y_train ,
986
+ sample_weight = self ._sample_weight ,
987
+ ** fit_params_ ,
988
+ )
989
+
940
990
return self
941
991
942
992
def conformalize (
@@ -948,7 +998,7 @@ def conformalize(
948
998
"""
949
999
Calibrates the model on the provided data, adjusting the prediction
950
1000
intervals based on quantile predictions and specified confidence
951
- levels . This step analyzes the conformity scores and refines the
1001
+ level . This step analyzes the conformity scores and refines the
952
1002
intervals to ensure desired coverage.
953
1003
954
1004
Parameters
@@ -969,6 +1019,14 @@ def conformalize(
969
1019
The ConformalizedQuantileRegressor instance with calibrated
970
1020
prediction intervals.
971
1021
"""
1022
+ self .predict_params = predict_params if predict_params else {}
1023
+
1024
+ self ._mapie_quantile_regressor .conformalize (
1025
+ X_conf ,
1026
+ y_conf ,
1027
+ ** self .predict_params
1028
+ )
1029
+
972
1030
return self
973
1031
974
1032
def predict_set (
@@ -1007,7 +1065,18 @@ def predict_set(
1007
1065
Prediction intervals with shape `(n_samples, 2)`, with lower
1008
1066
and upper bounds for each sample.
1009
1067
"""
1010
- return np .ndarray (0 )
1068
+ _ , intervals = self ._mapie_quantile_regressor .predict (
1069
+ X ,
1070
+ optimize_beta = minimize_interval_width ,
1071
+ allow_infinite_bounds = allow_infinite_bounds ,
1072
+ symmetry = symmetric_intervals ,
1073
+ ** self .predict_params
1074
+ )
1075
+
1076
+ return make_intervals_single_if_single_alpha (
1077
+ intervals ,
1078
+ self ._alpha
1079
+ )
1011
1080
1012
1081
def predict (
1013
1082
self ,
@@ -1026,7 +1095,9 @@ def predict(
1026
1095
NDArray
1027
1096
Array of point predictions with shape `(n_samples,)`.
1028
1097
"""
1029
- return np .ndarray (0 )
1098
+ estimator = self ._mapie_quantile_regressor
1099
+ predictions , _ = estimator .predict (X , ** self .predict_params )
1100
+ return predictions
1030
1101
1031
1102
1032
1103
class GibbsConformalRegressor :
0 commit comments