Logistic Classification
Threshold Probabilities
Convert predicted probabilities to 0/1 class labels by thresholding.
Default threshold 0.5: class = 1 if p>=0.5 else 0. A second loop at 0.7
shows how raising the threshold tightens the positive-class criterion.
Library: (np.array(probs) >= 0.5).astype(int). RESULT: labels at 0.5.
By hand
probs=[0.1,0.4,0.6,0.75,0.85,0.3]. At 0.5: [0,0,1,1,1,0]. At 0.7: [0,0,0,1,1,0] — p=0.6 flips from 1 to 0, p=0.4 stays 0.
naive.py
Replay: real traced execution (multi-file project)
probs = [0.1, 0.4, 0.6, 0.75, 0.85, 0.3]
labels = []
for p in probs:
labels.append(1 if p >= 0.5 else 0)
labels_07 = []
for p in probs:
labels_07.append(1 if p >= 0.7 else 0)
print('RESULT:', labels)
probs ← [0.1, 0.4, 0.6, 0.75, 0.85, 0.3]
1probs = [0.1, 0.4, 0.6, 0.75, 0.85, 0.3]2labels = []values this step[0.1, 0.4, 0.6, 0.75, 0.85, 0.3]probslabels ← []
1probs = [0.1, 0.4, 0.6, 0.75, 0.85, 0.3]2labels = []3for p in probs:values this step[]labelsp ← 0.1
2labels = []3for p in probs:4 labels.append(1 if p >= 0.5 else 0)values this step0.1plabels ← [0]
3for p in probs:4 labels.append(1 if p >= 0.5 else 0)5labels_07 = []values this step[] → [0]labelsp ← 0.4
2labels = []3for p in probs:4 labels.append(1 if p >= 0.5 else 0)values this step0.1 → 0.4plabels ← [0, 0]
3for p in probs:4 labels.append(1 if p >= 0.5 else 0)5labels_07 = []values this step[0] → [0, 0]labelsp ← 0.6
2labels = []3for p in probs:4 labels.append(1 if p >= 0.5 else 0)values this step0.4 → 0.6plabels ← [0, 0, 1]
3for p in probs:4 labels.append(1 if p >= 0.5 else 0)5labels_07 = []values this step[0, 0] → [0, 0, 1]labelsp ← 0.75
2labels = []3for p in probs:4 labels.append(1 if p >= 0.5 else 0)values this step0.6 → 0.75plabels ← [0, 0, 1, 1]
3for p in probs:4 labels.append(1 if p >= 0.5 else 0)5labels_07 = []values this step[0, 0, 1] → [0, 0, 1, 1]labelsp ← 0.85
2labels = []3for p in probs:4 labels.append(1 if p >= 0.5 else 0)values this step0.75 → 0.85plabels ← [0, 0, 1, 1, 1]
3for p in probs:4 labels.append(1 if p >= 0.5 else 0)5labels_07 = []values this step[0, 0, 1, 1] → [0, 0, 1, 1, 1]labelsp ← 0.3
2labels = []3for p in probs:4 labels.append(1 if p >= 0.5 else 0)values this step0.85 → 0.3plabels ← [0, 0, 1, 1, 1, 0]
3for p in probs:4 labels.append(1 if p >= 0.5 else 0)5labels_07 = []values this step[0, 0, 1, 1, 1] → [0, 0, 1, 1, 1, 0]labelsfor p in probs:
2labels = []3for p in probs:4 labels.append(1 if p >= 0.5 else 0)labels_07 ← []
4 labels.append(1 if p >= 0.5 else 0)5labels_07 = []6for p in probs:values this step[]labels_07p ← 0.1
5labels_07 = []6for p in probs:7 labels_07.append(1 if p >= 0.7 else 0)values this step0.3 → 0.1plabels_07 ← [0]
6for p in probs:7 labels_07.append(1 if p >= 0.7 else 0)8print('RESULT:', labels)values this step[] → [0]labels_07p ← 0.4
5labels_07 = []6for p in probs:7 labels_07.append(1 if p >= 0.7 else 0)values this step0.1 → 0.4plabels_07 ← [0, 0]
6for p in probs:7 labels_07.append(1 if p >= 0.7 else 0)8print('RESULT:', labels)values this step[0] → [0, 0]labels_07p ← 0.6
5labels_07 = []6for p in probs:7 labels_07.append(1 if p >= 0.7 else 0)values this step0.4 → 0.6plabels_07 ← [0, 0, 0]
6for p in probs:7 labels_07.append(1 if p >= 0.7 else 0)8print('RESULT:', labels)values this step[0, 0] → [0, 0, 0]labels_07p ← 0.75
5labels_07 = []6for p in probs:7 labels_07.append(1 if p >= 0.7 else 0)values this step0.6 → 0.75plabels_07 ← [0, 0, 0, 1]
6for p in probs:7 labels_07.append(1 if p >= 0.7 else 0)8print('RESULT:', labels)values this step[0, 0, 0] → [0, 0, 0, 1]labels_07p ← 0.85
5labels_07 = []6for p in probs:7 labels_07.append(1 if p >= 0.7 else 0)values this step0.75 → 0.85plabels_07 ← [0, 0, 0, 1, 1]
6for p in probs:7 labels_07.append(1 if p >= 0.7 else 0)8print('RESULT:', labels)values this step[0, 0, 0, 1] → [0, 0, 0, 1, 1]labels_07p ← 0.3
5labels_07 = []6for p in probs:7 labels_07.append(1 if p >= 0.7 else 0)values this step0.85 → 0.3plabels_07 ← [0, 0, 0, 1, 1, 0]
6for p in probs:7 labels_07.append(1 if p >= 0.7 else 0)8print('RESULT:', labels)values this step[0, 0, 0, 1, 1] → [0, 0, 0, 1, 1, 0]labels_07for p in probs:
5labels_07 = []6for p in probs:7 labels_07.append(1 if p >= 0.7 else 0)stdout ← RESULT: [0, 0, 1, 1, 1, 0]
7 labels_07.append(1 if p >= 0.7 else 0)8print('RESULT:', labels)values this stepRESULT: [0, 0, 1, 1, 1, 0]stdout
With NumPy
(np.array(probs) >= threshold).astype(int) applies the comparison
element-wise and converts the boolean array to ints in one expression.
library.py
import numpy as np
from dalib.display import set_display
set_display()
probs = [0.1, 0.4, 0.6, 0.75, 0.85, 0.3]
labels = (np.array(probs) >= 0.5).astype(int).tolist()
labels_07 = (np.array(probs) >= 0.7).astype(int).tolist()
print('threshold=0.5:', labels)
print('threshold=0.7:', labels_07)
print('RESULT:', labels)
threshold=0.5: [0, 0, 1, 1, 1, 0]
threshold=0.7: [0, 0, 0, 1, 1, 0]
RESULT: [0, 0, 1, 1, 1, 0]
Implementation notes
- Threshold 0.5 is the default: it minimises classification error when classes are balanced and the model is well-calibrated.
- Raising the threshold (e.g. to 0.7) requires higher confidence to predict positive — reduces false positives but increases false negatives. Lowering it does the opposite. This trade-off is the precision/recall curve.
- Cross-reference:
logistic-predict-given-weights(this chapter) computes the probabilities that are thresholded here. - Cross-reference:
log-loss-small(this chapter) evaluates probabilities before thresholding — log loss works on raw probs, not 0/1 labels.