O Aprendizado Sensível ao Custo é uma abordagem que busca otimizar decisões considerando os custos associados a diferentes tipos de erros. Diferentemente das abordagens tradicionais, onde os custos de erro são simétricos, esta abordagem lida com custos assimétricos — alguns erros podem ser mais custosos ou prejudiciais que outros. Esses erros podem ser de predição (Falsos Positivos ou Negativos) ou relacionados a regras de negócio, como fraudes ou aprovação de um serviço caro. A ideia central é minimizar o custo total das previsões, em vez de simplesmente maximizar a precisão.

Exemplo de Treinamento com Aprendizado Sensível ao Custo:

Considere um banco desenvolvendo um modelo para detectar transações fraudulentas. A matriz de custos poderia ser estruturada da seguinte forma:

Previsão \ Real Fraude Não Fraude
Fraude $0 $50
Não Fraude $1000 $0

Neste cenário:

Logo, o modelo treinado ajustaria seus parâmetros para minimizar o custo total. Isso pode resultar em aceitar mais falsos positivos para reduzir significativamente os falsos negativos mais custosos. Embora possa ter uma precisão geral ligeiramente menor, esse modelo seria mais eficaz em termos de redução de perdas financeiras para a empresa.

Dados Desbalanceados

Além disso, podemos aplicar essa metodologia para lidar com conjuntos de dados desbalanceados, onde uma classe é significativamente mais representada que outra. Atribuímos custos mais altos aos erros da classe menos representada, controlando assim a confiabilidade do modelo em relação às classes.

Para implementar isso, primeiro criamos um peso para cada classe, proporcional ao volume de dados para treino. Simulando para duas classes:

$$ \text{peso-da-classe} = \frac{\text{total-de-dados}}{\text{total-de-classes} \times \text{total-de-registros-da-classe-específica}}

$$

total_de_dados = 100
total_da_classe_0 = len(y_train[y_train == 0]) # 90
w1 = 100 / (2 * total_da_classe_0) #0.55

total_da_classe_1 = len(y_train[y_train == 1]) # 10
w2 = 100 / (2 * total_da_classe_1) #5

rf = RandomForestClassifier()
rf.fit(X_train, y_train, class_weight={0: 0.55, 1: 5})

Desta forma, contabilizará os pesos das duas classes dentro da função de perda. Neste caso, dentro de gini, contabilizará os dois pesos.

$$ \text{Gini} = 1 - \text{W}1*\text{Proportion}{c1}^2 - \text{W}2*\text{Proportion}{c2}^2 $$

scikit-learn por padrão, possibilita já calcular esse peso, apenas incrementado o parametro como “balanced”.

rf.fit(X_train, y_train, class_weight="balanced")

Há outros métodos utilizando metadados mais específicos. Para mais informações, recomendo a palestra no EuroSciPy 2023.