В течение последних нескольких недель я работал над созданием модели склонности на уровне пользователя, которую мы можем использовать в нашем процессе автоматического назначения ставок Google PPC. В настоящее время у нас есть Exponea/Bloomreach в качестве нашего CDXP, однако возможности прогнозной аналитики этого инструмента слишком ограничены, на мой вкус. Преимущество этого инструмента (на мой взгляд) заключается в том, что он легко подключается к различным рекламным платформам, если вы можете вводить свои данные и отслеживать события на своем веб-сайте. В любом случае, этот блог не об Exponea или моделировании на уровне пользователя — он о матрице путаницы.
Матрица путаницы — отличный способ понять производительность модели. Вы можете получить много диагностической статистики из 4 ячеек. В стандартной задаче бинарной классификации у вас есть два состояния — Фактическое и Прогнозируемое, и в каждом из них есть Истина или Ложь.

Я использую Exponea для создания модели конверсии на уровне пользователя. Однако статистика, которую я использовал для оценки производительности модели, там не была доступна. Поэтому я решил написать функцию Python, которая вычисляла бы все возможные статистические данные, которые мне понадобятся, из матрицы путаницы, если я ввожу в нее матрицу путаницы. Я мог бы использовать sklearn, но тогда мне нужно было бы импортировать метрики, а затем ссылаться на функцию для каждой статистики, и, давайте будем честными, почему нет только одной функции, которая выдает всю статистику, пока вы нажимаете y и y_pred или матрица путаницы?!

Итак, пока у вас есть матрица путаницы, которая представляет собой массив и выглядит так, как показано ниже (я использовал модели статистики pred_table), мой код будет работать нормально и возвращать словарь со статистикой из матрицы путаницы.

def model_diagnostic_stats(confusion_matrix):
    tp = confusion_matrix[1,1]
    tn = confusion_matrix[0,0]
    fp = confusion_matrix[0,1]
    fn = confusion_matrix[1,0]
    
    p = tp + fn
    n = fp + tn
    pp = tp + fp
    pn = fn + tn
    
    diagnostic_dict = {   
    'recall' : tp/p,
    'false_neg_rate' : fn/p,
    'false_pos_rate' : fp/n,
    'true_neg_rate' : tn/n,
    'positive_liklihood_ratio' : (tp/p)/(fp/n),
    'neg_liklihood_rate' : (fn/p)/(tn/n),
    'precision' : tp/pp,
    'false_omission_rate' : fn/pn,
    'false_discovery_rate' : fp/pp,
    'neg_pred_value' : tn/pn,
    'markedness' : (tp/pp)+(tn/pn)-1,
    'diagnostic_odds_ration' : ((tp/p)/(fp/n))/( (fn/p)/(tn/n)),
    'informedness' : (tp/p)+(tn/n)-1,
    'prevalence_threshold' : (sqrt((tp/p)*(fp/n))-(fp/n))/((tp/p)-(fp/n)),
    'prevalence' : p/(p+n),
    'accuracy' : (tp+tn)/(p+n),
    'balanced_accuracy' : ((tp/p)+(tn/n))/2,
    'F1_score' : 2*tp/(2*tp+fp+fn),
    'fowlkes_mallows_index' : sqrt((tp/pp)*(tp/p)),
    'jaccard_index' : tp/(tp+fn+fp),
    }
    
    return diagnostic_dict

Теперь, когда у меня есть диагностическая статистика модели, я могу судить, насколько моя модель лучше или хуже той, которую я построил в Exponea.