Gradientes Descendentes na prática — melhor jeito de entender
Um dos tópicos mais abordado e utilizado para quem está estudando ou trabalhando como data science, com certeza é esse famoso do gradiente. Mas o que significa gradiente descedentes e quais variações são mais encontradas nos artigos.
A gradiente descedente é um algoritmo de otimização usado para minimizar algumas funções movendo-se iterativamente na direção da descida mais íngreme, conforme definido pelo negativo do gradiente. Nos modelos de machine learning, usamos gradiente descendente para atualizar os parâmetros do nosso modelo. No link abaixo você encontra mais informação sobre o tema sendo aplicado em deep learning.
Antes de entrar nos tipos de gradientes descedentes, é importante ter a clareza do que significa "convergi o valor" e quais são os hiperparamentros para isso.
O parâmetro learning rate, será responsável em dizer qual a distância que ele deverá pecorrer em cada iteração. Vamos supor que está participando de um jogo de tabuleiro, e seu learning rate é 2 casas. Logo, toda vez que for sua vez de jogar, você só poderá andar em 2 em 2. O ponto de começar pode ser aleatório ou não e o gradiente sempre apontará para o mínimo local. Quando chegar nesse menor valor da função de custo, logo dizemos que convergiu, no "melhor" valor. Logo, caso escolha um learning rate muito pequeno, pode ser custoso computacionalmente por demorar a converger e se for muito grande, pode falhar em converger no mínimo por passar dele.
É normal encontrar learning rate entre esses valores: 0.001, 0.003, 0.01, 0.03, 0.1, 0.3.
Existem alguns tipos de learning rate conhecidos em modelos de deep learning como: Learning rate schedule e Adaptive learning rate. Não serão abordados aqui mas vale entender o que eles podem
Um outra dica seria em certificar de normalizar os dados, se estiverem em escalas muito diferentes. Se não normalizar os dados, as curvas de nível (contornos) irão ser mais estreitas e altas, o que significa que demorará mais tempo para convergir.
Abaixo, segue um gráfico para ajudar no entendimento do objetivio do gradiente descedente. Vamos supor que não esteja envesado. Se a inclinação do valor atual de w> 0, isso significa que estamos à direita do w * ótimo. Portanto, a atualização será negativa e começará a se aproximar dos valores ótimos de w *. No entanto, w<0, a atualização será positiva e aumentará os valores atuais de w para convergir para os valores ideais de w *.
Continue o processo até que a função de custo convirja. Isto é, até que a curva de erro se torne plana e paralela ao eixo w e não mude. Além disso, em cada iteração, a etapa estaria na direção do mínimo local, uma vez que é perpendicular (tangente) às curvas de nível em cada etapa.
Pela sua eficiência computacional, existem três tipos que se pode encontrar com uma certa frequência. Utilizaremos função custo MSE:
O h_theta é a hipótese, o valor previsto do modelo.
A função cal_cost()
cria um objeto do tamanho da dataset de treino, realiza uma multiplicação matricial (por isso utiliza a função dot) para calcular a previsão, em seguida calcula o MSE.
A imagem abaixo demonstra a função gradiente aplicada em diferentes thetas. Mas no exemplo, vamos considerar apenas uma variável explicativa portanto existirá apenas theta_zero e theta_um. Quando for executar a derivada parcial, o gradiente do theta_zero terá uma pequena diferença da função theta_um. Isso se deve a função do problema em questão: y = a+bx, onde theta_zero é o a e o theta_um é o b.
Caso a função possua 5 variáveis, teremos 6 thetas: theta_zero, theta_um, theta_dois, theta_tres, theta_quatro, theta_cinco, theta_seis. Dependendo da função cada gradiente descedente terá sua particularidade, ou não.
Achem o "erro": Vocês perceberam que as fórmulas descritas acima, existem uma pequena diferença entre elas? (Fórmula apresentada como MSE e a fórmula utilizada para explicar os thetas.)
Yep, existe sim! É o quadrado da função hipótese (preditiva) e a fração 1/2.
Porque 1/2m é inserido na função custo, de forma opicional?
É um detalhe em que muitas pessoas deixam passar despercebido. Multiplicamos nossa função de custo MSE por 1/2, de modo que, quando fazemos a derivada, os 2s se cancelam. Multiplicar a função de custo por um escalar não afeta a localização de seu mínimo, então podemos utilizar essa técnica sem problema, opicional. A única razão pela qual alguns autores gostam de incluí-lo é que, quando você tira a derivada em relação a 𝑥, o 2 desaparece.
A divisão por m garante que a função de custo não dependa do número de elementos no conjunto de treinamento. Isso permite uma melhor comparação entre os modelos.
Nos exemplos abaixo será considerado o mesmo dataset, com o mesmo número de iterações = 10000 e learning rate = 0,001.
X = 2 * np.random.rand(100,1)y = 5 +2 * X+np.random.randn(100,1)
Gradient Descent
Processo de tentar minimizar uma função olhando para o gradiente e tentando move-lo para baixo, de uma única vez.
Fiz um post dedicado a variações da função gradiente descendente, olhando para o quesito de performance.
Os resultados do theta0 e theta1 foram:
- theta0 = 4,23
- theta1 = 2,53
- Cost function = 0,493
- Tempo de execucao = 0,171
Stochastic Gradient Descent
Em vez de passar por todos os exemplos, Stochastic Gradient Descent (SGD) realiza a atualização dos parâmetros em cada exemplo (x_i, y _i) de forma aleatória. Portanto, o aprendizado acontece em todos os exemplos.
Como vocês podem notar o loop secundário utiliza a função de selecionar um número aleatório inteiro do tamanho do dataset m. Em seguida, consulta no X_i e y_i, funcionando como um index para identificar quais serão as observações selecionadas para atualizar os parâmetros theta0 e theta1.
- Theta0 = 4,84
- Theta1 = 2,01
- Cost function = 0,47
- Tempo de execução = 20,9
Mini Batch Gradient Descent
Uma mistura do gradient descendente com o estocástico, porque ele vai selecionar um pedaço do seu dataset, executar com todas as observações deste conjunto e assim consecutivamente. Como podem perceber na função abaixo, deixei um default de dividir em 20 "batches" o tamanho do dataset.
- Theta0 = 4,38
- Theta1 = 2,43
- Cost function = 0,02
- Tempo de execução = 2,45
Analisando a evolução dos coeficientes theta0 e theta1 com o passar das iterações. Percebemos que o método gradiente descendente e o mini batch, convergirão mais rápido. Contudo, no exemplo utilizado foi simples com um dataset pequeno. Se utilizamor um conjunto de dados muito grande, o cenário será inverso, o stocastic apresentará uma performance mais satisfatória.
Considerações
É um ótimo otimizador para se trabalhar, como vocês podem perceber é de fácil entendimento e implementação. Porém, tem alguns pontos que devemos considerar na hora de trabalhar com gradiente descendente (em geral gradient descendent e mini batches):
1- Não pode ser aplicado de forma confiável a problemas não convexos;
2- Requer o ajuste do learning rate, ficando assim preso no minimo local;
3- Pode chegar perto do ótimo, mas nunca convergir exatamente. Que também não é um problema na maioria dos casos;
4- Pode desviar na direção errada devido a atualizações frequentes;
5- Perde os benefícios da vetorização, pois processamos uma observação por vez;
6- As atualizações frequentes são custosas do ponto de vista computacional devido ao uso de todos os recursos para processar uma amostra de treinamento por vez;
E você, algum outro ponto para acrescentar?
Deixa um comentário aqui!
https://readthedocs.org/projects/machinelearning101/downloads/pdf/latest/
https://towardsdatascience.com/gradient-descent-in-python-a0d07285742f
https://towardsdatascience.com/gradient-descent-algorithm-and-its-variants-10f652806a3#:~:text=Batch%20Gradient%20Descent,-Batch%20Gradient%20Descent&text=It%20has%20straight%20trajectory%20towards,loss%20function%20is%20not%20convex.
https://towardsdatascience.com/gradient-descent-in-python-a0d07285742f
https://ml-cheatsheet.readthedocs.io/en/latest/gradient_descent.html#:~:text=Gradient%20descent%20is%20an%20optimization,the%20parameters%20of%20our%20model.
http://mccormickml.com/2014/03/04/gradient-descent-derivation/
https://jermwatt.github.io/machine_learning_refined/notes/3_First_order_methods/3_7_Problems.html