|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"""Directional Bias Amplification metric.""" |
|
|
|
import evaluate |
|
import datasets |
|
|
|
import numpy as np |
|
|
|
_DESCRIPTION = """ |
|
Directional Bias Amplification is a metric that captures the amount of bias (i.e., a conditional probability) that is amplified. |
|
This metric was introduced in the ICML 2021 paper "Directional Bias Amplification" (https://arxiv.org/abs/2102.12594). |
|
""" |
|
|
|
_KWARGS_DESCRIPTION = """ |
|
Args: |
|
predictions (`array` of `int`): Predicted task labels. Array of size n x |T|. n is number of samples, |T| is number of task labels. All values are binary 0 or 1. |
|
references (`array` of `int`): Ground truth task labels. Array of size n x |T|. n is number of samples, |T| is number of task labels. All values are binary 0 or 1. |
|
attributes(`array` of `int`): Ground truth attribute labels. Array of size n x |A|. n is number of samples, |A| is number of attribute labels. All values are binary 0 or 1. |
|
|
|
Returns |
|
bias_amplification(`float`): Bias amplification value. Minimum possible value is 0, and maximum possible value is 1.0. The higher the value, the more "bias" is amplified. |
|
disagg_bias_amplification (`array` of `float`): Array of size (number of unique attribute label values) x (number of unique task label values). Each array value represents the bias amplification of that particular task given that particular attribute. |
|
""" |
|
|
|
|
|
_CITATION = """ |
|
@inproceedings{wang2021biasamp, |
|
author = {Angelina Wang and Olga Russakovsky}, |
|
title = {Directional Bias Amplification}, |
|
booktitle = {International Conference on Machine Learning (ICML)}, |
|
year = {2021} |
|
} |
|
""" |
|
|
|
@evaluate.utils.file_utils.add_start_docstrings(_DESCRIPTION, _KWARGS_DESCRIPTION) |
|
class DirectionalBiasAmplification(evaluate.EvaluationModule): |
|
def _info(self): |
|
return evaluate.EvaluationModuleInfo( |
|
description=_DESCRIPTION, |
|
citation=_CITATION, |
|
inputs_description=_KWARGS_DESCRIPTION, |
|
features=datasets.Features( |
|
{ |
|
"predictions": datasets.Sequence(datasets.Value("int32")), |
|
"references": datasets.Sequence(datasets.Value("int32")), |
|
"attributes": datasets.Sequence(datasets.Value("int32")), |
|
} |
|
), |
|
reference_urls=["https://arxiv.org/abs/2102.12594"], |
|
) |
|
|
|
def _compute(self, predictions, references, attributes): |
|
|
|
task_preds, task_labels, attribute_labels = np.array(predictions), np.array(references), np.array(attributes) |
|
|
|
assert len(task_labels.shape) == 2 and len(attribute_labels.shape) == 2, 'Please read the shape of the expected inputs, which should be "num samples" by "num classification items"' |
|
assert len(task_labels) == len(attribute_labels) == len(task_preds), 'Please make sure the number of samples in the three input arrays is the same.' |
|
|
|
num_t, num_a = task_labels.shape[1], attribute_labels.shape[1] |
|
|
|
|
|
keep_indices = np.array(list(set(np.where(np.sum(task_labels_train, axis=1)>0)[0]).union(set(np.where(np.sum(attribute_labels_train, axis=1)>0)[0])))) |
|
task_labels_ind, attribute_labels_ind = task_labels[keep_indices], attribute_labels[keep_indices] |
|
|
|
|
|
p_at = np.zeros((num_a, num_t)) |
|
p_a_p_t = np.zeros((num_a, num_t)) |
|
num = len(task_labels) |
|
for a in range(num_a): |
|
for t in range(num_t): |
|
t_indices = np.where(task_labels_ind[:, t]==1)[0] |
|
a_indices = np.where(attribute_labels_ind[:, a]==1)[0] |
|
at_indices = set(t_indices)&set(a_indices) |
|
p_a_p_t[a][t] = (len(t_indices)/num)*(len(a_indices)/num) |
|
p_at[a][t] = len(at_indices)/num |
|
y_at = np.sign(p_at - p_a_p_t) |
|
|
|
|
|
t_cond_a = np.zeros((num_a, num_t)) |
|
that_cond_a = np.zeros((num_a, num_t)) |
|
for a in range(num_a): |
|
for t in range(num_t): |
|
t_cond_a[a][t] = np.mean(task_labels[:, t][np.where(attribute_labels[:, a]==1)[0]]) |
|
that_cond_a[a][t] = np.mean(task_preds[:, t][np.where(attribute_labels[:, a]==1)[0]]) |
|
delta_at = that_cond_a - t_cond_a |
|
|
|
values = y_at*delta_at |
|
val = np.nanmean(values) |
|
|
|
val, values |
|
return { |
|
"bias_amplification": val, |
|
"disagg_bias_amplification": values |
|
} |
|
|