Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Conformal prediction with conditional guarantees #455

Open
wants to merge 171 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
171 commits
Select commit Hold shift + click to select a range
4a367bd
ADD: first implementation of the CCP method
May 28, 2024
fffd511
UPD: increase test_results_with_constant_sample_weights assert_allclo…
Damien-Bouet May 28, 2024
56c67cf
MOVE PhiFunction into utils folder
Damien-Bouet May 31, 2024
765c70a
ADD Polynomial and Gaussian PhiFunctions
Damien-Bouet May 31, 2024
c8c004d
UPD docstrings and return self on fit and calibrate
Damien-Bouet May 31, 2024
1767c1e
FIX: tests
Damien-Bouet May 31, 2024
8a46555
ADD: Paper simulations reproduction
Damien-Bouet May 31, 2024
d75a48b
FIX: tests and coverage
Damien-Bouet Jun 3, 2024
e29d0d7
FIX: paper simulation
Damien-Bouet Jun 3, 2024
fb4dbcb
Remove Literal for python 3.7 compatibility
Damien-Bouet Jun 3, 2024
16c7069
UPD: sample_weight_test tol values
Damien-Bouet Jun 3, 2024
b32626e
RMV: seaborn from paper simulation imports
Damien-Bouet Jun 3, 2024
4f4447e
FIX: linting
Damien-Bouet Jun 3, 2024
015bdb7
FIX: useless seaborn grid style
Damien-Bouet Jun 3, 2024
22a901d
FIX: Gaussian exp formula
Damien-Bouet Jun 4, 2024
db23dc0
MOVE: check_parameters in outside of init
Damien-Bouet Jun 4, 2024
7f2cf56
FIX: Gaussian exp formula test
Damien-Bouet Jun 4, 2024
24d8e19
MOVE: PhiFunctions import from regression to regression.utils
Damien-Bouet Jun 4, 2024
023207f
UPD: Add fit/calib _attributes and Base classes inheritence
Damien-Bouet Jun 5, 2024
79efe4e
UPD: Improve parameters checks
Damien-Bouet Jun 5, 2024
c278273
MOVE: check_estimator into utils
Damien-Bouet Jun 5, 2024
595b037
UPD: CCP docstrings
Damien-Bouet Jun 5, 2024
b6735c2
UPD: Return predictions only if alpha is None
Damien-Bouet Jun 5, 2024
e48a8e6
UPD: Improve and functions
Damien-Bouet Jun 5, 2024
5158462
UPD: Convert PhiFunction into a Abstract class
Damien-Bouet Jun 5, 2024
2fcc380
ADD: CustomPhiFunction
Damien-Bouet Jun 5, 2024
88e9273
UPD: Tests
Damien-Bouet Jun 5, 2024
a376dd5
reduce Gibbs paper simulation runtime
Damien-Bouet Jun 5, 2024
c2481f3
RENAME: move CCP on the template fit/predict (with fit_estimator, fit…
Damien-Bouet Jun 5, 2024
3885491
FIX: forgot to stage a line from 'UPD: Convert PhiFunction into a Abs…
Damien-Bouet Jun 5, 2024
f728d77
FIX: array error for np.std
Damien-Bouet Jun 5, 2024
aeb7979
FIX: some forgotten fit_calibrator renaming
Damien-Bouet Jun 6, 2024
f848813
ADD: _is_fitted function (almost the copy of the private sklearn.util…
Damien-Bouet Jun 6, 2024
dc19045
typing
Damien-Bouet Jun 6, 2024
4fdd852
typing again...
Damien-Bouet Jun 6, 2024
b0e22ec
UPD: CustomPhiFunction can now take PhiFunction instances in function…
Damien-Bouet Jun 6, 2024
293f085
Merge branch 'master' into 449-cp-with-conditional-guarantees
Jun 6, 2024
809a39f
RENAME: check_estimator_regression
Damien-Bouet Jun 6, 2024
4cf1a9f
RMV: Exemple from MapieCCPRegressor
Damien-Bouet Jun 6, 2024
c588ec8
UPD: make fit method mandatory and use check_is_fitted from sklearn
Damien-Bouet Jun 10, 2024
8048220
MOVE: Externalise some utils functions
Damien-Bouet Jun 10, 2024
1adf14d
MOVE: PhiFunctions into phi_function folder
Damien-Bouet Jun 10, 2024
ec4ce10
FIX: Coverage
Damien-Bouet Jun 10, 2024
b8be35e
ADD: PhiFunction multiplication
Damien-Bouet Jun 10, 2024
99ea3fe
FIX: coverage
Damien-Bouet Jun 10, 2024
db360f9
MOVE and RENAME: PhiFunctions in calibrators/ccp
Damien-Bouet Jun 11, 2024
0a7ec52
ADD: Abstract 'Calibrator' class
Damien-Bouet Jun 11, 2024
e9e0f43
UPD: externalise MapieCCPRegressor into abstract SplitMapie and move …
Damien-Bouet Jun 12, 2024
f7e8296
RENAME tests
Damien-Bouet Jun 12, 2024
e45bf48
ADD: Draft of Classification, to assess the generaliation capacities …
Damien-Bouet Jun 12, 2024
f08f8ae
UPD: improve abstract calibrator class signature
Damien-Bouet Jun 13, 2024
d437750
FIX: Coverage
Damien-Bouet Jun 13, 2024
33573a3
UPD: docstring
Damien-Bouet Jun 14, 2024
9168201
UPD: docstrings and rename
Damien-Bouet Jun 14, 2024
328130c
ADD: demo notebook CCP Regression
Damien-Bouet Jun 14, 2024
61e52b1
MERGE master
Damien-Bouet Jun 17, 2024
fbd8bd0
UPD: linting, tests and coverage
Damien-Bouet Jun 17, 2024
cfe299f
UPD: move reg_param into init
Damien-Bouet Jun 17, 2024
6db9867
ADD: author
Damien-Bouet Jun 17, 2024
68f704d
FIX: has no attribute
Damien-Bouet Jun 17, 2024
e8914a0
REMOVE: CCP Docstring example
Damien-Bouet Jun 17, 2024
afacd1a
REMOVE: example results
Damien-Bouet Jun 17, 2024
2538ca0
FIX: ccp_regression_demo
Damien-Bouet Jun 17, 2024
73c3a29
ADD: tutorial_ccp_CandC.ipynb
Damien-Bouet Jun 17, 2024
cb80f3b
ADD: ccp_tutorial notebook in readthedocs
Damien-Bouet Jun 17, 2024
f1e3be4
UPD: ccp tuto
Damien-Bouet Jun 17, 2024
950f02d
FIX: remove seaborn import
Damien-Bouet Jun 18, 2024
a7a3297
FIX: isort imports
Damien-Bouet Jun 18, 2024
cc41209
UPD: ccp tutorial
Damien-Bouet Jun 18, 2024
3cfdba1
UPD: remove multipliers from CCPCalibrator init and remove assert
Damien-Bouet Jun 18, 2024
ef8e378
DEL: ccp notebook moved in the doc, not usefull anymore
Damien-Bouet Jun 18, 2024
2ddc543
FIX: typo in docstrings
Damien-Bouet Jun 18, 2024
2e5918f
MOVE: check_calibrator in calibrators.utils
Damien-Bouet Jun 18, 2024
64be82e
UPD: docstrings and minor fix
Damien-Bouet Jun 18, 2024
cad8e28
ADD: notebook tutorial_ccp_CandC in regression notebooks doc
Damien-Bouet Jun 18, 2024
dca25d3
ADD: test to check equivalence of new and old implementation of stand…
Damien-Bouet Jun 18, 2024
b5ed289
UPD: typos
Damien-Bouet Jun 21, 2024
9bb8863
ADD: perfect width in ccp tutorial plots
Damien-Bouet Jun 21, 2024
9115a87
UPD: Change regularization from L2 to L1
Damien-Bouet Jun 21, 2024
1eed6de
FIX: ccp tuto plot
Damien-Bouet Jun 21, 2024
8247e30
FIX: ccp tuto
Damien-Bouet Jun 21, 2024
e04ab4a
UPD: only sample gaussian points where multipliers values are not zer…
Damien-Bouet Jul 15, 2024
909ec93
UPD: gaussian default value set to 20
Damien-Bouet Jul 16, 2024
60bda1a
FIX: calib_kwargs bug fix
Damien-Bouet Jul 16, 2024
d14fa1b
MOVE: ccp null feature warning call
Damien-Bouet Jul 16, 2024
89e31b9
UPD: calib kwargs docstring
Damien-Bouet Jul 16, 2024
43dd443
UPD: multiply default sigma value by dnum of dimensions
Damien-Bouet Jul 16, 2024
0ab0d77
UPD: docstrings and some renaming
Damien-Bouet Jul 20, 2024
f3d272a
FIX: calib_kwargs bug and linting
Damien-Bouet Jul 22, 2024
907aec6
RMV warning in optional arg in custim ccp
Damien-Bouet Jul 22, 2024
3de4ef3
FIX: multiplier impact on normalize and sigma
Damien-Bouet Jul 23, 2024
e704700
UPD: ccp tutorial
Damien-Bouet Jul 23, 2024
2900605
ADD: ccp in api doc
Damien-Bouet Jul 23, 2024
a54aad8
UPD: add ccp tutorial conclusion and remove typo
Damien-Bouet Jul 23, 2024
8f12ac4
FIX typo in ccp_tuto
Damien-Bouet Jul 23, 2024
44c78fa
ADD: CCP theoretical description doc
Damien-Bouet Jul 24, 2024
fea21c4
FIX: ccp theory doc
Damien-Bouet Jul 25, 2024
28ff85b
RENAME compile_functions_warnings_errors utils function and update er…
Damien-Bouet Jul 25, 2024
4c560fd
RENAME ccp calibrator test functions
Damien-Bouet Jul 25, 2024
b31609c
Try to fix the doc
Damien-Bouet Jul 25, 2024
2babfa2
UPD: ccp_CandC notebook
Damien-Bouet Jul 25, 2024
71eaa1c
MOVE CCP doc into a new section
Damien-Bouet Jul 25, 2024
c67bb57
ADD tuto papier reference link
Damien-Bouet Jul 25, 2024
391f529
ADD: calibrator doc
Damien-Bouet Jul 25, 2024
ddc9b52
UPD: minor corrections in the doc
Damien-Bouet Jul 26, 2024
f3e0d32
MOVE: BaseCalibrator import
Damien-Bouet Jul 26, 2024
00bfd27
UPD docstrings and add ccp reference
Damien-Bouet Jul 26, 2024
c1a00dc
RMV not reproductible warning
Damien-Bouet Jul 26, 2024
fefd068
Merge branch 'master' into 449-cp-with-conditional-guarantees
Damien-Bouet Jul 26, 2024
20037f7
REFACTO: Adapte the PR to the new Classifier refacto
Damien-Bouet Jul 29, 2024
8ac6ae9
FIX: tests
Damien-Bouet Jul 29, 2024
add96e6
UNDO changes in sets.utils
Damien-Bouet Jul 29, 2024
4cb0aba
Linting
Damien-Bouet Jul 29, 2024
1afcf27
UPD: change naive by standard in doc
Damien-Bouet Jul 29, 2024
09881aa
ADD: classification main class and tuto
Damien-Bouet Jul 30, 2024
b31f9da
ADD: SplitCPClassifier tests
Damien-Bouet Jul 30, 2024
6d94658
FIX: coverage
Damien-Bouet Jul 30, 2024
24ab0fc
FIX: coverage
Damien-Bouet Jul 30, 2024
360cb39
FIX test
Damien-Bouet Jul 30, 2024
269546d
FIX docstring example
Damien-Bouet Jul 30, 2024
9c0b09f
UPD: change optimizer to SLSQP
Damien-Bouet Jul 31, 2024
20e94b2
UPD: change optimize to SLSQP
Damien-Bouet Jul 31, 2024
66fe957
UPD: update CandC notebook after changing optimizer
Damien-Bouet Jul 31, 2024
abe9bf9
FIX: tests
Damien-Bouet Jul 31, 2024
3c0f1c7
FIX tests
Damien-Bouet Jul 31, 2024
e82b1c7
UPD: fix coverage
Damien-Bouet Jul 31, 2024
42e1c60
Merge branch '449-cp-with-conditional-guarantees' into 499-adaptation…
Damien-Bouet Jul 31, 2024
40bf93a
FIX: typo
Damien-Bouet Jul 31, 2024
d53be61
FIX typo
Damien-Bouet Jul 31, 2024
ced2086
UPD: theoretical description
Damien-Bouet Aug 5, 2024
0562e79
ADD: reference in README
Damien-Bouet Aug 5, 2024
a6cf257
UPD: HISTORY with new CCP content
Damien-Bouet Aug 5, 2024
8ca56d9
UPD: theoretical description
Damien-Bouet Aug 5, 2024
2fc54fd
ADD: reference in README
Damien-Bouet Aug 5, 2024
26f07da
UPD: HISTORY with new CCP content
Damien-Bouet Aug 5, 2024
c33ed18
UPD: theoretical doc update and typo
Damien-Bouet Aug 7, 2024
db375a3
UPD: remove sample_weights and corrected alpha in the calibration ste…
Damien-Bouet Aug 7, 2024
53837bd
UPD: Typos in the doc
Damien-Bouet Aug 7, 2024
57e15f8
linting
Damien-Bouet Aug 7, 2024
9fa15fe
UPD: test values
Damien-Bouet Aug 7, 2024
926d3b6
Merge branch '449-cp-with-conditional-guarantees' into 506-ccp-reopti…
Damien-Bouet Aug 8, 2024
0ecabba
UPD: re optimize at inference time and add unsafe mode for old method
Damien-Bouet Aug 8, 2024
ab14963
Merge branch 'master' into 449-cp-with-conditional-guarantees
Damien-Bouet Aug 8, 2024
744d56f
typo
Damien-Bouet Aug 8, 2024
b4f06e8
Merge branch '449-cp-with-conditional-guarantees' into 499-adaptation…
Damien-Bouet Aug 8, 2024
171cd6d
Merge branch '449-cp-with-conditional-guarantees' into 506-ccp-reopti…
Damien-Bouet Aug 8, 2024
1de9cf4
tests
Damien-Bouet Aug 8, 2024
1feb27b
RMV: example from SplitCPClassifier doc
Damien-Bouet Aug 8, 2024
2b43867
FIX: tests
Damien-Bouet Aug 8, 2024
b054bfa
REMOVE warning about stochastic behavior
Damien-Bouet Aug 9, 2024
096b4b4
UPD: add :class: tag in docstrings
Damien-Bouet Aug 9, 2024
1ded613
UPD: optimize starting from n points value
Damien-Bouet Aug 9, 2024
600047b
UPD: remove commented section
Damien-Bouet Aug 9, 2024
14e05b9
UPD: add :class: tag in docstrings
Damien-Bouet Aug 9, 2024
10a419e
UPD: doc
Damien-Bouet Aug 9, 2024
0e5930b
Merge branch '449-cp-with-conditional-guarantees' into 499-adaptation…
Damien-Bouet Aug 9, 2024
90f865f
UPD: shorten giibs result reproduction duration
Damien-Bouet Aug 9, 2024
038f863
UPD: activate unsafe_approximation in the doc example
Damien-Bouet Aug 9, 2024
f9af89a
Apply suggestions from code review
thibaultcordier Oct 22, 2024
49080cc
Merge pull request #500 from scikit-learn-contrib/499-adaptation-ccp-…
thibaultcordier Oct 22, 2024
2b7207d
Merge branch 'master' into 449-cp-with-conditional-guarantees
thibaultcordier Oct 22, 2024
2788dbd
Merge branch '449-cp-with-conditional-guarantees' into 506-ccp-reopti…
Oct 22, 2024
6a35307
Add approximation boolean for classification
Oct 22, 2024
48b8730
UPD: typo
thibaultcordier Oct 22, 2024
a3664f5
Merge pull request #507 from scikit-learn-contrib/506-ccp-reoptimize-…
thibaultcordier Oct 22, 2024
6421813
Move HISTORY.rst new features block
Oct 23, 2024
6c4a3b2
Move calibrators into future + Add details in theorical explanations
Oct 23, 2024
0a8bc05
Change path access of the classes
Oct 23, 2024
6827b6d
FIX: change import path
Oct 23, 2024
ccc4057
FIX: change import path
Oct 23, 2024
4976082
Merge branch 'master' into 449-cp-with-conditional-guarantees
jawadhussein462 Nov 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions AUTHORS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,6 @@ Contributors
* Ambros Marzetta <ambrosm>
* Carl McBride Ellis <Carl-McBride-Ellis>
* Baptiste Calot <[email protected]>
* Damien Bouet <[email protected]>
* Leonardo Garma <[email protected]>
To be continued ...
4 changes: 4 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ History
0.9.x (2024-xx-xx)
------------------

* Add `SplitCPRegressor`, based on new `SplitCP` abstract class, to support the new CCP method
* Add `GaussianCCP`, `PolynomialCCP` and `CustomCCP` based on `CCPCalibrator` to implement the Conditional CP method
* Add the `StandardCalibrator`, to reproduce standard CP and make sure that the `SplitCPRegressor` is implemented correctly.
* Add the CCP documentation, tutorial and demo notebooks
* Fix issue 525 in contribution guidelines with syntax errors in hyperlinks and other formatting issues.
* Bump wheel version to avoid known security vulnerabilities

Expand Down
2 changes: 2 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,8 @@ and with the financial support from Région Ile de France and Confiance.ai.

[12] Angelopoulos, Anastasios N., Stephen, Bates, Emmanuel J. Candès, et al. "Learn Then Test: Calibrating Predictive Algorithms to Achieve Risk Control." (2022).

[13] Isaac Gibbs, John J. Cherian, and Emmanuel J. Candès, "Conformal Prediction With Conditional Guarantees" (2023).


📝 License
==========
Expand Down
29 changes: 28 additions & 1 deletion doc/api.rst
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@

.. _api:

#########
MAPIE API
#########
Expand Down Expand Up @@ -109,9 +112,33 @@ Resampling
subsample.BlockBootstrap
subsample.Subsample

New Split CP class
===================

.. autosummary::
:toctree: generated/
:template: class.rst

future.split.base.SplitCP
future.split.SplitCPRegressor
future.split.SplitCPClassifier

Calibrators
===========

.. autosummary::
:toctree: generated/
:template: class.rst

future.calibrators.base.BaseCalibrator
future.calibrators.StandardCalibrator
future.calibrators.ccp.CCPCalibrator
future.calibrators.ccp.CustomCCP
future.calibrators.ccp.PolynomialCCP
future.calibrators.ccp.GaussianCCP

Mondrian
==========
========

.. autosummary::
:toctree: generated/
Expand Down
10 changes: 10 additions & 0 deletions doc/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,16 @@
examples_classification/index
notebooks_classification

.. toctree::
:maxdepth: 2
:hidden:
:caption: CONDITIONAL CP

theoretical_description_ccp
theoretical_description_calibrators
examples_regression/4-tutorials/plot_ccp_tutorial
examples_classification/4-tutorials/plot_ccp_class_tutorial

.. toctree::
:maxdepth: 2
:hidden:
Expand Down
3 changes: 3 additions & 0 deletions doc/notebooks_regression.rst
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ This section lists a series of Jupyter notebooks hosted on the MAPIE Github repo
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


4. Leverage CCP method to have adaptative prediction intervals on Communities and Crime Dataset : `ccp_CandC_notebook <https://github.com/scikit-learn-contrib/MAPIE/tree/master/notebooks/regression/tutorial_ccp_CandC.ipynb>`_
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

80 changes: 80 additions & 0 deletions doc/theoretical_description_calibrators.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
.. title:: Calibrators : contents

.. _theoretical_description_calibrators:

###############
Calibrators
###############

In Mapie, the conformalisation step is done directly inside
:class:`~mapie.regression.MapieRegressor` or :class:`~mapie.classification.MapieClassifier`,
depending on the ``method`` argument.
However, when implementing the new CCP method, we decided to externalize the conformalisation
step into a new object named ``calibrator``, to have more freedom and possible customisation.

The new classes (:class:`~mapie.future.split.SplitCPRegressor` and :class:`~mapie.future.split.SplitCPClassifier`) have 3 steps:

1. ``fit_predictor``, which fit the sklearn estimator
2. ``fit_calibrator``, which do the conformalisation (calling ``calibrator.fit``)
3. ``predict``, which compute the predictions and call ``calibrator.predict`` to create the prediction intervals

Thus, the calibrators, based on :class:`~mapie.future.calibrators.base.BaseCalibrator`,
must have the two methods: ``fit`` and ``predict``.

Mapie currently implements calibrators for the CCP method (and the standard method),
but any conformal prediction method can be implemented by the user as
a subclass of :class:`~mapie.future.calibrators.base.BaseCalibrator`.

Example of standard split CP:
------------------------------

For instance, the :class:`~mapie.future.calibrators.StandardCalibrator` implements
the :ref:`standard split method<theoretical_description_regression_standard>`:

* ``.fit`` computes :math:`\hat{q}_{n, \alpha}^+`, the :math:`(1-\alpha)` quantile of the distribution
* ``.predict`` comptues the prediction intervals with: :math:`\hat{\mu}(X_{n+1}) \pm \hat{q}_{n, \alpha}^+`


The CCP calibrators:
---------------------
For the CCP method (see :ref:`theoretical description<theoretical_description_ccp>`),
:class:`~mapie.future.calibrators.ccp.CCPCalibrator` implements:

* ``.fit`` solve the optimization problem (see :ref:`step 2<theoretical_description_ccp_control_steps>`) to find the optimal :math:`\hat{g}`
* ``.predict`` comptues the prediction intervals using :math:`\hat{g}` (see :ref:`step 3<theoretical_description_ccp_control_steps>`)

We just need a way to define our :math:`\Phi` function (see :ref:`step 1<theoretical_description_ccp_control_steps>`).

Multiple subclasses are implemented to facilitate the definition of the :math:`\Phi` function,
but other could be implemented by the user as a subclass of :class:`~mapie.future.calibrators.ccp.CCPCalibrator`.

1. :class:`~mapie.future.calibrators.ccp.CustomCCP`

This class allows to define by hand the :math:`\Phi` function, as a
concatenation of other functions which create features of ``X`` (or potentially ``y_pred`` or any exogenous variable ``z``)

It can also be used to concatenate other :class:`~mapie.future.calibrators.ccp.CCPCalibrator` instances.

2. :class:`~mapie.future.calibrators.ccp.PolynomialCCP`

It create some polynomial features of ``X`` (or potentially ``y_pred`` or any exogenous variable ``z``).
It could be created by hand using `CustomCCP`, it is just a way simplify the creation of :math:`\Phi`.

3. :class:`~mapie.future.calibrators.ccp.GaussianCCP`

It create gaussian kernels, as done in the method's paper :ref:`[1]<theoretical_description_calibrators_references>`.
It samples random points from the :math:`\{ X_i \}_i`, then compute gaussian distances
between each point and :math:`X_{n+1}` with a given standard deviation :math:`\sigma`
(which can be optimized using cross-validation), following the formula:

.. math::
\forall j \in \{ \text{sampled index} \}, \quad \Phi(X)_j = exp \left( -\frac{(X_{n+1} - X_j)^2}{2\sigma ^2} \right)


.. _theoretical_description_calibrators_references:

References
==========

[1] Isaac Gibbs, John J. Cherian, and Emmanuel J. Candès,
"Conformal Prediction With Conditional Guarantees", `arXiv <https://arxiv.org/abs/2305.12616>`_, 2023.
201 changes: 201 additions & 0 deletions doc/theoretical_description_ccp.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
.. title:: Theoretical Description : contents

.. _theoretical_description_ccp:

########################
Theoretical Description
########################

The Conditional Conformal Prediction (CCP) method :ref:`[1]<theoretical_description_ccp_references>` is a model agnostic conformal prediction method which
can create adaptative prediction intervals.

In MAPIE, this method has a lot of advantages:

- It is model agnostic (it doesn’t depend on the model but only on the predictions, unlike CQR)
- It can create very adaptative intervals (with a varying width which truly reflects the model uncertainty)
- while providing coverage guarantee on all sub-groups of interest (avoiding biases)
- with the possibility to inject prior knowledge about the data or the model

thibaultcordier marked this conversation as resolved.
Show resolved Hide resolved
However, we will also see its disadvantages:
- The adaptativity depends on the calibrator we use: It can be difficult to choose the correct calibrator,
with the best parameters.
- The calibration and even more the inference are much longer than for the other methods.
We can reduce the inference time using ``unsafe_approximation=True``,
but we lose the strong theoretical guarantees and risk a small miscoverage
(even if, most of the time, the coverage is achieved).

To conclude, it can create more adaptative intervals than the other methods,
but it can be difficult to find the best settings (calibrator type and parameters)
and can have a big computational time.

How does it works?
====================

Method's intuition
--------------------

We recall that the `standard split method` estimates the absolute residuals by a constant :math:`\hat{q}_{n, \alpha}^+`
(which is the quantile of :math:`{|Y_i-\hat{\mu}(X_i)|}_{1 \leq i \leq n}`). Then, the prediction interval is:

.. math:: \hat{C}_{n, \alpha}^{\textrm split}(X_{n+1}) = \hat{\mu}(X_{n+1}) \pm \hat{q}_{n, \alpha}^+

The idea of the `CCP` method, is to learn, not a constant, but a function :math:`q(X)`,
to have a different interval width depending on the :math:`X` value. Then, we would have:

.. math:: \hat{C}_{n, \alpha}^{\textrm CCP}(X_{n+1}) = \hat{\mu}(X_{n+1}) \pm \hat{q}(X_{n+1})

To be able to find the best function, while having some coverage guarantees,
we should select this function inside some defined class of functions :math:`\mathcal{F}`.

This method is motivated by the following equivalence:

.. math::
\begin{array}{c}
\mathbb{P}(Y_{n+1} \in \hat{C} \; | \; X_{n+1}=x) = 1 - \alpha, \quad \text{for all x} \\
\textstyle \Longleftrightarrow \\
\mathbb{E} \left[ f(X_{n+1}) \mathbb{I} \left\{ Y_{n+1} \in \hat{C}(X_{n+1}) \right\} \right] = 0, \quad \text{for all measurable f} \\
\end{array}

This is the equation corresponding to the perfect conditional coverage, which is theoretically impossible to obtain.
Then, relaxing this objective by replacing "all measurable f" with "all f belonging to some class :math:`\mathcal{F}`"
seems a way to get close to the perfect conditional coverage.


.. _theoretical_description_ccp_control_steps:

The method follow 3 steps:
----------------------------

1. Choose a class of functions. The simple approach is to choose a class a finite dimension :math:`d \in \mathbb{N}`,
using, for any :math:`\Phi \; : \; \mathbb{R}^d \to \mathbb{R}` (chosen by the user)

.. math::
\mathcal{F} = \left\{ \Phi (\cdot)^T \beta : \beta \in \mathbb{R}^d \right\}

2. Find the best function of this class by solving the following optimization problem:

.. note:: It is actually a quantile regression between the transformation :math:`\Phi (X)` and the conformity scores `S`.

Considering an upper bound :math:`M` of the conformity scores,
such as :math:`S_{n+1} < M`:

.. math::
\hat{g}_M^{n+1} := \text{arg}\min_{g \in \mathcal{F}} \; \frac{1}{n+1} \sum_{i=1}^n{l_{\alpha} (g(X_i), S_i)} \; + \frac{1}{n+1}l_{\alpha} (g(X_{n+1}), M)

.. warning::
In the :ref:`API<api>`, we use by default :math:`M=max(\{S_i\}_{i\leq n})`,
the maximum conformity score of the calibration set,
but you can specify it yourself if a bound is known, considering your data,
model and conformity score.

Moreover, it means that there is still small computations which are done
for each test point :math:`X_{n+1}`. If you want to avoid that, you can
use ``unsafe_approximation=True``, which only consider:

.. math::
\hat{g} := \text{arg}\min_{g \in \mathcal{F}} \; \frac{1}{n} \sum_{i=1}^n{l_{\alpha} (g(X_i), S_i)}

However, it may result in a small miscoverage.
It is recommanded to empirically check the resulting coverage on the test set.

3. We use this optimized function :math:`\hat{g}_M^{n+1}` to compute the prediction intervals:

.. math::
\hat{C}_M^{n+1}(X_{n+1}) = \{ y : S(X_{n+1}, \: y) \leq \hat{g}_M^{n+1}(X_{n+1}) \}

.. note:: The formulas are generic and work with all conformity scores. But in the case of the absolute residuals, we get:

.. math::
\hat{C}(X_{n+1}) = \hat{\mu}(X_{n+1}) \pm \hat{g}_M^{n+1}(X_{n+1})

.. _theoretical_description_ccp_control_coverage:

Coverage guarantees:
-----------------------

.. warning::
The following guarantees assume that the approximation described above is not used, and that
the chosen bound M is indeed such as :math:`\forall \text{ test index }i, \; S_i < M`

Following this steps, we have the coverage guarantee:
:math:`\forall f \in \mathcal{F},`

.. math::
\mathbb{P}_f(Y_{n+1} \in \hat{C}_M^{n+1}(X_{n+1})) \geq 1 - \alpha

.. math::
\text{and} \quad \left | \mathbb{E} \left[ f(X_{n+1}) \left(\mathbb{I} \left\{ Y_{n+1} \in \hat{C}_M^{n+1}(X_{n+1}) \right\} - (1 - \alpha) \right) \right] \right |
\leq \frac{d}{n+1} \mathbb{E} \left[ \max_{1 \leq i \leq n+1} \left|f(X_i)\right| \right]

.. note::
If we want to have a homogenous coverage on some given groups in :math:`\mathcal{G}`, we can use
:math:`\mathcal{F} = \{ x \mapsto \sum _{G \in \mathcal{G}} \; \beta_G \mathbb{I} \{ x \in G \} : \beta_G \in \mathbb{R} \}`,
then we have :math:`\forall G \in \mathcal{G}`:

.. math::
1 - \alpha
\leq \mathbb{P} \left( Y_{n+1} \in \hat{C}_M^{n+1}(X_{n+1}) \; | \; X_{n+1} \in G \right)
\leq 1- \alpha + \frac{|\mathcal{G}|}{(n+1) \mathbb{P}(X_{n+1} \in G)} \\
= 1- \alpha + \frac{\text{number of groups in } \mathcal{G}}{\text{number of samples of } \{X_i\} \text{ in G}}

How to use it in practice?
============================

Creating a class a function adapted to our needs
--------------------------------------------------

The following will provide some tips on how to use the method (for more practical examples, see
:doc:`examples_regression/4-tutorials/plot_ccp_tutorial` or
`How to leverage the CCP method on real data
<https://github.com/scikit-learn-contrib/MAPIE/tree/master/notebooks/regression/tutorial_ccp_CandC.ipynb>`_
).

1. If you want a generally adaptative interval and you don't have prior
knowledge about your data, you can use gaussian kernels, implemented in Mapie
in :class:`~mapie.future.calibrators.ccp.GaussianCCP`. See the API doc for more information.

2. If you want to avoid bias on sub-groups and ensure an homogenous coverage on those,
you can add indicator functions corresponding to those groups.

3. You can inject prior knowledge in the method using :class:`~mapie.future.calibrators.ccp.CustomCCP`,
if you have information about the conformity scores distribution
(domains with different biavior, expected model uncertainty depending on a given feature, etc).

4. Empirically test obtained coverage on a test set, to make sure that the expected coverage is achieved.


Avoid miscoverage
--------------------

- | To guarantee marginal coverage, you need to have an intercept term in the :math:`\Phi` function (meaning, a feature equal to :math:`1` for all :math:`X_i`).
| It correspond, in the :ref:`API<api>`, to ``bias=True``.

- | Some miscoverage can come from the optimization process, which is
solved with numerical methods, and may fail to find the global minimum.
If the target coverage is not achieved, you can try adding regularization,
to help the optimization process. You can also try reducing the number of dimensions :math:`d`
or using a smoother :math:`\Phi` function, such as with gaussian kernels
(indeed, using only indicator functions makes the optimization difficult).

.. warning::
Adding some regularization will theoretically induce a miscoverage,
as the objective function will slightly increase, to minimize the regularization term.

In practice, it may increase the coverage (as it helps the optimization convergence),
but it can also decrease it. Always empirically check the resulting coverage
and avoid too big regularization terms (below :math:`10^{-4}` is usually recommanded).


- | Finally, if you have coverage issues because the optimisation is difficult,
you can artificially enforce higher coverage by reducing the value of :math:`\alpha`.
Evaluating the best adjusted :math:`\alpha` using cross-validation will ensure
the same coverage on the test set (subject to variability due to the finite number of samples).


.. _theoretical_description_ccp_references:

References
==========

[1] Isaac Gibbs, John J. Cherian, and Emmanuel J. Candès,
"Conformal Prediction With Conditional Guarantees", `arXiv <https://arxiv.org/abs/2305.12616>`_, 2023.
3 changes: 3 additions & 0 deletions doc/theoretical_description_classification.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ for at least :math:`90 \%` of the new test data points.
Note that the guarantee is possible only on the marginal coverage, and not on the conditional coverage
:math:`P \{Y_{n+1} \in \hat{C}_{n, \alpha}(X_{n+1}) | X_{n+1} = x_{n+1} \}` which depends on the location of the new test point in the distribution.


.. _theoretical_description_classification_lac:

1. LAC
------

Expand Down
Loading
Loading