Soft labels and annotator proportions¶
When the reference is soft (the proportion of annotators who chose a label, or a calibrated probability), the Boolean conjunction that forms the cell matrices is replaced by a t-norm:
im = IndicatorMatrix(Y_soft, P_soft, task="multilabel", tnorm="product")
im.compute("f1", "exemplar")
A worked example¶
Five simulated annotators label 400 examples, each correct 80% of the time. The soft label is the proportion of annotators voting positive; the model produces a score in \([0,1]\).
import numpy as np
from aggmetrics import IndicatorMatrix
rng = np.random.default_rng(0)
n = 400
truth = (rng.random(n) < 0.3).astype(int)
annotators = np.where(rng.random((n, 5)) < 0.8, truth[:, None], 1 - truth[:, None])
soft_y = annotators.mean(axis=1) # in {0, 0.2, ..., 1}
score = np.clip(0.55 * truth + 0.45 * rng.random(n), 0, 1)
im = IndicatorMatrix(soft_y, score, task="binary", tnorm="product")
im.compute("f1", "micro") # 0.5331
Thresholding both at 0.5 and scoring the hard labels gives \(F_1 = 0.892\). The two numbers are not comparable, and the soft one is lower for a reason: with a t-norm, uncertainty counts as partial error. A score of 0.6 against a label of 0.8 contributes 0.48 to the true positives and parts of the mass to false positives and false negatives. The soft cell matrices are the expected counts if the label and the prediction were independent Bernoulli variables with these probabilities. They are not counts of examples, and ratios of expected counts are not expected values of the ratios.
Why the product¶
Only the product t-norm preserves the marginals: the soft true positives and false negatives add up to the soft count of positives, whatever the predictions are. On this example:
T-norm |
\(tp + fn\) |
|
|---|---|---|
product |
137.60 (equals |
0.0 |
Gödel (minimum) |
187.62 |
0.5 |
Łukasiewicz |
87.58 |
0.5 |
With the Gödel or Łukasiewicz t-norms the number of positives implied by the cells is not the
number of positives in the data, so measures such as recall are computed against a different
population. marginal_defect returns the largest violation over a grid on \([0,1]^2\) and is 0
only for the product.
The pointwise order of t-norms (Łukasiewicz \(\le\) product \(\le\) Gödel) applies to all four cell matrices in the same direction, so it says nothing about the direction in which a ratio of them moves. On this example the \(F_1\) is 0.627, 0.533 and 0.561 under the three.
Other t-norms¶
Any callable \(T(a, b)\) can be passed as tnorm. aggmetrics.tnorms.hamacher(gamma) builds the
Hamacher family; gamma = 1 is the product, and other values depart from marginal consistency:
from aggmetrics.tnorms import hamacher
from aggmetrics import marginal_defect
marginal_defect(hamacher(1.0)) # 0.0
marginal_defect(hamacher(2.0)) # 0.101
IndicatorMatrix(soft_y, score, task="binary", tnorm=hamacher(2.0))
Soft labels are not the same as predicted probabilities¶
A predicted probability matrix passed without tnorm is thresholded (multilabel, at
threshold, 0.5 by default) or argmaxed (multiclass) before the cells are formed. Pass tnorm
only when you want the soft calculation above. Soft predictions with a hard reference are also
handled by the t-norm path: a hard label is a soft label in \(\{0,1\}\).