Classificando Gestos com Deep Learning
Já imaginou como seria natural controlar dispositivos ou aplicativos apenas com as mãos, sem teclados ou mouses? Essa é a promessa do…
Classificando Gestos com Deep Learning
Já imaginou como seria natural controlar dispositivos ou aplicativos apenas com as mãos, sem teclados ou mouses? Essa é a promessa do reconhecimento de gestos, uma área fascinante do aprendizado profundo que vem ganhando cada vez mais espaço. Neste artigo, vamos explorar as redes neurais para construir um classificador de gestos que reconhece “pedra”, “papel” e “tesoura” com base em imagens.
Antes de mais nada, vamos introduzir alguns conceitos importantes para a elaboração e implementação do classificador, mostrando os diferentes otimizadores e como eles podem ajudar no processamentos dos dados.
Médias Móveis Exponencialmente Ponderadas (EWMAs)
As Médias Móveis Exponencialmente Ponderadas (EWMAs) são uma poderosa técnica estatística amplamente utilizada para analisar séries temporais. Diferentemente da média móvel simples, que atribui o mesmo peso a todos os pontos de dados de uma janela específica, as EWMAs empregam um mecanismo de ponderação exponencial. Esse método confere maior importância às observações mais recentes, enquanto os dados mais antigos têm sua influência gradualmente diminuída de forma exponencial.
Essa característica torna esses métodos eficazes na identificação de tendências atuais e na filtragem de ruídos em dados altamente variáveis. Consequentemente, são amplamente aplicadas em áreas como previsão financeira, análise de mercado e, mais recentemente, em técnicas avançadas de aprendizado de máquina e aprendizado profundo.
No domínio do aprendizado profundo, as EWMAs desempenham um papel crucial na estabilização do treinamento de modelos. Ao suavizar métricas fundamentais, como gradientes e sua variância, elas garantem que os ajustes nos pesos da rede neural ocorram de maneira mais controlada e eficiente. Essa suavização não apenas reduz a sensibilidade a flutuações abruptas, mas também contribui para uma convergência mais estável e rápida, especialmente em problemas de alta dimensionalidade ou em cenários ruidosos.
Além disso, a versatilidade das EWMAs permite sua integração em algoritmos de otimização modernos, como o Adam, onde são utilizadas para adaptar dinamicamente a taxa de aprendizado.
Por que as EWMAs são importantes para os otimizadores?
As EWMAs desempenham um papel fundamental no treinamento de redes neurais ao oferecer uma série de benefícios que impactam diretamente a eficiência e a estabilidade do aprendizado. Suas principais contribuições incluem:
- Responsividade adaptativa: A natureza exponencial das EWMAs permite que as atualizações sejam mais sensíveis a mudanças recentes nos gradientes. Essa propriedade é particularmente útil em cenários dinâmicos, onde os dados ou a superfície de perda apresentam variações rápidas que precisam ser capturadas para evitar estagnação ou superestimação.
- Suavização dos gradientes: Durante o treinamento, os gradientes podem apresentar oscilações significativas, especialmente em problemas com alta dimensionalidade ou ruídos. As EWMAs atenuam essas flutuações, proporcionando uma visão mais estável da direção geral de descida no espaço de parâmetros.
- Estabilidade e convergência: Ao suavizar os gradientes e moderar a magnitude das atualizações, as EWMAs promovem passos mais confiáveis na otimização dos pesos. Isso não apenas acelera a convergência, mas também reduz o risco de que o treinamento fique preso em mínimos locais ruins ou regiões instáveis da superfície de erro.
Como funcionam as (EWMAs)?
As Médias Móveis Exponencialmente Ponderadas são calculadas com base em uma fórmula que combina o valor atual de uma série temporal com sua média suavizada anterior. A expressão matemática é:

Fonte: Daniel Voigt Godoy, Deep Learning with PyTorch: Step-by-Step — A Beginner’s Guide, Independently Published, 2024
Onde:
- x(t) é o valor atual dos dados;
- α é o fator de suavização;
- EWMAt-1 é o valor de EWMA calculado anteriormente;
Essa equação, utilizando α como o peso do valor atual, é mais comum em outras áreas, como finanças. Porém, tem outra equação, utilizando β, que é comumente utilizado no otimizador Adam, por exemplo. A equação da versão β é dado por:

Fonte: Daniel Voigt Godoy, Deep Learning with PyTorch: Step-by-Step — A Beginner’s Guide, Independently Published, 2024
onde β, assim como α, é o fator de suavização;
O fator de decaimento α ou β é um parâmetro essencial no cálculo da EWMA, geralmente definido próximo de 1, como 0,9 ou 0,999. Valores mais altos atribuem maior peso a dados passados, tornando a média suavizada menos sensível a alterações recentes. Por outro lado, valores menores aumentam a responsividade da EWMA a novas informações, permitindo capturar mudanças rápidas no comportamento da série temporal.
Vamos ver como os pesos são distribuídos pelas defasagens para duas médias, uma EWMA com alfa igual a um terço e uma média móvel simples de cinco períodos.

DistributionFonte: Daniel Voigt Godoy, Deep Learning with PyTorch: Step-by-Step — A Beginner’s Guide, Independently Published, 2024 of weights over lags
Pelo gráfico é possível notar que numa média móvel simples, todos os valores têm o mesmo peso, isto é, eles contribuem igualmente para a média. Mas, numa EWMA, os valores mais recentes tem pesos maiores que os mais antigos.
Segue um exemplo de uma implementação da EWMA:

Fonte: Daniel Voigt Godoy, Deep Learning with PyTorch: Step-by-Step — A Beginner’s Guide, Independently Published, 2024
Para calculá-lo ao longo de uma série de valores, dado um período, podemos definir uma função do seguinte modo:

Fonte: Daniel Voigt Godoy, Deep Learning with PyTorch: Step-by-Step — A Beginner’s Guide, Independently Published, 2024
No bloco try..except, você perceberá que, caso não exista um valor anterior para a EWMA (como no primeiro passo), ele assume um valor inicial de zero.
Embora essa abordagem simplifique o cálculo da EWMA, ela apresenta uma limitação importante: como o método não considera todos os valores anteriores dentro do período, as médias iniciais tendem a ser significativamente enviesadas. Para corrigir esse viés, podemos calcular a EWMA com ajuste de viés. Essa correção garante que a influência dos valores ausentes seja reduzida à medida que mais dados são processados.

Fonte: Daniel Voigt Godoy, Deep Learning with PyTorch: Step-by-Step — A Beginner’s Guide, Independently Published, 2024
Na fórmula, β (igual a 1−α) permanece o mesmo. Em código, podemos implementar o fator de correção da seguinte maneira:

Fonte: Daniel Voigt Godoy, Deep Learning with PyTorch: Step-by-Step — A Beginner’s Guide, Independently Published, 2024
Por fim, para calcular o EWMA ajustado, podemos usar essa função:

Fonte: Daniel Voigt Godoy, Deep Learning with PyTorch: Step-by-Step — A Beginner’s Guide, Independently Published, 2024
Stochastic Gradient Descent (SGD)
O Stochastic Gradient Descent (SGD) é uma versão simplificada do Gradient Descent tradicional, usada para minimizar a função de perda em aprendizado profundo. Em vez de calcular o gradiente com base em todo o conjunto de dados, o SGD utiliza apenas uma amostra ou mini-batch a cada iteração, o que acelera o treinamento para datasets grandes. Para entender melhor o funcionamento da SGD, primeiro veremos como funciona o Gradiente Descendente tradicional.
O Gradiente Descendente (Gradient Descent) é um algoritmo de otimização usado para minimizar funções, sendo amplamente aplicado no treinamento de modelos de aprendizado de máquina e redes neurais. O objetivo principal do Gradiente Descendente é ajustar os parâmetros do modelo para minimizar uma função de perda, que mede o quão bem o modelo está performando.
Para um melhor entendimento, vamos visualizar com um exemplo prático. Seja f(x,y) = x² + y², onde o gráfico dessa superfície é:

Fonte: Autoral
Se plotarmos o gráfico do gradiente dessa função obteremos o seguinte:

Fonte: Autoral
Repare que no gráfico do gradiente, as setas apontam para a direção de maior inclinação. O que o gradiente descendente faz é seguir na direção oposta das setas para ir de encontro ao mínimo global.
O algoritmo segue os seguintes passos básicos:
- Inicialização dos Parâmetros: Começamos com valores iniciais para os parâmetros θ do modelo, geralmente atribuídos aleatoriamente ou com algum critério pré-definido.
- Cálculo do Gradiente: O gradiente ∇L(θ) é calculado em relação à função de perda L(θ). Ele indica a direção de maior crescimento da função no espaço dos parâmetros.
- Atualização dos Parâmetros: Os parâmetros θ são ajustados na direção oposta ao gradiente (pois queremos minimizar a função). A atualização é dada por:
θt+1=θt − η⋅∇Lθt
Onde:
- θt: Parâmetros no passo t.
- η: Taxa de aprendizado (learning rate), que controla o tamanho do passo.
- ∇L(θt): Gradiente da função de perda no passo t.
- Iteração até a Convergência: O processo é repetido até que a função de perda atinja um valor mínimo (local ou global), ou um critério de parada seja satisfeito (como limite de iterações ou mudanças pequenas na perda).
Já o SGD é uma variante do gradiente descendente que realiza atualizações de parâmetros usando exemplos individuais do conjunto de dados. Isso o torna mais rápido e eficiente para grandes bases de dados, mas também mais ruidoso devido à variabilidade entre os exemplos.
A atualização dos pesos no SGD segue a fórmula:

Fonte: Daniel Voigt Godoy, Deep Learning with PyTorch: Step-by-Step — A Beginner’s Guide, Independently Published, 2024
onde:
- param t: Parâmetros do modelo no passo t.
- η: Taxa de aprendizado.
- gradient [t]): Gradiente da função de perda em relação aos parâmetros param t.
Embora eficiente, o SGD básico possui limitações:
- Oscilações: Pode apresentar grande variação nos valores dos gradientes, dificultando a convergência.
- Eficiência reduzida em mínimos locais ou vales alongados: A movimentação do SGD pode ser ineficaz em regiões da superfície de perda que possuem curvaturas diferentes em cada direção.
Existem variantes do SGD que aprimoram o algoritmo, as mais conhecidas são o Momentum e o Nesterov Momentum.
Momentum
O Momentum é uma técnica que aprimora o método de Stochastic Gradient Descent (SGD) ao adicionar uma forma de “memória” sobre as atualizações anteriores. Ele ajuda a suavizar as oscilações durante o treinamento e acelera a convergência, especialmente em funções com formas de “vale” alongadas.
Funcionamento do Momentum

Fonte: Daniel Voigt Godoy, Deep Learning with PyTorch: Step-by-Step — A Beginner’s Guide, Independently Published, 2024
Analisando as equações, vemos que em vez de calcular a média dos gradientes, o algoritmo do Momentum realiza uma soma cumulativa dos gradientes, aplicando um “desconto” ao longo do tempo. Isso significa que, embora todos os gradientes anteriores contribuam para o cálculo, a influência dos gradientes mais antigos diminui progressivamente à medida que se tornam mais distantes. Esse “desconto” é controlado pelo parâmetro beta. A fórmula do momento pode ser expressa da seguinte forma:

Fonte: Daniel Voigt Godoy, Deep Learning with PyTorch: Step-by-Step — A Beginner’s Guide, Independently Published, 2024
Nesterov Momentum
O Nesterov Momentum é uma variação do método de gradiente descendente que utiliza o momento para acelerar a convergência. A ideia básica é que, ao adicionar uma porção do movimento anterior ao cálculo do próximo passo, o algoritmo pode “passar por” mínimos locais e convergir mais rapidamente para o mínimo global.

Fonte: Daniel Voigt Godoy, Deep Learning with PyTorch: Step-by-Step — A Beginner’s Guide, Independently Published, 2024
Essa equação calcula o momento de Nesterov, que é uma pequena variação do momento padrão. A diferença é que aqui, o momento anterior (mot) é usado para calcular o próximo passo, em vez do gradiente atual. Isso é conhecido como "olhar para frente" e pode melhorar a convergência.
Vamos ver a diferença entre o SGD, SGD com Momentum e o SGD com o Nesterov Momentum em um gráfico para visualizar a ideia por traz desses otimizadores:

Fonte: Daniel Voigt Godoy, Deep Learning with PyTorch: Step-by-Step — A Beginner’s Guide, Independently Published, 2024
Learning Rate Schedulers: Aplicação e Teoria
A taxa de aprendizado (learning rate) é um hiperparâmetro crítico no treinamento de redes neurais. Ela controla o tamanho do passo na atualização dos pesos do modelo durante o processo de otimização. Uma taxa de aprendizado muito alta pode levar a oscilações e divergência, enquanto uma taxa de aprendizado muito baixa pode tornar o treinamento lento e ineficiente. Os Learning Rate Schedulers são técnicas que ajustam dinamicamente a taxa de aprendizado durante o treinamento, com o objetivo de melhorar a convergência e o desempenho do modelo.
A Necessidade de Ajustar a Taxa de Aprendizado
O valor inicial da taxa de aprendizado é importante, mas muitas vezes não é suficiente para garantir o melhor treinamento. A função de perda pode ter regiões com diferentes características: regiões mais planas, onde passos maiores são apropriados, e regiões mais acentuadas, onde passos menores são necessários. Ajustar a taxa de aprendizado durante o treinamento permite que o modelo se adapte a essas variações, ajudando a:
- Acelerar a Convergência: Taxas de aprendizado maiores no início podem ajudar o modelo a explorar o espaço de parâmetros mais rapidamente.
- Evitar Oscilações: Reduzir a taxa de aprendizado à medida que o treinamento avança pode evitar oscilações em torno do mínimo e garantir uma convergência mais suave.
- Encontrar Mínimos Melhores: A taxa de aprendizado dinâmica pode ajudar o otimizador a escapar de mínimos locais e encontrar regiões com um desempenho melhor.
Tipos de Learning Rate Schedulers
Existem diversas estratégias para ajustar a taxa de aprendizado, divididas em três categorias principais: schedulers que atualizam a taxa de aprendizado a cada epoch, schedulers que atualizam a taxa de aprendizado quando a perda de validação para de melhorar e schedulers que atualizam a taxa de aprendizado a cada mini-batch.
Epoch Schedulers (Schedulers de Época)
Esses schedulers ajustam a taxa de aprendizado após cada época de treinamento (após todos os minibatches). Alguns dos mais comuns incluem:
- StepLR: Reduz a taxa de aprendizado por um fator gamma a cada step_size épocas.
- **Teoria**: Implementa um decaimento em passos, reduzindo a taxa de aprendizado a cada n epochs.
Implementação:
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=5, gamma=0.1)
Multi Step LR: Reduz a taxa de aprendizado por um fator gamma em épocas específicas definidas em milestones.
Implementação:
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
scheduler = torch.optim.lr_scheduler.MultiStepLR(optimizer, milestones=[5,10], gamma=0.1)
Exponential LR:
Reduz a taxa de aprendizado por um fator gamma em cada época.
Lambda LR:
Permite definir uma função personalizada para ajustar a taxa de aprendizado.
Implementação:
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
lmbda = lambda epoch: 0.95 ** epoch
scheduler = torch.optim.lr_scheduler.LambdaLR(optimizer, lr_lambda=lmbda)
Cosine Annealing LR:
Usa o decaimento do cosseno para decair a taxa de aprendizado ao longo do treinamento.
Implementação:
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
scheduler = torch.optim.lr_scheduler.CosineAnnealingLR(optimizer, T_max=10)
Reduce LR On Plateau:
Reduz a taxa de aprendizado quando a perda de validação não melhora por um número específico de épocas (patience), multiplicado por um fator factor.
Implementação:
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, patience=4, factor=0.1)
Mini-Batch Schedulers (Schedulers de Mini-Batch): Esses schedulers ajustam a taxa de aprendizado após cada mini-batch. Geralmente, eles utilizam alguma forma de “ciclo” para aumentar e diminuir a taxa de aprendizado.
Cyclic LR: Faz um ciclo entre uma taxa de aprendizado base e uma taxa de aprendizado máxima, o que pode ser triangular, triangular2 ou exponencial.
Implementação:
optimizer = torch.optim.SGD(model.parameters(), lr=0.01) scheduler = torch.optim.lr_scheduler.CyclicLR(optimizer, base_lr=1e-4, max_lr=1e-3, step_size_up=10, mode='triangular2')
One Cycle LR: Segue uma taxa de aprendizado que sobe a um valor definido, e então abaixa gradativamente até um valor inferior no total de passos definidos.
Implementação:
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
scheduler = torch.optim.lr_scheduler.OneCycleLR(optimizer, max_lr=0.1, total_steps=1000)
Cosine Annealing Warm Restarts: Usa o decaimento do cosseno de forma cíclica.
Implementação:
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
scheduler = torch.optim.lr_scheduler.CosineAnnealingWarmRestarts(optimizer, T_0=10)
Por fim, veremos dois exemplos de treinamento, o primeiro usando scheduler de época e o segundo treinamento usando scheduler de mini-batch:
Scheduler de época
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
scheduler = torch.optim.lr_scheduler.StepLR(optimizer, step_size=5, gamma=0.1)
for epoch in range(num_epochs):
# Treinamento do modelo (loop interno)
# ...
# Avaliação do modelo (loop interno)
# ...
scheduler.step()
Scheduler de mini-batch
optimizer = torch.optim.SGD(model.parameters(), lr=0.01)
scheduler = torch.optim.lr_scheduler.CyclicLR(optimizer, base_lr=0.001, max_lr=0.01, step_size_up=10)
for epoch in range(num_epochs):
for i, (x_batch, y_batch) in enumerate(train_loader):
# Atualização dos parâmetros
# ...
optimizer.step()
scheduler.step()
optimizer.zero_grad()
A implementação do código completo do classificador pode encontra-se no meu repositório no github em:
https://github.com/diogovinicius18/ML_ADM/tree/main/Code
Referência Bibliográfica
Este artigo foi inspirado e complementado pelos conceitos apresentados no livro “Deep Learning with PyTorch: Step-by-Step — A Beginner’s Guide” de Daniel Voigt Godoy (2024). A obra é uma referência essencial para quem está iniciando na área de aprendizado profundo, oferecendo uma abordagem prática e detalhada para entender e implementar modelos de deep learning com PyTorch.
메타데이터
- post_id
- 2bc4f0e5d9f7
- slug
- classificando-gestos-com-deep-learning-2bc4f0e5d9f7
- url
- https://medium.com/@diogo.vinicius.089/classificando-gestos-com-deep-learning-2bc4f0e5d9f7
- canonical_url
- https://medium.com/@diogo.vinicius.089/classificando-gestos-com-deep-learning-2bc4f0e5d9f7
- author_url
- https://medium.com/@diogo.vinicius.089
- status
- ok
- fetched_at
- 2026-06-26 21:52:29