riix.metrics
module for computing metrics for rating system experiments
1"""module for computing metrics for rating system experiments""" 2 3import numpy as np 4 5 6def binary_accuracy(probs: np.ndarray, outcomes: np.ndarray) -> float: 7 """compute accuracy where outcomes is binary ties count for half""" 8 pos_mask = probs > 0.5 9 neg_mask = probs < 0.5 10 draw_mask = probs == 0.5 11 correct = outcomes[pos_mask].sum() + (1.0 - outcomes[neg_mask]).sum() + 0.5 * draw_mask.sum() 12 return correct / probs.shape[0] 13 14 15def accuracy_without_draws(probs: np.ndarray, outcomes: np.ndarray) -> float: 16 """compute binary accuracy after first filtering out rows where the label is a draw""" 17 draw_mask = outcomes == 0.5 18 probs = probs[~draw_mask] 19 outcomes = outcomes[~draw_mask] 20 return binary_accuracy(probs, outcomes) 21 22 23def accuracy_with_draws(probs: np.ndarray, outcomes: np.ndarray, draw_margin=0.0) -> float: 24 """computes accuracy where probs within draw_margin of 0.5 are treated as draw predictions""" 25 pos_pred_mask = probs > (0.5 + draw_margin) 26 neg_pred_mask = probs < (0.5 - draw_margin) 27 draw_pred_mask = np.abs(probs - 0.5) <= draw_margin 28 correct = outcomes[pos_pred_mask].sum() 29 correct += (1.0 - outcomes)[neg_pred_mask].sum() 30 correct += (outcomes[draw_pred_mask] == 0.5).sum() 31 return correct / outcomes.shape[0] 32 33 34def binary_log_loss(probs: np.ndarray, outcomes: np.ndarray, eps: float = 1e-6) -> float: 35 """compute log loss where outcome is binary 1.0 or 0.0""" 36 probs = np.clip(probs, eps, 1 - eps) 37 loss_array = -(np.log(probs) * outcomes) - (np.log(1.0 - probs) * (1.0 - outcomes)) 38 return loss_array.mean() 39 40 41def brier_score(probs: np.ndarray, outcomes: np.ndarray) -> float: 42 """compute the brier score, which is equivalent to the MSE""" 43 return np.square(probs - outcomes).mean() 44 45 46def binary_metrics_suite(probs: np.ndarray, outcomes: np.ndarray): 47 """a wrapper class for running a bunch of binary metrics""" 48 metrics = { 49 'accuracy': float(binary_accuracy(probs, outcomes)), 50 'accuracy_without_draws': float(accuracy_without_draws(probs, outcomes)), 51 'log_loss': float(binary_log_loss(probs, outcomes)), 52 'brier_score': float(brier_score(probs, outcomes)), 53 } 54 return metrics
def
binary_accuracy(probs: numpy.ndarray, outcomes: numpy.ndarray) -> float:
7def binary_accuracy(probs: np.ndarray, outcomes: np.ndarray) -> float: 8 """compute accuracy where outcomes is binary ties count for half""" 9 pos_mask = probs > 0.5 10 neg_mask = probs < 0.5 11 draw_mask = probs == 0.5 12 correct = outcomes[pos_mask].sum() + (1.0 - outcomes[neg_mask]).sum() + 0.5 * draw_mask.sum() 13 return correct / probs.shape[0]
compute accuracy where outcomes is binary ties count for half
def
accuracy_without_draws(probs: numpy.ndarray, outcomes: numpy.ndarray) -> float:
16def accuracy_without_draws(probs: np.ndarray, outcomes: np.ndarray) -> float: 17 """compute binary accuracy after first filtering out rows where the label is a draw""" 18 draw_mask = outcomes == 0.5 19 probs = probs[~draw_mask] 20 outcomes = outcomes[~draw_mask] 21 return binary_accuracy(probs, outcomes)
compute binary accuracy after first filtering out rows where the label is a draw
def
accuracy_with_draws(probs: numpy.ndarray, outcomes: numpy.ndarray, draw_margin=0.0) -> float:
24def accuracy_with_draws(probs: np.ndarray, outcomes: np.ndarray, draw_margin=0.0) -> float: 25 """computes accuracy where probs within draw_margin of 0.5 are treated as draw predictions""" 26 pos_pred_mask = probs > (0.5 + draw_margin) 27 neg_pred_mask = probs < (0.5 - draw_margin) 28 draw_pred_mask = np.abs(probs - 0.5) <= draw_margin 29 correct = outcomes[pos_pred_mask].sum() 30 correct += (1.0 - outcomes)[neg_pred_mask].sum() 31 correct += (outcomes[draw_pred_mask] == 0.5).sum() 32 return correct / outcomes.shape[0]
computes accuracy where probs within draw_margin of 0.5 are treated as draw predictions
def
binary_log_loss( probs: numpy.ndarray, outcomes: numpy.ndarray, eps: float = 1e-06) -> float:
35def binary_log_loss(probs: np.ndarray, outcomes: np.ndarray, eps: float = 1e-6) -> float: 36 """compute log loss where outcome is binary 1.0 or 0.0""" 37 probs = np.clip(probs, eps, 1 - eps) 38 loss_array = -(np.log(probs) * outcomes) - (np.log(1.0 - probs) * (1.0 - outcomes)) 39 return loss_array.mean()
compute log loss where outcome is binary 1.0 or 0.0
def
brier_score(probs: numpy.ndarray, outcomes: numpy.ndarray) -> float:
42def brier_score(probs: np.ndarray, outcomes: np.ndarray) -> float: 43 """compute the brier score, which is equivalent to the MSE""" 44 return np.square(probs - outcomes).mean()
compute the brier score, which is equivalent to the MSE
def
binary_metrics_suite(probs: numpy.ndarray, outcomes: numpy.ndarray):
47def binary_metrics_suite(probs: np.ndarray, outcomes: np.ndarray): 48 """a wrapper class for running a bunch of binary metrics""" 49 metrics = { 50 'accuracy': float(binary_accuracy(probs, outcomes)), 51 'accuracy_without_draws': float(accuracy_without_draws(probs, outcomes)), 52 'log_loss': float(binary_log_loss(probs, outcomes)), 53 'brier_score': float(brier_score(probs, outcomes)), 54 } 55 return metrics
a wrapper class for running a bunch of binary metrics