Optimization Algorithm
Um algoritmo de otimização atualiza os pesos de um modelo para minimizar a sua perda durante o treino. Abrange descida do gradiente, momentum, Adam, AdamW, Muon e código.
Um algoritmo de otimização, ou otimizador, é a regra que um processo de treinamento usa para alterar os parâmetros de um modelo de modo a reduzir sua função de perda. No aprendizado profundo, o otimizador recebe, por meio da retropropagação, o gradiente da perda em relação a cada peso do modelo e decide o quanto e em que direção mover cada um deles. Junto com a taxa de aprendizado, o otimizador determina a velocidade de convergência do treinamento, sua estabilidade, a quantidade de memória necessária e, muitas vezes, o quanto o modelo final generaliza.
Como funcionam os otimizadores#
Quase todos os otimizadores de aprendizado profundo são variantes da descida do gradiente: calcula-se o gradiente g da perda em um minilote e, em seguida, move-se os pesos um pequeno passo na direção oposta, w ← w − η·g. Os otimizadores diferem no que fazem com g antes de dar o passo. Os métodos com momentum calculam a média dos gradientes ao longo do tempo para ganhar velocidade em direções que permanecem consistentes. Os métodos adaptativos dividem o passo de cada parâmetro por uma estimativa móvel da magnitude do gradiente. O Muon ortogonaliza a atualização de cada matriz de pesos como um todo. Os métodos de segunda ordem também usam a curvatura, o que permite passos mais bem informados, mas muito mais caros de calcular. Métodos que não precisam de gradiente, como algoritmos evolutivos e busca aleatória, otimizam testando candidatos e mantendo o melhor:
A regra de atualização é mais importante quando a superfície de perda é mal condicionada, curvando-se acentuadamente em algumas direções e suavemente em outras. Executar três otimizadores a partir do mesmo ponto inicial em um vale estreito mostra a diferença:
import torch
# A long, narrow valley: f(w) = w1^2 + 50 * w2^2, with its minimum at (0, 0)
scale = torch.tensor([1.0, 50.0])
optimizers = {
"SGD": lambda p: torch.optim.SGD(p, lr=0.015),
"SGD + momentum": lambda p: torch.optim.SGD(p, lr=0.015, momentum=0.9),
"Adam": lambda p: torch.optim.Adam(p, lr=0.1),
}
for name, make_optimizer in optimizers.items():
w = torch.tensor([5.0, 1.0], requires_grad=True)
optimizer = make_optimizer([w])
# Same loss and starting point for every optimizer; only the update rule differs
for step in range(100):
loss = (scale * w**2).sum()
optimizer.zero_grad()
loss.backward()
optimizer.step()
print(f"{name:15s} f(w) after 100 steps: {(scale * w**2).sum().item():.6f}")O SGD simples para em 0.056531 porque a direção íngreme w2 limita sua taxa de aprendizado: qualquer taxa acima de 0.02 faz w2 ultrapassar o valor correto cada vez mais a cada passo, e, com 0.021, a perda chega a cerca de 9,5 bilhões em 100 passos. Com esse limite, o progresso na direção suave w1 é lento. O momentum chega a 0.000216 ao ganhar velocidade ao longo de w1, e o Adam chega a 0.001953 ao atribuir um tamanho de passo próprio a cada coordenada.
Algoritmos de otimização comuns#
- Descida estocástica do gradiente (SGD): Dá passos na direção oposta ao gradiente do minilote. Com momentum de 0.9, treinou a maioria das redes convolucionais de referência e armazena um valor extra por parâmetro.
- AdaGrad e RMSProp: Ajustam o passo de cada parâmetro de acordo com o histórico de seus gradientes ao quadrado. O AdaGrad divide pela raiz da soma acumulada desses gradientes, que só aumenta, por isso seus passos diminuem ao longo do treinamento. O RMSProp usa, em vez disso, uma média com decaimento exponencial, que mantém os tamanhos dos passos responsivos.
- Adam: Combina momentum com o ajuste de escala do RMSProp e corrige as duas médias móveis para compensar o início em zero. Seus valores padrão — taxa de aprendizado de 0.001, β1 = 0.9 e β2 = 0.999 — funcionam em muitos problemas.
- AdamW: Adam com decaimento de pesos desacoplado, que reduz os pesos diretamente em vez de fazê-lo por meio do ajuste adaptativo da escala do gradiente. É o otimizador padrão para Transformers e modelos de linguagem de grande escala (LLMs).
- Muon: Ortogonaliza a atualização de momentum de cada matriz de pesos 2D com iterações de Newton–Schulz e mantém um único buffer de estado por parâmetro. A Moonshot AI escalou o método para o pré-treinamento de LLMs.
- L-BFGS: Um método quase-Newton que constrói uma estimativa da curvatura a partir de gradientes recentes. Converge em poucos passos em problemas suaves com lotes completos, e gradientes ruidosos de minilotes o tornam inadequado para redes grandes.
O pacote de otimizadores do PyTorch implementa todos esses métodos, incluindo torch.optim.Muon, além de escalonadores de taxa de aprendizado compatíveis com qualquer um deles.
Otimizador e termos relacionados#
- Função de perda: O objetivo que o otimizador minimiza, como a entropia cruzada para classificação ou o erro quadrático médio para regressão.
- Escalonador de taxa de aprendizado: Ajusta o tamanho do passo η durante o treinamento, com aquecimento, decaimento por etapas ou recozimento cosseno, além de qualquer otimizador.
- Ajuste de hiperparâmetros: Uma busca externa entre configurações como otimizador, taxa de aprendizado e tamanho do lote, na qual cada candidato exige uma execução de treinamento completa ou parcial. Métodos sem gradiente, como otimização bayesiana e busca evolutiva, realizam essa tarefa porque não é possível diferenciar uma pontuação de validação em relação a escolhas como o otimizador.
Como escolher um otimizador#
O otimizador e a taxa de aprendizado são escolhidos em conjunto, pois cada otimizador funciona em uma faixa própria: o SGD com momentum normalmente começa entre 0.01 e 0.1, e os otimizadores da família Adam, em torno de 0.001. O treinamento do Ultralytics YOLO faz essa escolha automaticamente: o padrão optimizer="auto" ignora lr0 e escolhe AdamW com uma taxa de aprendizado ajustada ao número de classes para execuções de até 10.000 iterações, ou MuSGD, a combinação de SGD e Muon usada para treinar os checkpoints lançados do YOLO26, para cronogramas mais longos; ao especificar um otimizador, lr0 passa a valer:
from ultralytics import YOLO
# Carrega um modelo YOLO26n pré-treinado
model = YOLO("yolo26n.pt")
# Escolha SGD explicitamente; lr0 só se aplica quando o otimizador não é "auto"
results = model.train(data="coco8.yaml", epochs=5, optimizer="SGD", lr0=0.01)Com optimizer="SGD", o treinador também ativa o momentum de Nesterov, usando o argumento momentum, que é 0.937 por padrão, como coeficiente.










