def get_thresholds_greedy(
    scores: np.ndarray,
    labels: np.ndarray,
    score_fn: Callable,
    num_iterations: int = 100,
    num_thresholds: int = 100,
    thresholds: np.ndarray = None,
    patience: int = 3,
    atol: float = 0.01,
) -> Tuple[float, List[float]]:
    """Finds best thresholds for classification task with brute-force algorithm.

    Args:
        scores: estimated per-class scores/probabilities predicted by the model
        labels: ground truth labels
        score_fn: callable function, based on (scores, labels, thresholds)
        num_iterations: number of iteration for brute-force algorithm
        num_thresholds: number of thresholds ot try for each class
        thresholds: baseline thresholds, which we want to optimize
        patience: maximum number of iteration before early stop exit
        atol: minimum required improvement per iteration for early stop exit

    Returns:
        tuple with best found objective score and per-class thresholds
    """
    num_classes = scores.shape[1]
    if thresholds is None:
        thresholds = [0.5] * num_classes
    best_metric = score_fn(scores, labels, thresholds)
    iteration_metrics = []

    for i in range(num_iterations):
        if len(iteration_metrics) >= patience:
            if best_metric < iteration_metrics[i - patience] + atol:
                break

        for class_index in range(num_classes):
            current_thresholds = thresholds.copy()
            class_scores = []
            class_thresholds = np.linspace(
                scores[:, class_index].min(),
                scores[:, class_index].max(),
                num=num_thresholds,
            )

            for threshold in class_thresholds:
                current_thresholds[class_index] = threshold
                class_score = score_fn(scores, labels, current_thresholds)
                class_scores.append(class_score)

            best_class_score = np.max(class_scores)
            best_score_index = np.argmax(class_scores)
            if best_class_score > best_metric:
                best_metric = best_class_score
                thresholds[class_index] = class_thresholds[best_score_index]
        iteration_metrics.append(best_metric)

    return best_metric, thresholds
Finds best thresholds for classification task with brute-force algorithm.

    Args:
        scores: estimated per-class scores/probabilities predicted by the model
        labels: ground truth labels
        score_fn: callable function, based on (scores, labels, thresholds)
        num_iterations: number of iteration for brute-force algorithm
        num_thresholds: number of thresholds ot try for each class
        thresholds: baseline thresholds, which we want to optimize
        patience: maximum number of iteration before early stop exit
        atol: minimum required improvement per iteration for early stop exit

    Returns:
        tuple with best found objective score and per-class thresholds
    
catalyst/contrib/utils/thresholds.py