mlebench/competitions/rsna-breast-cancer-detection/grade.py (45 lines of code) (raw):

import pandas as pd from mlebench.grade_helpers import InvalidSubmissionError def pfbeta(labels, predictions, beta): """ Adapted from https://www.kaggle.com/code/sohier/probabilistic-f-score adaptations: code formatting, this docstring. """ y_true_count = 0 ctp = 0 cfp = 0 for idx in range(len(labels)): prediction = min(max(predictions[idx], 0), 1) if labels[idx]: y_true_count += 1 ctp += prediction else: cfp += prediction beta_squared = beta * beta c_precision = ctp / (ctp + cfp) c_recall = ctp / y_true_count if c_precision > 0 and c_recall > 0: result = ( (1 + beta_squared) * (c_precision * c_recall) / (beta_squared * c_precision + c_recall) ) return result else: return 0 def prepare_for_metric(submission: pd.DataFrame, answers: pd.DataFrame) -> dict: id_col = "prediction_id" target_col = "cancer" assert id_col in answers.columns, f"{id_col} not in answers" assert target_col in answers.columns, f"{target_col} not in answers" if id_col not in submission.columns: raise InvalidSubmissionError(f"{id_col} not in submission") if target_col not in submission.columns: raise InvalidSubmissionError(f"{target_col} not in submission") if len(submission) != len(answers): raise InvalidSubmissionError("submission and answers have different lengths") submission = submission.sort_values(by=id_col) answers = answers.sort_values(by=id_col) if (submission[id_col].values != answers[id_col].values).any(): raise InvalidSubmissionError(f"{id_col} not aligned") labels = answers[target_col].to_numpy() predictions = submission[target_col].to_numpy() return {"labels": labels, "predictions": predictions} def grade(submission: pd.DataFrame, answers: pd.DataFrame) -> float: pf1_inputs = prepare_for_metric(submission, answers) # F1 score, so beta=1; https://www.kaggle.com/competitions/rsna-breast-cancer-detection/discussion/370123 score = pfbeta(**pf1_inputs, beta=1) return score