Alexandre Marcondes
13/10/2021

Tradeoff entre precisão e recall: explorando o output de seu modelo de classificação

Photo by Lukas Blazek on Unsplash

Após realizar o treinamento de um modelo de classificação, é usual utilizarmos o método predict() para prever as classes em nossa base de teste, calcular as métricas em relação as classes reais e validar nosso modelo. É o famoso “fit-predict” que aprendemos nos tutoriais e cursos por aí. Porém, a verdade é que podemos explorar mais o output de nosso modelo utilizando a probabilidade prevista ao invés de utilizar diretamente as classe.

A ideia deste artigo é abrir os olhos para os seguintes pontos:

  • Como explorar melhor o output de seu modelo de classificação;
  • Entender o tradeoff entre precisão e recall.

Esses pontos são bastante importantes no cotidiano de um cientista de dados e, muitas vezes, não são explorados em cursos e tutoriais disponíveis na internet.

Métricas de classificação

Para dar sequência no tema, se faz necessário o entendimento de algumas das principais métricas de classificação. Neste texto são apresentadas três das métricas mais conhecidas para classificação: acurácia, precisão e recall.

A acurácia é, talvez, a métrica mais comum e mais intuitiva para modelos de classificação. Trata-se da fração das previsões realizadas pelo modelo que foram corretas e, para uma classificação binária, pode ser calculada por meio da relação abaixo:


Onde TP são os verdadeiros positivos (True Positives), TN são os verdadeiros negativos (True Negatives), FP são os falsos positivos (False Positives) e FN são os falsos negativos (False Negatives). A ideia da acurácia é bastante simples: quanto maior o número de acertos do modelo, seja de casos positivos ou negativos, maior será a acurácia.

Em diversos tipos de problemas a acurácia pode não ser interessante, principalmente nos casos onde os dados são desbalanceados. Suponha que a base de validação de um problema de classificação tenha 1000 amostras, destas, somente 5% (50 amostras) são positivas. Se o modelo simplesmente apontar que todas as amostras são negativas, a acurácia do modelo será de 95% - o que é um valor bastante alto. Porém, claramente o modelo não seria bom, visto que nenhum dos casos positivos foi descoberto. Este é um exemplo que ilustra bem onde a acurácia pode ser ineficaz.

A precisão contabiliza, dentre todos os positivos apontados pelo modelo, qual a fração destes que são de fato positivos. A equação abaixo ilustra como se calcula a precisão:


A terceira métrica é o recall, o qual mensura quantos casos positivos foram descobertos pelo modelo, dentre todos os casos positivos presentes em nossa base de validação. É, portanto, a divisão entre os verdadeiros positivos e a soma dos verdadeiros positivos e os positivos que foram apontado como negativos (falsos negativos), como descreve a equação abaixo:


O tradeoff entre precisão e recall

Observando as equações das métricas de precisão e recall, nota-se que são métricas que medem grandezas distintas. Além disso, comentamos quão negativo pode ser a escolha da acurácia como métrica de seleção de um modelo.

Neste ponto, vamos destacar as diferenças entre as métricas e como a sua avaliação correta é importante. Um aumento na precisão, em geral, pode trazer uma redução no número de positivos que é descoberto pelo modelo. Pode-se pensar que um modelo muito preciso raramente erra ao apontar um positivo, porém, como consequência, pode acabar apontando poucos positivos.

Vamos ilustrar com um exemplo: considere uma base com 10 mil clientes, dos quais 1% (100 clientes) são maus pagadores. Agora, considere duas situações:

  • Situação 1 - Suponha que seu modelo de classificação apontou que 50 clientes são maus pagadores. Dos 50 clientes, 40 deles são de fato maus pagadores. Temos, portanto, uma precisão de 80%, porém um recall de 40%. Então, estamos com uma precisão maior, pois 80% dos casos apontados pelo modelo são de fato positivos, porém o recall ficou abaixo, pois o modelo está apontando somente 40% dos maus pagadores;
  • Situação 2 - Suponha que seu modelo de classificação apontou que 160 clientes são maus pagadores. Dos 160 clientes, 70 deles são de fato maus pagadores. Temos portanto uma precisão de 44%, porém um recall de 70%. Então, estamos com um recall maior, pois o modelo está apontando 70% dos maus pagadores, porém a precisão ficou abaixo, pois somente 44% dos clientes que o modelo apontou como maus pagadores são maus pagadores de fato.

Nas duas situações acima, notamos uma troca que existe entre recall e tradeoff. Ao aumentar a precisão do modelo e ter um melhor percentual de acerto, temos o custo de aprovar mais maus pagadores. Ao aumentar o recall e barrar uma maior quantidade de maus pagadores, temos o custo de barrar uma maior quantidade de clientes bons neste grupo.

Essa troca que existe entre as métricas de precisão e recall é bastante conhecida no mundo do aprendizado de máquina e tem um nome: trata-se do tradeoff entre precisão e recall.

Mas afinal, qual é a melhor métrica para otimizar meu modelo?

A resposta sempre será: depende! Deve-se avaliar a natureza do problema e seus objetivos, assim pode-se definir a métrica principal de seleção do modelo. Abaixo temos um exemplo ilustrativo dessa escolha…

Na prática: a curva de precisão e recall com um exemplo

Vamos pensar em um caso prático, um problema de inadimplência, considerando dois cenários distintos. Ressaltando que neste caso um positivo é um cliente ruim, ou seja, um cliente com grandes chances de se tornar inadimplente.

  • Cenário 1 - Trata-se de uma empresa que busca diminuir seu percentual de inadimplência, pois os números estão muito altos. Então, espera-se que o modelo aprove uma parcela de clientes, porém aponte o máximo possível de clientes ruins, mesmo que isso signifique barrar alguns dos clientes bons. Portanto, nesse caso admite-se que o modelo aponte um maior número de falsos positivos em busca de uma redução da inadimplência e, consequentemente, espera-se uma precisão menor e um maior recall;
  • Cenário 2 - Trata-se de uma empresa nova, que está em busca de uma expansão em sua carteira de clientes e está disposta a arcar com os possíveis custos de falsos negativos, ou seja, clientes ruins que foram apontados como bons pelo modelo. Espera-se, portanto, um modelo que tenha maior precisão e aponte somente clientes com grandes chances de serem ruins, com o custo de não apontar um volume maior de clientes ruins.

Para simular estes cenários, vamos desenvolver um modelo simples de classificação. No trecho de código abaixo, cria-se um conjunto de dados de classificação com 80% de negativos e 20% de positivos. Para encaixar nos cenários acima, vamos considerar que se trata de uma base de clientes com 20% de inadimplentes.

Além disso, abaixo, também, treinamos um modelo simples utilizando o CatBoost. Como o objetivo aqui não é melhorar a performance do modelo, seguimos com o CatBoost com seus parâmetros padrão. Caso queira entender um pouco mais sobre o CatBoost e outros algoritmos de boosting, temos o melhor material disponível neste link.

Por fim, temos no código abaixo o script necessário para plotar a curva de precisão-recall variando com o limiar de probabilidade do modelo.

from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from catboost import CatBoostClassifier
from sklearn.metrics import accuracy_score, precision_score, recall_score
import pandas as pd
import matplotlib.pyplot as pltdef gera_listas_recall_precisao(y_true, y_proba):
   """
   Gera listas de de recall e precisão, considerando cortes em cada   percentil
   da probabilidade do modelo.
   """
   precision_list = []
   recall_list = []
   cortes = [i/100 for i in range(0, 100)]
   for corte in cortes:
       y_temp = []
       for pred in y_proba:
           if pred < corte:
               y_temp.append(0)
           else:
               y_temp.append(1)
       precision_list.append(precision_score(y_test, y_temp))
       recall_list.append(recall_score(y_test, y_temp))
   return precision_list, recall_listdef plot_precision_recall_vs_threshold(precisions, recalls, thresholds):
   """
   Plota o gráfico de precisão vs recall.
   """
   plt.figure(figsize=(8, 4))
   plt.title("Precisão e Recall como função do limiar de decisão", pad=15)
   plt.plot(thresholds, precisions, "b--", label="Precisão")
   plt.plot(thresholds, recalls, "g-", label="Recall")
   plt.ylabel("Score")
   plt.xlabel("Limiar de decisão")
   plt.legend(loc='best')# Criando o dataset sintético
X, y = make_classification(
   n_samples=50000, weights=[0.80, 0.20], n_redundant=2, n_informative=5, random_state=42, flip_y=0.15
)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# Treinando o classificador
clf = CatBoostClassifier()
clf.fit(X_train, y_train, verbose=0)
# Gerando as previsões
y_proba = clf.predict_proba(X_test)[:, 1]
# Plotando a curva de precisão vs recall
precision_list, recall_list = gera_listas_recall_precisao(y_test, y_proba)
plot_precision_recall_vs_threshold(precision_list, recall_list, cortes)


Como resultado do código acima temos a curva apresentada na figura abaixo, onde verificamos exatamente o comportamento de tradeoff entre precisão e recall que comentamos acima. Nota-se que ao aumentar o ponto de corte, aumentamos a precisão e diminuímos o recall.

Exemplo da curva de tradeoff entre precisão e recall


Ao definir um ponto de corte baixo de probabilidade
, aumentamos o número de clientes que são considerados inadimplentes, pois um cliente com uma probabilidade um pouco acima da média já seria considerado ruim. Neste caso, barraríamos grande parte dos clientes ruins, todavia, a consequência disso seria um aumento no número de falsos positivos, diminuindo assim nossa precisão e aumentando nosso recall. Assim, conclui-se que um limiar mais baixo na probabilidade seria o ideal para a empresa do cenário 1, a qual busca reduzir sua inadimplência, pois assim mais clientes seriam apontados como inadimplentes.

Ao definir um ponto de corte mais alto de probabilidade, diminuímos o número de clientes que são considerados inadimplentes pois, para ser considerado ruim, um cliente deve ter uma probabilidade muito alta apontada pelo modelo. Neste caso admitiríamos um número maior de clientes em nossa carteira, a maior parte dos positivos apontados pelo modelo seriam de fato inadimplentes (alta precisão), porém com a consequência do aumento do número de falsos negativos (baixo recall). Escolher um limiar alto de probabilidade coincide então com os objetivos do cenário 2, pois assim a taxa de admissão do modelo seria maior e a carteira teria um crescimento acelerado.

Vale ressaltar que nunca existirá um modelo perfeito. O processo de definição da política que define o que é um cliente ruim ou bom, baseado no output do modelo de classificação, é uma tarefa recorrente no cotidiano de um cientista de dados. Essa definição sempre deve levar em conta as características do negócio e quais são os objetivos com o modelo.

Conclusões

Neste artigo, exploramos um pouco da dinâmica existente entre precisão e recall em modelos de classificação. Além do que foi mencionado, para definir qual seria um bom ponto de corte, seria necessário um estudo mais aprofundado. Uma boa ideia seria, por exemplo, estimar os custos de um inadimplente e comparar com os ganhos previstos com um cliente bom, levando essa análise de tradeoff para um ponto de vista financeiro.

Ademais, vale mencionar que existem métricas além das que foram apresentadas neste artigo - as quais são muito eficientes para uma boa seleção do modelo de classificação. Duas das métricas que mais utilizamos na prática são: a área abaixo de curva ROC (ROC-AUC score) e o teste de Kolmogorov-Smirnov (teste KS).

Por fim, caso queira aprender mais sobre o mundo da Ciência de Dados, fique a vontade para acessar os demais artigos em. Tem muito conteúdo interessante por lá!

Aproveite e dê uma passada em nosso site e veja como solucionamos problemas do mundo real com Machine Learning. :)


Referências

3.3. Metrics and scoring: quantifying the quality of predictions
Model selection and evaluation using tools, such as model_selection.GridSearchCV andmodel_selection.cross_val_score …

scikit-learn.org

Classification: Precision and Recall | Machine Learning Crash Course
Estimated Time: 9 minutes Precision attempts to answer the following question: What proportion of positive…

developers.google.com

CatBoost - state-of-the-art open-source gradient boosting library with categorical features support
CatBoost is an algorithm for gradient boosting on decision trees. It is developed by Yandex researchers and engineers…

catboost.ai

Thanks to Erasmo Neto

Mais artigos da Datarisk

Ver todos os artigos
© Copyright 2017 - 2022 | Datarisk.io | Todos os direitos reservados