Python API¶
import fairmedfm as fm
fm.auc_gap(y_true, y_score, sensitive_features=group) # one metric, one number
report = fm.evaluate(y_true, y_score, sensitive_features) # binary classification
report = fm.evaluate_segmentation(sensitive_features, dice=dice) # segmentation from Dice scores
report = fm.evaluate_segmentation(sensitive_features, pred_masks=p, true_masks=t) # ... or from masks
Both return a FairnessReport with pandas tables (summary,
by_group) and JSON export. See Evaluate your model for examples and
Fairness metrics for the definitions.
Single metrics¶
Each function returns one float and accepts the same inputs and options as evaluate or
evaluate_segmentation. With several sensitive attributes, their combinations are compared.
auc_gap ¶
auc_gap(
y_true,
y_score,
*,
sensitive_features,
pos_label=None,
score_type="auto",
score_column=None,
bins=None,
)
Largest minus smallest group ROC AUC (0 is fair).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
y_true
|
Any
|
ground truth per sample (0/1, booleans, one-hot rows, or any labels with |
required |
y_score
|
Any
|
positive-class probabilities, logits, or a (samples, classes) matrix such as |
required |
sensitive_features
|
Any
|
group of each sample, e.g. sex or site: an array, Series, list, or a DataFrame or dict of several attributes (their combinations are compared). |
required |
pos_label
|
Any
|
the positive class, when labels are not 0/1 or booleans (one-vs-rest with more classes). |
None
|
score_type
|
str
|
|
'auto'
|
score_column
|
Optional[int]
|
column of the positive class in a (samples, classes) |
None
|
bins
|
Optional[Bins]
|
groups for continuous attributes, e.g. |
None
|
See :func:fairmedfm.evaluate for details.
worst_group_auc ¶
worst_group_auc(
y_true,
y_score,
*,
sensitive_features,
pos_label=None,
score_type="auto",
score_column=None,
bins=None,
)
Lowest group ROC AUC (higher is better).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
y_true
|
Any
|
ground truth per sample (0/1, booleans, one-hot rows, or any labels with |
required |
y_score
|
Any
|
positive-class probabilities, logits, or a (samples, classes) matrix such as |
required |
sensitive_features
|
Any
|
group of each sample, e.g. sex or site: an array, Series, list, or a DataFrame or dict of several attributes (their combinations are compared). |
required |
pos_label
|
Any
|
the positive class, when labels are not 0/1 or booleans (one-vs-rest with more classes). |
None
|
score_type
|
str
|
|
'auto'
|
score_column
|
Optional[int]
|
column of the positive class in a (samples, classes) |
None
|
bins
|
Optional[Bins]
|
groups for continuous attributes, e.g. |
None
|
See :func:fairmedfm.evaluate for details.
accuracy_gap ¶
accuracy_gap(
y_true,
y_score,
*,
sensitive_features,
pos_label=None,
score_type="auto",
score_column=None,
bins=None,
)
Largest minus smallest group accuracy at the threshold with the best overall F1 (0 is fair).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
y_true
|
Any
|
ground truth per sample (0/1, booleans, one-hot rows, or any labels with |
required |
y_score
|
Any
|
positive-class probabilities, logits, or a (samples, classes) matrix such as |
required |
sensitive_features
|
Any
|
group of each sample, e.g. sex or site: an array, Series, list, or a DataFrame or dict of several attributes (their combinations are compared). |
required |
pos_label
|
Any
|
the positive class, when labels are not 0/1 or booleans (one-vs-rest with more classes). |
None
|
score_type
|
str
|
|
'auto'
|
score_column
|
Optional[int]
|
column of the positive class in a (samples, classes) |
None
|
bins
|
Optional[Bins]
|
groups for continuous attributes, e.g. |
None
|
See :func:fairmedfm.evaluate for details.
bce_gap ¶
bce_gap(
y_true,
y_score,
*,
sensitive_features,
pos_label=None,
score_type="auto",
score_column=None,
bins=None,
)
Largest minus smallest group binary cross-entropy (0 is fair).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
y_true
|
Any
|
ground truth per sample (0/1, booleans, one-hot rows, or any labels with |
required |
y_score
|
Any
|
positive-class probabilities, logits, or a (samples, classes) matrix such as |
required |
sensitive_features
|
Any
|
group of each sample, e.g. sex or site: an array, Series, list, or a DataFrame or dict of several attributes (their combinations are compared). |
required |
pos_label
|
Any
|
the positive class, when labels are not 0/1 or booleans (one-vs-rest with more classes). |
None
|
score_type
|
str
|
|
'auto'
|
score_column
|
Optional[int]
|
column of the positive class in a (samples, classes) |
None
|
bins
|
Optional[Bins]
|
groups for continuous attributes, e.g. |
None
|
See :func:fairmedfm.evaluate for details.
ece_gap ¶
ece_gap(
y_true,
y_score,
*,
sensitive_features,
pos_label=None,
score_type="auto",
score_column=None,
bins=None,
)
Largest minus smallest group expected calibration error (0 is fair).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
y_true
|
Any
|
ground truth per sample (0/1, booleans, one-hot rows, or any labels with |
required |
y_score
|
Any
|
positive-class probabilities, logits, or a (samples, classes) matrix such as |
required |
sensitive_features
|
Any
|
group of each sample, e.g. sex or site: an array, Series, list, or a DataFrame or dict of several attributes (their combinations are compared). |
required |
pos_label
|
Any
|
the positive class, when labels are not 0/1 or booleans (one-vs-rest with more classes). |
None
|
score_type
|
str
|
|
'auto'
|
score_column
|
Optional[int]
|
column of the positive class in a (samples, classes) |
None
|
bins
|
Optional[Bins]
|
groups for continuous attributes, e.g. |
None
|
See :func:fairmedfm.evaluate for details.
equal_opportunity_difference ¶
equal_opportunity_difference(
y_true,
y_score,
*,
sensitive_features,
pos_label=None,
score_type="auto",
score_column=None,
bins=None,
)
Largest minus smallest group true positive rate at the best-F1 threshold (eo; 0 is fair).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
y_true
|
Any
|
ground truth per sample (0/1, booleans, one-hot rows, or any labels with |
required |
y_score
|
Any
|
positive-class probabilities, logits, or a (samples, classes) matrix such as |
required |
sensitive_features
|
Any
|
group of each sample, e.g. sex or site: an array, Series, list, or a DataFrame or dict of several attributes (their combinations are compared). |
required |
pos_label
|
Any
|
the positive class, when labels are not 0/1 or booleans (one-vs-rest with more classes). |
None
|
score_type
|
str
|
|
'auto'
|
score_column
|
Optional[int]
|
column of the positive class in a (samples, classes) |
None
|
bins
|
Optional[Bins]
|
groups for continuous attributes, e.g. |
None
|
See :func:fairmedfm.evaluate for details.
equalized_odds_score ¶
equalized_odds_score(
y_true,
y_score,
*,
sensitive_features,
pos_label=None,
score_type="auto",
score_column=None,
bins=None,
)
1 - (TPR gap + TNR gap) / 2 at the best-F1 threshold (eod; 1 is fair).
A score, not a difference: unlike fairlearn's equalized_odds_difference (0 is fair), higher is fairer.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
y_true
|
Any
|
ground truth per sample (0/1, booleans, one-hot rows, or any labels with |
required |
y_score
|
Any
|
positive-class probabilities, logits, or a (samples, classes) matrix such as |
required |
sensitive_features
|
Any
|
group of each sample, e.g. sex or site: an array, Series, list, or a DataFrame or dict of several attributes (their combinations are compared). |
required |
pos_label
|
Any
|
the positive class, when labels are not 0/1 or booleans (one-vs-rest with more classes). |
None
|
score_type
|
str
|
|
'auto'
|
score_column
|
Optional[int]
|
column of the positive class in a (samples, classes) |
None
|
bins
|
Optional[Bins]
|
groups for continuous attributes, e.g. |
None
|
See :func:fairmedfm.evaluate for details.
dice_gap ¶
dice_gap(
dice=None, *, sensitive_features, bins=None, **masks
)
Largest minus smallest group mean Dice (delta_dice; 0 is fair).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dice
|
Any
|
Dice score per sample. Alternatively pass |
None
|
sensitive_features
|
Any
|
group of each sample, as in the classification functions. |
required |
bins
|
Optional[Bins]
|
groups for continuous attributes, e.g. |
None
|
**masks
|
Any
|
|
{}
|
worst_group_dice ¶
worst_group_dice(
dice=None, *, sensitive_features, bins=None, **masks
)
Lowest group mean Dice (min_dice; higher is better).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dice
|
Any
|
Dice score per sample. Alternatively pass |
None
|
sensitive_features
|
Any
|
group of each sample, as in the classification functions. |
required |
bins
|
Optional[Bins]
|
groups for continuous attributes, e.g. |
None
|
**masks
|
Any
|
|
{}
|
dice_std ¶
dice_std(
dice=None, *, sensitive_features, bins=None, **masks
)
Standard deviation of the group mean Dice scores (std_dice; 0 is fair).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dice
|
Any
|
Dice score per sample. Alternatively pass |
None
|
sensitive_features
|
Any
|
group of each sample, as in the classification functions. |
required |
bins
|
Optional[Bins]
|
groups for continuous attributes, e.g. |
None
|
**masks
|
Any
|
|
{}
|
dice_skewness ¶
dice_skewness(
dice=None, *, sensitive_features, bins=None, **masks
)
(1 - worst group Dice) / (1 - best group Dice) (skewness_dice; 1 is fair, NaN if a group is perfect).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dice
|
Any
|
Dice score per sample. Alternatively pass |
None
|
sensitive_features
|
Any
|
group of each sample, as in the classification functions. |
required |
bins
|
Optional[Bins]
|
groups for continuous attributes, e.g. |
None
|
**masks
|
Any
|
|
{}
|
equity_scaled_dice ¶
equity_scaled_dice(
dice=None, *, sensitive_features, bins=None, **masks
)
Mean Dice divided by 1 + the standard deviation of group means (es_dice; higher is better).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dice
|
Any
|
Dice score per sample. Alternatively pass |
None
|
sensitive_features
|
Any
|
group of each sample, as in the classification functions. |
required |
bins
|
Optional[Bins]
|
groups for continuous attributes, e.g. |
None
|
**masks
|
Any
|
|
{}
|
Full reports¶
evaluate ¶
evaluate(
y_true,
y_score,
sensitive_features,
*,
pos_label=None,
score_type="auto",
score_column=None,
bins=None,
intersectional=False,
)
Fairness of a binary classifier across the groups of one or more sensitive attributes.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
y_true
|
Any
|
ground truth per sample: 0/1, booleans, one-hot rows, or any labels together with |
required |
y_score
|
Any
|
model output per sample: positive-class probabilities, logits, or a (samples, classes) array of probabilities or logits. Lists, NumPy arrays, pandas objects and PyTorch tensors all work. |
required |
sensitive_features
|
Any
|
a pandas DataFrame (one column per attribute), a dict of name to values, a Series, or one array. Values can be strings or numbers; missing values exclude the sample for that attribute. |
required |
pos_label
|
Any
|
the positive class in |
None
|
score_type
|
str
|
|
'auto'
|
score_column
|
Optional[int]
|
column of the positive class when |
None
|
bins
|
Optional[Bins]
|
how to group continuous attributes, e.g. |
None
|
intersectional
|
bool
|
also evaluate the combination of all attributes (e.g. |
False
|
Returns:
| Name | Type | Description |
|---|---|---|
A |
FairnessReport
|
class: |
FairnessReport
|
|
|
FairnessReport
|
(TPR gap) and |
evaluate_segmentation ¶
evaluate_segmentation(
sensitive_features,
*,
dice=None,
pred_masks=None,
true_masks=None,
label=None,
mask_threshold=0.5,
empty_score=1.0,
bins=None,
intersectional=False,
)
Fairness of a segmentation model across the groups of one or more sensitive attributes.
Give either per-sample Dice scores (dice) or predicted and ground-truth masks (pred_masks and
true_masks), from which Dice is computed per sample.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
sensitive_features
|
Any
|
as in :func: |
required |
dice
|
Any
|
Dice score in [0, 1] per sample (image or volume). |
None
|
pred_masks
|
Any
|
one predicted mask per sample: a list of arrays or tensors, a stacked array, or file paths
( |
None
|
true_masks
|
Any
|
one ground-truth mask per sample, in the same forms. |
None
|
label
|
Any
|
the class to evaluate in multi-class masks; by default any non-zero value is foreground. |
None
|
mask_threshold
|
float
|
threshold for probability masks. |
0.5
|
empty_score
|
float
|
Dice when both masks of a sample are empty (default 1.0, a correct empty prediction). The
benchmark trainer's |
1.0
|
bins
|
Optional[Bins]
|
as in :func: |
None
|
intersectional
|
bool
|
as in :func: |
False
|
Returns:
| Name | Type | Description |
|---|---|---|
A |
FairnessReport
|
class: |
FairnessReport
|
|
FairnessReport ¶
Result of :func:evaluate or :func:evaluate_segmentation.
Attributes:
| Name | Type | Description |
|---|---|---|
task |
|
|
summary |
one row per sensitive attribute with the fairness metrics (see the metric reference). |
|
by_group |
one row per (attribute, group) with the group's sample count and metrics. Groups that could not
be evaluated have a |
|
overall |
metrics on all samples. |
|
warnings |
notes about how the input was interpreted or which groups were skipped. |
|
metadata |
how the input was read, e.g. the score transform or the positive label. |
Building blocks¶
binary_classification_report ¶
binary_classification_report(
prob, label, threshold=0.5, suffix=""
)
AUC, accuracy, BCE, ECE, TPR, TNR and confusion counts at one decision threshold.
expected_calibration_error ¶
expected_calibration_error(
prob,
label,
num_bins=10,
metric_variant="abs",
quantile_bins=False,
)
Calibration error: the sample-weighted mean, over bins of prob, of |mean prob - fraction positive|.
Bins are num_bins equal-width intervals over the range of prob (pandas.cut), or equal-count bins
with quantile_bins=True. metric_variant="squared" averages squared differences and "rmse" takes
the square root of that. See Guo et al. (2017), https://arxiv.org/abs/1706.04599, and Nixon et al. (2019),
https://arxiv.org/abs/1904.01685.
binary_cross_entropy ¶
binary_cross_entropy(prob, label)
Mean binary cross-entropy, with log terms clamped at -100 as in torch.nn.BCELoss.
find_threshold ¶
find_threshold(prob, label)
Decision threshold with the highest F1 score on these samples (the lowest such threshold on ties).
Choosing the operating point by F1 follows the chest X-ray fairness evaluations of Seyyed-Kalantari et al. (Nature Medicine, 2021) and Zhang et al. (CHIL, 2022).
Earlier interfaces¶
classification_fairness and segmentation_fairness from version 0.1 are deprecated: they emit a
FutureWarning and will be removed in 1.0. Use evaluate, evaluate_segmentation or the single metrics instead.
They take one sensitive attribute, require 0/1 labels and positive-class probabilities, and raise an error for a
group with only one label.
classification_fairness ¶
classification_fairness(prob, label, group)
Fairness of a binary classifier across the groups of one sensitive attribute.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
prob
|
ArrayLike
|
positive-class probability for each sample. |
required |
label
|
ArrayLike
|
ground-truth label (0 or 1) for each sample. |
required |
group
|
Sequence[Any]
|
sensitive attribute value for each sample, e.g. |
required |
Deprecated since 0.4.1 and to be removed in 1.0: use :func:fairmedfm.evaluate, which accepts more input forms
and reports groups it cannot evaluate instead of failing, or a single metric such as :func:fairmedfm.auc_gap.
Returns:
| Type | Description |
|---|---|
Dict[str, Any]
|
|
Dict[str, Any]
|
|
Dict[str, Any]
|
minus the smallest group value. |
Dict[str, Any]
|
|
Dict[str, Any]
|
|
Dict[str, Any]
|
|
segmentation_fairness ¶
segmentation_fairness(dice, group)
Fairness of a segmentation model from per-sample Dice scores across the groups of one attribute.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
dice
|
ArrayLike
|
Dice similarity coefficient in [0, 1] for each sample (image or volume). |
required |
group
|
Sequence[Any]
|
sensitive attribute value for each sample; two or more groups. |
required |
Deprecated since 0.4.1 and to be removed in 1.0: use :func:fairmedfm.evaluate_segmentation or a single metric
such as :func:fairmedfm.dice_gap.
Returns:
| Type | Description |
|---|---|
Dict[str, Any]
|
|
Dict[str, Any]
|
|
Dict[str, Any]
|
group has a mean Dice of exactly 1), |
Dict[str, Any]
|
|
Dict[str, Any]
|
|
evaluate_binary, organize_results and evaluate_seg keep the interfaces of the original benchmark code and
are used by its trainers. evaluate_seg returns inf for skewness_dice when the best group's mean Dice is 1 and
lets NaN Dice scores propagate, as the original did.
evaluate_binary ¶
evaluate_binary(pred, Y, A)
Overall metrics and per-group metric lists (groups in sorted order).
organize_results ¶
organize_results(overall_metrics, subgroup_metrics)
Fairness summary from the output of :func:evaluate_binary.
evaluate_seg ¶
evaluate_seg(dsc_list, sensitive_list)
Segmentation fairness summary as logged by the trainers; see :func:segmentation_fairness.
Unlike :func:segmentation_fairness, skewness_dice is inf when the best group has a mean Dice of 1,
and NaN Dice scores propagate into the means instead of raising.