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:
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.
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:
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:
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…
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.
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.
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.
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. :)
scikit-learn.org
developers.google.com
catboost.ai
Thanks to Erasmo Neto