-
Notifications
You must be signed in to change notification settings - Fork 5
Jmafoster1/329 estimator endpoint #382
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
Open
jmafoster1
wants to merge
15
commits into
main
Choose a base branch
from
jmafoster1/329-estimator-endpoint
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
15 commits
Select commit
Hold shift + click to select a range
2720122
Estimators now as entrypoints
jmafoster1 3651a2f
Causal effects now as entry points
jmafoster1 35d1419
Added support for estimator and effect kwargs
jmafoster1 dde436c
Pytests
jmafoster1 740f840
Fixed estimator kwarg formatting
jmafoster1 fb199ac
MetamorphicRelation estimator validation and testing
jmafoster1 09be676
Docs
jmafoster1 1458192
Pylint imports
jmafoster1 d204e2f
Added a top level `causal-testing` entrypoint
jmafoster1 8c99927
Added custom estimation docs
jmafoster1 161c964
Added custom estimation docs
jmafoster1 5595207
Merge branch 'jmafoster1/329-estimator-endpoint' of github.com:CITCOM…
jmafoster1 b9e1d04
Fixed title level misalighment error
jmafoster1 99fb9ab
Added endpoint reinstall note
jmafoster1 6dae63f
Merge branch 'main' into jmafoster1/329-estimator-endpoint
jmafoster1 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| Custom Estimators | ||
| ================= | ||
|
|
||
| If the supported :ref:`estimators` are not sufficient for your needs, you can implement your own custom estimator by extending the :code:`Estimator` class and implementing the abstract :code:`add_modelling_assumptions` method and the estimation method for the causal effect measure you wish to calculate. | ||
| For example, if you wished to estimate the ATE using the empirical mean of the recorded outcome under the control and treatment values, you would need to implement a method called :code:`estimate_ate`. | ||
| If you wished to estimate the risk ratio, you would need to call your method :code:`estimate_risk_ratio`. | ||
| The code for the :code:`EmpiricalMeanEstimator` is shown below. | ||
|
|
||
| .. code-block:: python | ||
|
|
||
| from causal_testing.estimation.abstract_estimator import Estimator | ||
| from scipy.stats import bootstrap | ||
|
|
||
| class EmpiricalMeanEstimator(Estimator): | ||
| """ | ||
| Custom estimator class to estimate the causal effect based on the empirical mean. | ||
| """ | ||
|
|
||
| def add_modelling_assumptions(self): | ||
| """ | ||
| Add modelling assumptions to the estimator. This is a list of strings which list the modelling assumptions that | ||
| must hold if the resulting causal inference is to be considered valid. | ||
| """ | ||
| self.modelling_assumptions += "The data must contain runs with the exact configuration of interest." | ||
|
|
||
| def estimate_ate(self) -> EffectEstimate: | ||
| """Estimate the outcomes under control and treatment. | ||
| :return: The empirical average treatment effect. | ||
| """ | ||
| treatment_variable = self.base_test_case.treatment_variable.name | ||
| outcome_variable = self.base_test_case.outcome_variable.name | ||
|
|
||
| control_results = self.df.where(self.df[treatment_variable] == self.control_value)[outcome_variable].dropna() | ||
| treatment_results = self.df.where(self.df[treatment_variable] == self.treatment_value)[ | ||
| outcome_variable | ||
| ].dropna() | ||
|
|
||
| def risk_ratio(sample1, sample2): | ||
| return sample1.mean() - sample2.mean() | ||
|
|
||
| bootstraps = bootstrap((treatment_results, control_results), risk_ratio, confidence_level=self.alpha) | ||
| return EffectEstimate( | ||
| type="risk_ratio", | ||
| value=risk_ratio(treatment_results, control_results), | ||
| ci_low=bootstraps.confidence_interval.low, | ||
| ci_high=bootstraps.confidence_interval.high, | ||
| ) | ||
|
|
||
| Once you have implemented your estimator, you will need to register it as an extra entry point in your project's :code:`pyproject.toml` file so that the Causal Testing Framework can find it. | ||
| For example, if you had defined your :code:`EmpiricalMeanEstimator` class in a module called :code:`empirical_mean_estimator` in a folder called :code:`custom_estimators`, you would register it as follows. | ||
| You will also need to reinstall your project, e.g. with :code:`pip install -e .` each time you add a new estimator to your :code:`pyproject.toml`. | ||
| You do not need to reinstall each time you edit your project for source code edits. | ||
|
|
||
|
|
||
| .. code-block:: ini | ||
|
|
||
| [project.entry-points."estimators"] | ||
| CustomFlakefighter = "custom_estimators.empirical_mean_estimator:EmpiricalMeanEstimator" | ||
|
|
||
| Of course, for this to work, your module needs to be discoverable on your python path. | ||
| That is, you should be able to execute :code:`from custom_estimators.empirical_mean_estimator import EmpiricalMeanEstimator` successfully from within the current working directory. | ||
|
|
||
| You can also add your custom estimator to causal test cases specified in JSON. | ||
| To do so, you can simply set the :code:`estimator` property to the name of your estimator class and the :code:`estimate_type` property to the name of your causal effect measure. | ||
| In the above :code:`EmpiricalMeanEstimator` example, :code:`estimator` would be set to :code:`"EmpiricalMeanEstimator"` and :code:`estimate_type` would be set to :code:`"ate"`. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,5 @@ | ||
| .. _estimators: | ||
|
|
||
| Estimators Overview | ||
| =================== | ||
|
|
||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jmafoster1 Are we dropping functionality for test-specific queries now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, the estimators all handle it anyway, so there's no need to do it here as well. The alternative would be to move the "query" argument from the estimators, which I could also do. That's possibly a bit DRY-er, but I'm not sure whether it might be nice to keep it as an option if people want to use the estimators without driving it from the main frontend?