Belle II Software development
scores.py
1
8
9"""This module contains score functions to quantify the quality of a classification
10
11All score function have the signature
12def score(truths, predictions):
13
14comparing the truth information against a model and return a numerical value.
15"""
16
17import numpy as np
18
19
20def data_amount(truths, predictions):
21 """Score function: amount of data after a selection"""
22 n_predictions = len(predictions)
23 n_truths = len(truths)
24
25 if n_predictions != n_truths:
26 raise ValueError("Prediction and truth do not represent the same amount of data.")
27
28 return n_predictions
29
30
31def signal_amount(truths, predictions):
32 """Score function: amount of signal of a classification"""
33 return np.count_nonzero(truths)
34
35
36def accepted_amount(truths, predictions):
37 """Score function: amount accepted of a classification"""
38 return np.count_nonzero(predictions)
39
40
41def accepted_signal_amount(truths, predictions):
42 """Score function: amount of accepted signal of a classification"""
43 return np.count_nonzero(predictions * truths)
44
45
46# Functions independent of the data model
47
48# Amounts #
49# ####### #
50
51def background_amount(truths, predictions):
52 """Score function: amount of background of a classification"""
53 return data_amount(truths, predictions) - signal_amount(truths, predictions)
54
55
56def rejected_amount(truths, predictions):
57 """Score function: amount rejected of a classification"""
58 return data_amount(truths, predictions) - accepted_amount(truths, predictions)
59
60
61def rejected_signal_amount(truths, predictions):
62 """Score function: amount of rejected signal of a classification"""
63 return signal_amount(truths, predictions) - accepted_signal_amount(truths, predictions)
64
65
66def accepted_background_amount(truths, predictions):
67 """Score function: amount of accepted background of a classification"""
68 return accepted_amount(truths, predictions) - accepted_signal_amount(truths, predictions)
69
70
71def rejected_background_amount(truths, predictions):
72 """Score function: amount of rejected background of a classification"""
73 return background_amount(truths, predictions) - accepted_background_amount(truths, predictions)
74
75
76# Ratios #
77# ###### #
78
79def purity(truths, predictions):
80 """Score function: purity = accepted signal / accepted"""
81 return np.divide(1.0 * accepted_signal_amount(truths, predictions), accepted_amount(truths, predictions))
82
83
84def efficiency(truths, predictions):
85 """Score function: efficiency = accepted signal / signal"""
86 return np.divide(1.0 * accepted_signal_amount(truths, predictions), signal_amount(truths, predictions))
87
88
89def accuracy(truths, predictions):
90 """Score function: accuracy = (accepted signal + rejected background) / total"""
91 n_correct = accepted_signal_amount(truths, predictions) + rejected_background_amount(truths, predictions)
92 n_data = data_amount(truths, predictions)
93 return np.divide(1.0 * n_correct, n_data)
94
95
96def background_rejection(truths, predictions):
97 """Score function: background rejection = rejected background / background"""
98 n_background = background_amount(truths, predictions)
99 n_rejected_background = rejected_background_amount(truths, predictions)
100 return np.divide(1.0 * n_rejected_background, n_background)
101
102
103def signal_background_ratio(truths, predictions):
104 """Score function: background / signal"""
105 n_data = data_amount(truths, predictions)
106 n_signal = signal_amount(truths, predictions)
107 n_background = n_data - n_signal
108 return np.divide(1.0 * n_signal, n_background)