O que é LoRA: Low-Rank Adaptation
Adaptar um modelo de bilhões de parâmetros por fine-tuning tradicional significa recalcular e armazenar gradientes para todos eles: dias de GPU e memória que pouca gente tem. LoRA parte de uma observação simples e profunda: a mudança que o ajuste fino precisa fazer nos pesos tem rank baixo, ela ocupa pouquíssimas direções do espaço disponível. Em vez de aprender a matriz de mudança inteira (), LoRA a escreve como o produto de duas matrizes finas, , e treina só essas duas. Com dimensão 4096 e rank , são 65.536 parâmetros por camada no lugar de 16,7 milhões, uma redução de 256 vezes. Os pesos originais ficam congelados, e no fim o produto é somado de volta: o modelo adaptado tem a mesma arquitetura e a mesma latência do original, sem nenhum custo extra de inferência.
Você tem um modelo de linguagem já treinado e quer adaptá-lo para uma tarefa específica: entender contratos jurídicos brasileiros, responder sobre o catálogo de uma empresa, lidar com a terminologia de um setor regulado. A resposta certa está nos pesos do modelo, mas mexer em todos eles custa caro demais. E se a mudança necessária fosse muito menor do que parece?
A abordagem mais direta para essa adaptação é fazer fine-tuning: continuar o treinamento do modelo usando exemplos da nova tarefa. Conceitualmente o processo é simples, mas, na prática, ele esbarra num problema de escala. Modelos modernos possuem bilhões de parâmetros, e o fine-tuning tradicional atualiza todos eles, o que significa calcular gradientes para cada peso, armazenar estados do otimizador e movimentar uma quantidade enorme de dados pela GPU a cada passo de treinamento. Durante muito tempo, parecia não haver alternativa: se você queria mudar o comportamento do modelo, precisava modificar todos os seus pesos.
O LoRA, que significa Low-Rank Adaptation (adaptação de rank baixo), surgiu a partir de uma observação simples, mas profunda: talvez não seja necessário atualizar todos os parâmetros para adaptar um modelo, porque a mudança realmente importante é muito menor do que o tamanho da matriz sugere. Para entender por que isso funciona, o resto do post olha para o que de fato acontece durante o fine-tuning, e mostra como uma única ideia de álgebra linear corta o custo da adaptação em mais de 99%.
O problema que LoRA resolve: por que ajustar um modelo inteiro é caro demais
Ajustar um modelo grande significa pegar os pesos que ele já tem e continuar treinando, agora com dados da sua tarefa. O obstáculo não é conceitual, é de escala. Um modelo como o Llama 2 7B tem 7 bilhões de parâmetros, e cada camada de atenção carrega uma matriz de pesos com dimensão 4096×4096, ou seja, 16,7 milhões de números, repetida ao longo de dezenas de camadas. Cada passo de treino exige passar o gradiente por todos esses parâmetros, guardar os estados do otimizador (o Adam armazena dois valores por parâmetro, a média do gradiente e a média do quadrado do gradiente) e manter tudo na GPU ao mesmo tempo. O resultado é que o fine-tuning completo de um modelo de 7B precisa, na prática, de uma GPU com 80 GB ou mais, e o treino leva dias.
Para o exemplo dos contratos jurídicos, isso quer dizer que cada tentativa de adaptar o modelo custa caro, e cada novo hiperparâmetro que você queira testar paga o preço de novo. O custo deixa de ser um detalhe de engenharia e vira uma barreira: você não experimenta, não itera, não descobre o que funciona. A saída tradicional era aceitar essa conta ou recuar para modelos pequenos que não capturam a complexidade do domínio. LoRA oferece uma terceira via, e ela começa com uma pergunta sobre o que o fine-tuning de fato aprende.
O que o fine-tuning realmente aprende
Considere uma matriz de pesos qualquer do modelo, que vamos chamar de . Antes do treinamento, ela possui determinados valores; depois do fine-tuning, ela passa a ter valores ligeiramente diferentes. Podemos representar essa mudança separando o que o modelo já sabia do que ele acabou de aprender:
Aqui é a matriz depois do treino e é tudo o que foi aprendido. Essa expressão importa porque isola duas coisas que costumam ficar embaralhadas: o conhecimento original do modelo, armazenado em , e a adaptação para a nova tarefa, armazenada em . Quando fazemos fine-tuning tradicional, o treinamento aprende diretamente , o que na prática significa ajustar potencialmente milhões de elementos em cada matriz de pesos, com total liberdade para mexer em qualquer direção do espaço. A pergunta que dá origem ao LoRA é justamente se toda essa liberdade é mesmo necessária.
A hipótese central: a atualização tem rank baixo
O insight por trás do LoRA veio de trabalhos que estudavam a chamada dimensão intrínseca de modelos superparametrizados, em especial Aghajanyan et al. (2020). A observação era curiosa: embora esses modelos possuam um número enorme de parâmetros, as mudanças necessárias para adaptá-los a novas tarefas parecem ocupar uma região muito menor do espaço disponível. Em outras palavras, o modelo tem bilhões de graus de liberdade, mas o ajuste fino costuma usar apenas uma pequena parte deles. O paper do LoRA, de Hu et al. (2021), transforma essa observação numa hipótese concreta: a atualização tem estrutura de rank baixo. Essa frase é o coração da técnica, e para entendê-la precisamos falar do que significa rank.
Uma forma intuitiva de pensar em rank é como uma medida da quantidade de direções independentes que uma matriz consegue representar. Imagine uma multidão atravessando uma estação de metrô: em princípio, cada pessoa poderia caminhar em qualquer direção, mas, na prática, quase todas seguem alguns poucos fluxos principais, entrada, saída e acesso às plataformas. Embora existam milhares de trajetórias individuais, a dinâmica coletiva pode ser descrita por um número muito menor de direções dominantes, e é exatamente essa ideia que o rank captura. Uma matriz de rank alto possui muitas direções independentes; uma matriz de rank baixo concentra seu comportamento em poucas direções principais.
O que o LoRA sugere é que as atualizações produzidas pelo fine-tuning se parecem com o segundo caso. Mesmo que a matriz original seja enorme, a mudança necessária para adaptar o modelo costuma estar concentrada num conjunto relativamente pequeno de direções relevantes. Se isso for verdade, treinar todos os elementos de é desperdício, e a evidência de que é verdade é forte: para o GPT-3 175B, cuja matriz de pesos tem dimensão 12.288, um rank de apenas 1 já produz desempenho competitivo com o fine-tuning completo, ou seja, a mudança inteira cabe numa única direção. Isso não é coincidência, é uma propriedade estrutural de como modelos grandes aprendem.
A matemática do LoRA: ΔW = B·A e a decomposição de rank baixo
É aqui que a álgebra linear entra. Uma propriedade importante das matrizes é que qualquer matriz de rank baixo pode ser escrita como o produto de duas matrizes menores. Em vez de aprender diretamente , o LoRA escreve , onde e . Aqui é a dimensão da camada e é um número pequeno chamado rank, o hiperparâmetro central da técnica. A ideia é simples: em vez de aprender uma matriz grande, aprendemos duas matrizes pequenas cujo produto produz a atualização desejada. Mas por que isso funciona? A resposta está nas dimensões.
Suponha que a matriz original tenha dimensão . A matriz tem dimensão e a matriz tem dimensão . Como as dimensões internas coincidem, podemos multiplicá-las, e o resultado tem exatamente o mesmo formato da matriz original:
Isso é essencial porque queremos somar a atualização aos pesos, , e a soma só é possível porque ambas têm as mesmas dimensões. Do ponto de vista da arquitetura do modelo, nada muda: a camada continua recebendo e produzindo vetores do mesmo tamanho. O que muda é apenas a forma como a atualização é representada, e a economia que isso traz é enorme. Para o Llama 2 7B, com e , a matriz tem 4096×4096 = 16.777.216 parâmetros, enquanto e juntas têm 4096×8 + 8×4096 = 65.536, uma redução de 256 vezes. Em vez de treinar 16,7 milhões de números por camada, você treina 65 mil.
LoRA reduz o número de parâmetros treináveis em 256 vezes, de 16,7 milhões para 65 mil por camada, sem perder a capacidade de adaptar o modelo.
O significado geométrico de A e B: o gargalo da adaptação
A fatoração não é só um truque algébrico, ela tem uma interpretação intuitiva. A matriz atua como uma compressão: ela pega um vetor que vive num espaço de dimensão e o projeta num espaço muito menor, de dimensão . Se e , por exemplo, estamos reduzindo milhares de dimensões para apenas oito. Depois entra a matriz , que pega essa representação compacta e a expande de volta para o espaço original, fechando o fluxo . Toda a atualização precisa passar por esse gargalo, e é aí que mora a restrição que torna o método eficiente: a adaptação não pode ocupar qualquer direção possível do espaço original, ela é obrigada a viver dentro de um subespaço de dimensão .
É essa mesma imagem que dá sentido ao papel do rank. O controla a capacidade da adaptação, e pensá-lo como a largura do gargalo deixa o trade-off óbvio: quanto mais estreito o gargalo, mais compacta precisa ser a solução aprendida; quanto mais largo, maior a flexibilidade, mas também maior o custo. Se for muito pequeno, a atualização pode ficar excessivamente restrita; se for muito grande, parte da eficiência do método se perde. Na prática, valores relativamente pequenos costumam funcionar surpreendentemente bem, o que reforça a hipótese de partida: muitas adaptações realmente podem ser descritas usando poucas direções relevantes.
O que realmente é treinado
Durante o treinamento, a matriz original permanece congelada: ela não recebe gradientes e não muda. Os únicos parâmetros atualizados são as matrizes e . A saída da camada, que originalmente era , passa a somar o caminho extra da adaptação:
O primeiro termo continua sendo o comportamento original do modelo, congelado, e o segundo termo é a adaptação aprendida para a nova tarefa. Toda a aprendizagem acontece dentro desse caminho adicional, e é isso que reduz drasticamente o número de parâmetros treináveis. Em vez de armazenar gradientes e estados do otimizador para a matriz inteira, precisamos fazê-lo apenas para e , que são muito menores. O efeito sobre a memória é direto: um fine-tuning completo do Llama 2 7B pode exigir 80 GB de VRAM, enquanto o mesmo treino com LoRA cabe numa GPU de 24 GB, porque o gradiente e os estados do otimizador passam a ser proporcionais aos 65 mil parâmetros por camada, não aos 16,7 milhões.
O que acontece depois do treinamento: fusão sem custo extra
Uma vantagem importante do LoRA aparece quando o treinamento termina. A adaptação aprendida é dada por , e nada impede que calculemos esse produto uma única vez e o incorporemos diretamente aos pesos originais, . Depois dessa fusão, o modelo volta a ter exatamente a mesma estrutura de antes: não existem camadas extras, não existem multiplicações adicionais, não existe custo extra de inferência. O modelo adaptado possui a mesma arquitetura e a mesma latência do original, e a única diferença é que seus pesos agora incorporam a atualização aprendida.
Essa fusão, vale notar, é opcional. Você também pode manter e separadas e trocá-las dinamicamente para diferentes tarefas, sem recarregar o modelo inteiro, o que é uma vantagem prática e tantas vezes decisiva para sistemas que servem vários ajustes finos a partir de um mesmo modelo base. Em um caso você ganha latência idêntica à do original; no outro, ganha a flexibilidade de carregar e descarregar adaptações como se fossem plugins.
Por que o LoRA funciona tão bem
A pergunta natural é por que uma atualização tão restrita consegue competir com o fine-tuning completo. A resposta mais aceita é que o próprio fine-tuning tradicional já opera, na prática, dentro de um subespaço relativamente pequeno. Embora o algoritmo tenha liberdade para modificar bilhões de parâmetros, os gradientes tendem a se alinhar em poucas direções dominantes durante o treino. O LoRA não cria essa estrutura, ele apenas assume que ela existe e constrói um mecanismo que a explora de forma explícita. Por isso, em muitos benchmarks, treinar uma pequena fração dos parâmetros produz resultados comparáveis aos do ajuste completo, e às vezes melhores.
O que parece um truque de compressão acaba revelando algo mais profundo sobre a própria geometria do aprendizado em modelos grandes. À primeira vista, o LoRA parece apenas uma técnica para economizar memória, mas sua contribuição principal é conceitual: ele parte da ideia de que a adaptação de um modelo não precisa explorar todo o espaço de parâmetros disponível, porque as mudanças que importam estão concentradas em poucas direções. Se essa hipótese estiver correta, não faz sentido treinar tudo; basta aprender essas direções e incorporá-las ao modelo. Em vez de modificar bilhões de parâmetros, o LoRA aprende uma atualização compacta que captura a essência da adaptação, reduzindo drasticamente o custo do fine-tuning sem alterar a arquitetura nem comprometer a capacidade de adaptação. Mais do que uma otimização de engenharia, ele é a consequência direta de uma ideia matemática: às vezes, a mudança que importa ocupa muito menos espaço do que imaginamos.
Onde a Pumpkin entra
LoRA é uma das técnicas que a Pumpkin tem à disposição no harness para adaptar modelos a domínios específicos sem o custo de um fine-tuning completo. Mas a parte mais importante do nosso trabalho vem antes de chegar a ela. A maioria dos times pula direto para fine-tuning ou LoRA assim que o modelo erra o jargão do negócio, como se treinar peso fosse o único caminho. Na prática, com o harness certo, quase nunca é. Boa parte do que parece exigir um modelo adaptado se resolve antes, na camada de contexto: o knowledge graph e a recuperação estruturada colocam os fatos certos na frente do modelo a cada pergunta, e o comportamento que se queria treinar emerge do contexto bem montado, sem mexer em nenhum peso.
É aí que a expertise da Pumpkin entra de verdade: em decidir quando a adaptação de pesos é realmente necessária e quando ela é só custo disfarçado de solução. Treinar um LoRA tem preço, em GPU, em tempo de iteração e em uma peça a mais para versionar e manter. Antes de pagar isso, a gente esgota o que o harness já resolve de graça, e só recorre ao LoRA quando o ganho justifica, quando a tarefa exige um comportamento que o contexto sozinho não induz, como um estilo de saída muito específico ou uma terminologia que precisa estar nos próprios pesos. Quando esse momento chega, LoRA entrega a adaptação com GPU modesta e sem custo extra de inferência; quando não chega, a gente economiza o cliente de um treino que não precisava existir.
A lição que fica é dupla. O custo de adaptar um modelo grande não precisa ser proporcional ao tamanho dele, e, mais do que isso, muitas vezes a adaptação de pesos nem é o passo certo. Saber a diferença, e construir o harness que torna essa escolha possível, é o que separa um bom agente caro de um bom agente que não desperdiça tempo nem dinheiro.
O que é LoRA e como funciona?
O que significa dizer que a atualização tem rank baixo?
Quanto LoRA reduz o número de parâmetros treináveis?
LoRA tem custo extra de inferência?
Qual é o papel do rank r no LoRA?
Qual a diferença entre LoRA e fine-tuning completo?
- Hu, E. et al. LoRA: Low-Rank Adaptation of Large Language Models. ICLR, 2022.
- Aghajanyan, A. et al. Intrinsic Dimensionality Explains the Effectiveness of Language Model Fine-Tuning. ACL, 2020.