Introdução
Se você já treinou um classificador binário, você provavelmente usou a função de custo "binary cross-entropy" (entropia cruzada) ou "log loss".
Mas você já pensou a respeito do que essa função de custo realmente significa? Hoje em dia, as bibliotecas e frameworks são tão fáceis de usar, que costumamos ignorar o verdadeiro significado da função de custo utilizada.
Motivação
Eu estava em busca de um artigo que explicasse de uma maneira clara, visual e breve os conceitos por trás da "binary cross-entropy" ou "log loss", para mostrar aos meus alunos do Data Science Retreat. Mas como não encontrei nada que me agradasse, resolvi escrever eu mesmo :-)
Uma Classificação Básica
Imagine que temos 10 pontos aleatórios:
x = [-2.2, -1.4, -0.8, 0.2, 0.4, 0.8, 1.2, 2.2, 2.9, 4.6]
Eles são nosso único atributo: x.
Então, vamos associar cores aos pontos: vermelho e verde. Esses são nossos rótulos.
Nosso problema de classificação é bastante simples: dado o atributo x, temos que prever o respectivo rótulo: vermelho ou verde.
Mas, como essa é uma classificação binária, podemos formular o problema da seguinte forma: "o ponto é verde?" ou, melhor ainda, "qual a probabilidade do ponto ser verde?". Teoricamente, pontos verdes deveriam ter uma probabilidade de 1.0 (de ser verde), ao passo que pontos vermelhos deveriam ter uma probabilidade de 0.0 (de ser verde).
Assim, pontos verdes pertencem à classe positiva (SIM, eles são verdes), ao passo que pontos vermelhos pertencem à classe negativa (NÃO, eles não são verdes).
Se treinarmos um modelo que faça essa classificação, ele irá prever, para cada ponto, a probabilidade do ponto ser verde. Dado que já sabemos as verdadeiras cores dos pontos, como podemos avaliar se as probabilidades previstas são boas (ou ruins)? Esse é o papel da função de custo! Uma boa função de custo retorna valores altos para previsões ruins e valores baixos para previsões boas.
No caso de uma classificação binária, como em nosso exemplo, a função de custo típica é a "binary cross-entropy" ou "log loss".
Função de Custo: Binary Cross-Entropy / Log Loss
Se você pesquisar essa função de custo, é isso que você vai encontrar:
onde y é o rótulo (1 para pontos verdes e 0 para pontos vermelhos) e p(y) é a previsão da probabilidade do ponto ser verde para todos N pontos.
Pela fórmula, podemos verificar que, para cada ponto verde (y=1), o custo é acrescido do valor log(p(y)), ou seja, do logaritmo da probabilidade dele ser verde. De forma similar, para cada ponto vermelho (y=0), o custo é acrescido do valor log(1-p(y)), ou seja, do logaritmo da probabilidade dele ser vermelho. A fórmula não é tão difícil, mas também não é nem um pouco intuitiva…
E, o que a entropia tem a ver com isso? Por que motivo usamos o logaritmo das probabilidades? Essas são perguntas válidas e pretendo respondê-las na seção "Quero ver as fórmulas" abaixo.
Mas, antes de mostrar qualquer outra fórmula, quero mostrar a representação visual dessa função de custo…
Calculando o Custo — visualmente
Primeiro, vamos separar os pontos de acordo com a classe, positiva ou negativa, como na figura abaixo:
Então, vamos treinar uma Regressão Logística para classificar nossos pontos. A curva dessa regressão é uma curva sigmóide que representa a probabilidade de um ponto ser verde, dado seu atributo x:
Para os pontos que pertencem à classe positiva (verde), quais as probabilidades previstas pelo nosso classificador? Essas são as barras verdes abaixo da curva sigmóide, posicionadas sobre o atributo x de cada um dos pontos.
Ótimo! Mas e os pontos da classe negativa? Ora, se as barras verdes abaixo da curva sigmóide representam as probabilidades dos pontos serem verdes, como seriam as probabilidades dos pontos serem vermelhos? Barras vermelhas ACIMA da curva sigmóide, é claro :-)
Juntando tudo, obtemos uma figura como essa:
As barras representam as probabilidades previstas correspondentes à verdadeira classe de cada ponto!
OK, já que temos as probabilidades previstas, é hora de avaliar as previsões usando a nossa funçao de custo "binary cross-entropy" ou "log loss"!
Como só precisamos das probabilidades, vamos descartar o eixo x e botar as barras juntas umas das outras:
Essas barras penduradas não fazem mais sentido, então vamos reposicioná-las:
Nosso objetivo é calcular o custo, então temos que penalizar previsões ruins, não é mesmo? Se a probabilidade associada à verdadeira classe é 1.0, o custo deve ser zero. De forma análoga, se a probabilidade for baixa, tipo, 0.01, o custo retornado deve ser ALTO!
Coincidentemente, o (negativo do) logaritmo da probabilidade é bastante adequado para esse objetivo (já que o logaritmo de valores entre 0.0 e 1.0 é negativo, usamos o negativo do logaritmo para que os valores sejam positivos).
Na realidade, a utilização do logaritmo é decorrente da definição de entropia cruzada, veja mais detalhes na seção "Quero ver as fórmulas" abaixo.
A figura abaixo ilustra bem isso — conforme a probabilidade prevista para a verdadeira classe se aproxima de zero, o custo aumenta exponencialmente:
Agora vamos calcular o (negativo do) logaritmo das probabilidades — o custo associado a cada um dos pontos.
Finalmente, calculamos a média de todos os custos.
Feito! Conseguimos calcular o custo dado pela função "binary cross-entropy" ou "log loss" do nosso exemplo básico. O resultado é 0.3329!
Quero ver o código
Se você quiser conferir o valor que acabamos de calcular, execute o código abaixo e veja você mesmo :-)
Quero ver as fórmulas (sério?!)
Brincadeiras à parte, esse artigo não tem a intenção de ser matematicamente pesado… mas, para os meus leitores que querem entender melhor o papel da entropia, do logaritmo e tudo mais, taí :-)
Se você quiser se aprofundar em teoria da informação, incluindo todos esses conceitos — entropia, entropia cruzada e muito mais — confira o detalhado artigo do Chris Olah (em inglês)
Distribuição
Vamos começar pela distribuição dos nossos pontos. Já que y representa a classe dos pontos (3 pontos vermelhos e 7 pontos verdes), a sua distribuição q(y) tem o seguinte formato:
Entropia
A entropia é uma medida de incerteza associada a uma distribuição q(y).
E se todos nossos pontos fossem verdes? Qual seria a incerteza associada a essa distribuição? ZERO, né? Afinal de contas, não teríamos nenhuma dúvida a respeito da cor de um ponto: seria sempre verde! Então, a entropia é zero!
Por outro lado, e se soubéssemos que exatamente a metade dos pontos é verde e a outra metade, vermelho? Esse é o pior caso possível, né? Não teríamos forma alguma de adivinhar a cor de um ponto: seria totalmente aleatório! Nesse caso, a entropia é dada pela seguinte fórmula (temos duas classes (cores) — vermelho ou verde — portanto, 2):
Para todos demais casos intermediários, podemos calcular a entropia de uma distribuição, como a q(y) acima, usando a seguinte fórmula, onde C é o número de classes existentes:
Então, se conhecermos a verdadeira distribuição de uma variável aleatória, conseguimos calcular sua entropia. Mas, se for assim, pra que treinar um classificador? Afinal, conhecemos a verdadeira distribuição…
Mas, e se NÃO conhecermos? Podemos tentar aproximar a verdadeira distribuição com alguma outra distribuição, tipo, p(y)? Claro! :-)
Entropia Cruzada (Cross-Entropy)
Podemos supor que nossos pontos seguem essa outra distribuição p(y). Porém, sabemos que esses pontos são provenientes da verdadeira (e desconhecida) distribuição q(y).
Se calcularmos a entropia dessa forma, na realidade, estaremos calculando a entropia cruzada entre as duas distribuições:
Se, por milagre, conseguirmos bater p(y) com q(y) perfeitamente, ambos valores calculados, da entropia cruzada e da entropia, vão bater também.
Já que isso provavelmente não vai acontecer nunca, a entropia cruzada vai ter um valor MAIOR que o da entropia calculada a partir da verdadeira distribuição.
Essa diferença entre a entropia cruzada e a entropia tem um nome…
Divergência de Kullback-Leibler
A Divergência de Kullback-Leibler, ou "Divergência KL", é uma medida de dissimilaridade entre duas distribuições:
Assim, quanto mais próxima p(y) for de q(y), menor a divergência e, portanto, menor a entropia cruzada.
Então, precisamos encontrar uma boa distribuição p(y)… mas, peraí, não é isso que nosso classificador deveria estar fazendo?! Exatamente! Ele busca a melhor distribuição p(y) possível, que é aquela que minimiza a entropia cruzada.
Função de Custo
Durante o treinamento, o classificador usa cada um dos N pontos no conjunto de treinamento para calcular o custo dado pela entropia cruzada, determinando assim a distribuição p(y)! Já que a probabilidade de cada ponto é dados por 1/N, a entropia cruzada é dada por:
Lembra das Figuras 6 a 10 acima? Temos que calcular a entropia cruzada a partir das probabilidades associadas a verdadeira classe de cada ponto. Ou seja, temos que usar as barras verdes para os pontos pertencentes à classe positiva (y=1) e as barras vermelhas penduradas para os pontos pertencentes à classe negativa (y=0). Matematicamente falando, temos:
O último passo é calcular a média de todos os pontos em ambas as classes, tanto positiva como negativa:
Finalmente, com um pouquinho de manipulação das variáveis, conseguimos colocar todos os pontos, sejam da classe positiva ou negativa, no mesmo somatório:
Feito! Chegamos à fórmula original da função de custo "binary cross-entropy" ou "log loss" :-)
Considerações Finais
Espero que esse artigo tenha conseguido ilustrar o conceito de entropia cruzada binária (binary cross-entropy) como função de custo. Além disso, espero também que tenha servido para mostrar um pouquinho da conexão entre Machine Learning e Teoria da Informação.
Para sugestões, perguntas ou comentários, por favor, escreva abaixo ou me contate no Twitter.