# M6. Fluxo de treino e inferência
> Treinar e usar são dois algoritmos diferentes.
**Duração prevista:** 3 semanas. **Filme:** 6 minutos de animação narrada em https://llms.newortho.com.br/movimento#m6
A função de perda, o backpropagation ponta a ponta, o otimizador e o laço autorregressivo da inferência. O módulo que separa o que acontece uma vez, na fábrica, do que acontece toda vez que você manda um prompt.
**Por que este módulo existe.** Boa parte da confusão pública sobre LLMs vem de misturar treino com inferência. Quem separa os dois entende por que o modelo não aprende com a sua conversa, por que o mesmo prompt pode dar respostas diferentes, e o que exatamente um contexto longo custa.

## 1. A função de perda, na prática
Durante o treino, o modelo recebe um trecho de texto real e tenta prever cada token a partir dos anteriores. Para cada posição, compara-se a distribuição prevista com a verdade, que é uma distribuição concentrada inteiramente no token que de fato apareceu.
A cross-entropy, nesse caso particular, colapsa em algo muito simples: a perda daquela posição é apenas menos o logaritmo da probabilidade que o modelo deu ao token correto. Se deu 0,9, a perda é 0,105. Se deu 0,01, a perda é 4,6. A perda total é a média sobre todas as posições do lote.
É uma métrica honesta e cruel: o modelo é punido pelo logaritmo, então errar com muita confiança custa desproporcionalmente caro.

$$
L = -\frac{1}{N} \sum_{t} \log P\left(w_t \mid w_{<t}\right)
$$
*Leitura:* A perda é a média, sobre todas as posições, do logaritmo negativo da probabilidade atribuída ao token correto.

[Ouvir esta seção](https://llms.newortho.com.br/audio/m6-s0.webm) (narração em voz humana)

## 2. Backpropagation ponta a ponta
Com a perda calculada, a pergunta passa a ser: qual a sensibilidade da perda em relação a cada um dos parâmetros. A resposta vem da regra da cadeia aplicada da saída para a entrada.
O procedimento tem duas passagens. Na passagem para frente, a entrada atravessa todas as camadas e cada resultado intermediário é guardado. Na passagem para trás, começa-se com a derivada da perda em relação à saída e propaga-se camada a camada, multiplicando pelas derivadas locais e reaproveitando os valores guardados.
O custo de memória dessa segunda passagem é a razão de treinar exigir muito mais memória do que rodar o modelo. Em inferência, nada precisa ser guardado para trás.

[Ouvir esta seção](https://llms.newortho.com.br/audio/m6-s1.webm) (narração em voz humana)

## 3. Otimizador, lote e época
Calcular o gradiente sobre o conjunto inteiro de treino a cada passo seria proibitivo. Na prática usa-se um lote, um subconjunto aleatório, e o gradiente estimado nele. Daí o nome descida estocástica do gradiente: estocástico porque o lote é sorteado.
O otimizador usado quase universalmente hoje é o Adam, que mantém médias móveis do gradiente e do seu quadrado para ajustar automaticamente o passo de cada parâmetro. Na prática, parâmetros com gradientes historicamente grandes recebem passos menores, e vice-versa.
Uma época é uma passagem completa pelos dados. Modelos de linguagem grandes frequentemente treinam por menos de uma época sobre corpora gigantescos, o que muda a intuição herdada de aprendizado de máquina clássico.

[Ouvir esta seção](https://llms.newortho.com.br/audio/m6-s2.webm) (narração em voz humana)

## 4. Inferência: o laço autorregressivo
Quando você manda um prompt, nenhum parâmetro muda. O modelo é uma função fixa, e o que acontece é um laço.
Primeiro, todo o prompt passa pelo modelo de uma vez, etapa chamada de preenchimento, e produz um logit para a próxima posição. Escolhido o token, ele é anexado à sequência e o modelo roda de novo, agora com um token a mais. E assim por diante, um token por iteração, até um limite ou até o token de parada.
Duas consequências práticas. A geração é sequencial por natureza, e é por isso que respostas longas demoram proporcionalmente ao número de tokens. E o custo de contexto é real: como a atenção compara cada posição com todas as outras, dobrar o contexto mais do que dobra o trabalho da atenção.
Uma otimização importante: como as chaves e valores das posições anteriores não mudam, eles são guardados em um cache. Isso evita recalcular tudo a cada token e é a razão de o segundo token sair muito mais rápido que o primeiro.

[Ouvir esta seção](https://llms.newortho.com.br/audio/m6-s3.webm) (narração em voz humana)

## 5. O papel do acaso
Com temperatura zero e escolha do maior logit, o modelo é determinístico, e o mesmo prompt tende a produzir a mesma saída, ressalvadas diferenças de hardware e paralelismo que podem alterar arredondamentos.
Com temperatura acima de zero, há sorteio, e cada execução pode divergir. Um único token diferente no início muda o condicionamento de tudo que vem depois, e as saídas se separam rapidamente.
Isso responde a uma pergunta comum: o modelo não está sendo inconsistente nem mudando de opinião. Ele está amostrando de uma distribuição que ele mesmo considera plausível, e você está vendo amostras diferentes do mesmo objeto.

[Ouvir esta seção](https://llms.newortho.com.br/audio/m6-s4.webm) (narração em voz humana)

## Exercícios

1. **O modelo deu 0,25 ao token correto. Qual a perda nessa posição?**

   Menos o logaritmo natural de 0,25, aproximadamente 1,386.

2. **Por que treinar consome muito mais memória do que inferir?**

   Porque o backpropagation exige guardar as ativações intermediárias da passagem para frente para usá-las na passagem para trás. Em inferência, cada camada pode descartar o que já usou.

3. **Sua conversa de hoje muda os pesos do modelo?**

   Não. Inferência não altera parâmetro nenhum. O que muda o comportamento dentro de uma conversa é o contexto, não o modelo.

4. **O que o cache de chaves e valores evita?**

   Recalcular as projeções K e V de todas as posições anteriores a cada novo token gerado.

5. **Por que duas execuções do mesmo prompt divergem tanto com temperatura alta?**

   Porque o sorteio de um token diferente muda o condicionamento de todos os tokens seguintes, e as trajetórias se afastam de forma composta.

## Trilhos do tutor socrático

### Da probabilidade do token correto até a perda do lote (6 passos)

Um lote minúsculo, de apenas três posições. O modelo atribuiu ao token correto as probabilidades 0,25, depois 0,9 e depois 0,01. Vamos transformar isso em perda.

**Passo 1.** Na primeira posição o modelo deu probabilidade 0,25 ao token correto. Qual é a perda dessa posição, com três casas decimais?

   Resposta: 1.386. O logaritmo natural de 0,25 vale aproximadamente menos 1,386. Trocando o sinal, a perda é 1,386. O valor confere com a intuição: uma probabilidade baixa custa caro.

**Passo 2.** Na segunda posição o modelo acertou com folga e deu 0,9 ao token correto. Qual é a perda dessa posição, com três casas decimais?

   Resposta: 0.105. O logaritmo natural de 0,9 vale aproximadamente menos 0,105. Trocando o sinal, a perda é 0,105. Acertar com confiança quase não custa.

**Passo 3.** Na terceira posição o modelo deu apenas 0,01 ao token correto. Qual é a perda dessa posição, com três casas decimais?

   Resposta: 4.605. O logaritmo natural de 0,01 vale aproximadamente menos 4,605. Trocando o sinal, a perda é 4,605, mais de trinta vezes a perda da posição que acertou com 0,9.

**Passo 4.** Agora junte as três posições. Qual é a perda do lote, com três casas decimais?

   Resposta: 2.032. A soma dá aproximadamente 6,097 e a divisão por três dá 2,032. Repare como a posição de 0,01 sozinha domina a média inteira.

**Passo 5.** Qual das três posições contribuiu com mais da metade da perda do lote?

   Resposta: 2. A posição que recebeu 0,01 responde por 4,605 de uma perda total de 6,097, ou seja, cerca de três quartos. É essa a resposta, e é assim que o treino aprende: os erros confiantes puxam o gradiente.

**Passo 6.** Fechando o raciocínio ao contrário: qual probabilidade o modelo precisaria dar ao token correto para que a perda daquela posição fosse exatamente 1? Responda com três casas decimais.

   Resposta: 0.368. E elevado a menos um vale aproximadamente 0,368. Ou seja, uma perda de valor um corresponde a acertar com pouco mais de um terço de confiança.

Este trilho mostrou que a perda não é uma medida de acerto ou erro, e sim de confiança calibrada. Uma única posição errada com convicção domina a média de todo um lote.

### Por que treinar pesa mais na memória do que inferir (6 passos)

Um modelo com 40 camadas, cada uma produzindo uma ativação intermediária de 8 megabytes por exemplo. Vamos comparar o que o treino precisa guardar com o que a inferência precisa guardar.

**Passo 1.** Das duas passagens do backpropagation, qual delas guarda os resultados intermediários?

   Resposta: 0. A resposta é a passagem para frente. Ela calcula a saída e guarda cada intermediário, exatamente porque a passagem para trás vai multiplicar por derivadas locais e precisa desses valores.

**Passo 2.** E o que exatamente a passagem para trás produz ao final?

   Resposta: 1. A resposta é a sensibilidade da perda em relação a cada parâmetro, isto é, o gradiente. É com ele que o otimizador decide o ajuste.

**Passo 3.** Durante o treino, com 40 camadas e 8 megabytes de ativação por camada, quantos megabytes de ativação precisam ficar guardados para um único exemplo?

   Resposta: 320. Quarenta vezes oito dá 320 megabytes. É esse acúmulo que faz o treino estourar a memória de placas que rodam o mesmo modelo sem esforço em inferência.

**Passo 4.** Em inferência, cada camada pode descartar o que já usou assim que passa adiante. Quantos megabytes de ativação ficam vivos ao mesmo tempo, na mesma escala do enunciado?

   Resposta: 8. A resposta é 8 megabytes, o tamanho de uma só ativação. É por isso que o mesmo modelo cabe confortavelmente em hardware muito mais modesto quando apenas roda.

**Passo 5.** Qual é a razão entre a memória de ativação do treino e a da inferência, nesse exemplo?

   Resposta: 40. 320 dividido por 8 dá 40, exatamente o número de camadas. Não é coincidência: a razão é o próprio número de ativações retidas.

**Passo 6.** Qual frase resume corretamente a causa dessa diferença?

   Resposta: 1. A resposta correta é a segunda: o treino retém as ativações da ida para a passagem para trás, e a inferência simplesmente não tem passagem para trás.

Treinar e inferir usam a mesma rede, mas não o mesmo algoritmo. A memória do treino cresce com a profundidade porque a volta precisa dos valores da ida.

### Lote, época e a contagem de passos de atualização (6 passos)

Um conjunto de treino com 12.000 exemplos e um lote de 32 exemplos por passo. Vamos contar quantas vezes os pesos mudam.

**Passo 1.** Quantos passos de atualização acontecem em uma época completa?

   Resposta: 375. 12.000 dividido por 32 dá 375. São 375 atualizações de peso em uma única passagem pelos dados.

**Passo 2.** Mantendo o mesmo lote, quantos passos de atualização acontecem em três épocas?

   Resposta: 1125. 375 vezes três dá 1.125 passos de atualização no total das três épocas.

**Passo 3.** O que exatamente torna estocástica a descida estocástica do gradiente?

   Resposta: 2. É o lote. Ele é um subconjunto aleatório e o gradiente calculado nele é uma estimativa do gradiente verdadeiro, daí o termo estocástico.

**Passo 4.** Se o lote dobrar para 64 exemplos, quantos passos de atualização passa a ter uma época?

   Resposta: 187.5. 12.000 dividido por 64 dá 187,5. Na prática, isso significa 187 lotes cheios e um lote final pela metade.

**Passo 5.** Quantas épocas modelos de linguagem grandes costumam treinar sobre os seus corpora?

   Resposta: 1. A resposta é: frequentemente menos de uma época sobre corpora gigantescos. É por isso que a intuição clássica sobre repetir épocas não se transfere diretamente.

**Passo 6.** O que o otimizador Adam mantém, além do gradiente do passo atual?

   Resposta: 0. A resposta é: médias móveis do gradiente e do seu quadrado. Com elas, parâmetros de gradiente historicamente grande recebem passos menores, e vice-versa.

Lote e época contam coisas diferentes: um mede o quanto se vê por atualização, o outro mede quantas voltas se dá nos dados. Confundir os dois desorganiza qualquer leitura de curva de treino.

### O custo real do laço autorregressivo (6 passos)

Um prompt de 200 tokens e uma resposta de 50 tokens. O preenchimento leva 300 milissegundos e cada token seguinte leva 20 milissegundos.

**Passo 1.** Depois de gerados os 50 tokens da resposta, quantos tokens tem a sequência completa?

   Resposta: 250. 200 mais 50 dá 250 tokens. É esse o comprimento que a atenção enxerga na última iteração.

**Passo 2.** Contando o preenchimento como a rodada que produz o primeiro token, quantas vezes o modelo roda ao todo para entregar os 50 tokens?

   Resposta: 50. São exatamente 50 rodadas, uma por token. É essa serialização que faz respostas longas demorarem proporcionalmente ao número de tokens.

**Passo 3.** Com preenchimento de 300 milissegundos e 20 milissegundos por token seguinte, qual é o tempo total, em milissegundos, para entregar os 50 tokens?

   Resposta: 1280. 49 vezes 20 dá 980, e somando os 300 do preenchimento chega-se a 1.280 milissegundos, pouco menos de um segundo e trezentos.

**Passo 4.** O que exatamente o cache de chaves e valores evita?

   Resposta: 0. A resposta é a primeira: o cache evita recalcular as projeções de chave e valor das posições anteriores. É por isso que o segundo token sai muito mais rápido que o primeiro.

**Passo 5.** Por que dobrar o contexto mais do que dobra o trabalho da atenção?

   Resposta: 0. A resposta correta é a primeira: a atenção compara cada posição com todas as outras, e é esse crescimento quadrático que faz o contexto longo custar caro.

**Passo 6.** Se o trabalho da atenção cresce com o quadrado do número de posições, por quanto ele é multiplicado ao passar de 1.000 para 4.000 posições?

   Resposta: 16. Quatro ao quadrado dá 16. Quadruplicar o contexto multiplica por dezesseis o trabalho da atenção, e é esse o preço concreto de janelas longas.

A inferência é um laço, não um cálculo único. Tempo de resposta, custo de contexto e o efeito do cache saem todos dessa mesma estrutura sequencial.

### Por que duas execuções do mesmo prompt se separam (5 passos)

Suponha que, com a temperatura escolhida, a chance de duas execuções sortearem o mesmo token em uma dada posição seja 0,9. Vamos ver o que acontece ao longo da resposta.

**Passo 1.** Com temperatura zero e escolha sempre do maior logit, o que se espera de duas execuções do mesmo prompt?

   Resposta: 0. A resposta é a primeira: a saída tende a ser a mesma, com a ressalva honesta de que arredondamentos de hardware e paralelismo podem, em raros casos, mudar qual logit é o maior.

**Passo 2.** Com chance 0,9 de coincidência por posição e posições independentes, qual é a probabilidade de duas execuções coincidirem nos três primeiros tokens? Responda com três casas decimais.

   Resposta: 0.729. 0,9 elevado a três dá 0,729. Ou seja, mais de um quarto das duplas de execução já divergiu antes do quarto token.

**Passo 3.** E qual é a probabilidade de coincidirem nos dez primeiros tokens? Responda com três casas decimais.

   Resposta: 0.349. 0,9 elevado a dez dá aproximadamente 0,349. Em dez tokens, a chance de duas execuções seguirem idênticas já caiu para cerca de um terço.

**Passo 4.** Então qual é a probabilidade de as duas execuções já terem divergido em algum ponto dos dez primeiros tokens? Responda com três casas decimais.

   Resposta: 0.651. Um menos 0,349 dá 0,651. Cerca de dois terços das duplas já se separaram nos dez primeiros tokens, e a partir daí o condicionamento diferente afasta as trajetórias de vez.

**Passo 5.** Diante de duas respostas bem diferentes para o mesmo prompt, qual é a leitura correta?

   Resposta: 1. A resposta é a segunda: você está vendo duas amostras da mesma distribuição. Não há inconsistência nem mudança de opinião, há amostragem.

A divergência entre execuções é composta: cada sorteio muda o condicionamento de tudo o que vem depois. Determinismo e variação são escolhas de procedimento, não traços de personalidade do modelo.

## Dúvidas frequentes

**A conversa que eu tenho hoje com o modelo treina ele de alguma forma?**

Não. Inferência não altera parâmetro nenhum: o modelo é uma função fixa enquanto responde. O que muda o comportamento dentro de uma conversa é o contexto, ou seja, o texto que já está na janela e volta a ser lido a cada iteração. Assim que a conversa termina, esse contexto some e o modelo continua exatamente como estava. Treinar é outro procedimento, feito antes, com perda, gradiente e otimizador.

**Por que a mesma pergunta me dá respostas diferentes em execuções diferentes?**

Porque com temperatura acima de zero o token de cada posição é sorteado, e não simplesmente o mais provável. Um único token diferente logo no início muda o condicionamento de tudo o que vem depois, e as duas trajetórias se afastam de forma composta. O modelo não está sendo inconsistente nem mudando de opinião: você está vendo amostras diferentes da mesma distribuição. Com temperatura zero e escolha do maior logit, a saída tende a se repetir.

**Qual é a diferença prática entre lote e época?**

O lote é o subconjunto sorteado de exemplos usado em um único passo de atualização dos pesos. A época é uma passagem completa por todo o conjunto de dados. Dividindo o número de exemplos pelo tamanho do lote você obtém quantas atualizações acontecem em uma época. São grandezas de níveis diferentes: uma conta o que o modelo vê por passo, a outra conta quantas voltas ele deu nos dados.

**Por que treinar exige tanta memória de GPU e rodar o modelo não exige?**

Porque o backpropagation tem duas passagens. Na ida, cada camada produz um resultado intermediário que precisa ficar guardado, já que a volta vai multiplicar pelas derivadas locais e reaproveitar exatamente esses valores. Com dezenas de camadas, essas ativações se acumulam. Em inferência não existe volta, então cada camada descarta o que já usou assim que passa o resultado adiante.

**Por que a perda usa logaritmo em vez de medir simplesmente o quanto errou?**

Porque o logaritmo pune de forma desproporcional a confiança equivocada. Dar 0,9 ao token correto custa 0,105, dar 0,25 custa 1,386 e dar 0,01 custa 4,605. Uma medida linear trataria esses três casos como quase equivalentes, e o treino não teria pressão para corrigir justamente os erros mais graves. Além disso, o logaritmo transforma produtos de probabilidades ao longo da sequência em somas, o que torna a conta estável.

**Se a perda é uma média, uma única posição muito errada estraga o lote inteiro?**

Ela domina, e isso é intencional. Como a perda cresce sem limite quando a probabilidade do token correto se aproxima de zero, uma posição catastrófica pode responder sozinha pela maior parte da média. No exemplo do trilho, uma posição de 4,605 pesa mais que as outras duas somadas. O efeito prático é que o gradiente aponta preferencialmente para corrigir os erros confiantes, que é o comportamento desejado.

**O que o Adam faz de diferente da descida do gradiente simples?**

A descida simples aplica o mesmo passo a todos os parâmetros. O Adam mantém duas médias móveis por parâmetro, uma do gradiente e outra do quadrado do gradiente, e usa a segunda para dimensionar o passo individualmente. Na prática, parâmetros com gradientes historicamente grandes recebem passos menores e parâmetros com gradientes pequenos recebem passos maiores. É por isso que ele exige menos ajuste manual de taxa de aprendizado.

**Por que o primeiro token demora bem mais que os seguintes?**

Porque o primeiro token vem do preenchimento, a etapa em que o prompt inteiro atravessa o modelo de uma vez. Todos os tokens do prompt precisam ter as suas projeções calculadas nessa rodada. A partir do segundo token, as chaves e valores das posições anteriores já estão no cache e só a posição nova precisa ser processada. Daí a diferença de tempo entre a primeira e as demais iterações.

**O que exatamente o cache de chaves e valores guarda?**

Guarda as projeções de chave e de valor já calculadas para cada posição anterior da sequência. Como essas projeções não mudam quando um token novo é anexado ao final, recalculá-las a cada iteração seria repetir trabalho idêntico. O cache troca memória por tempo: ocupa espaço proporcional ao comprimento do contexto e economiza a maior parte do cálculo em cada iteração seguinte.

**Dobrar o tamanho do contexto dobra o custo de rodar o modelo?**

Mais do que dobra, por causa da atenção. Como cada posição é comparada com todas as outras, o número de comparações cresce com o quadrado do número de posições. Dobrar o contexto multiplica por quatro o trabalho dessa parte, e quadruplicar multiplica por dezesseis. As demais partes do bloco crescem de forma linear, então o custo total fica entre o linear e o quadrático, mas a atenção é quem manda quando o contexto é longo.

**Temperatura zero garante que eu receba exatamente a mesma saída sempre?**

Garante a mesma saída em teoria, porque a escolha do maior logit não envolve sorteio. Na prática existe uma ressalva honesta: diferenças de hardware, de ordem de paralelismo e de arredondamento em ponto flutuante podem alterar qual logit é o maior quando dois estão muito próximos. Isso é raro, mas acontece. Temperatura zero remove o acaso do sorteio, não o ruído numérico da máquina.

**Modelos grandes treinam por quantas épocas?**

Frequentemente por menos de uma época, o que costuma surpreender quem vem do aprendizado de máquina clássico. Quando o corpus é gigantesco, uma única passagem já consome todo o orçamento de cálculo disponível, e o modelo pode nem ver o mesmo trecho duas vezes. Isso muda a intuição sobre memorização e sobre repetir dados: aqui, o risco de decorar um exemplo específico é diferente do risco em conjuntos pequenos revisitados dezenas de vezes.

**O que são a passagem para frente e a passagem para trás, em uma frase cada?**

A passagem para frente leva a entrada por todas as camadas até a saída, calculando a perda e guardando cada resultado intermediário. A passagem para trás começa na derivada da perda em relação à saída e caminha camada a camada no sentido inverso, multiplicando pelas derivadas locais até obter a sensibilidade da perda em relação a cada parâmetro. A primeira produz o resultado, a segunda produz o gradiente.

**Se eu corrigir o modelo no meio da conversa, ele guarda essa correção para depois?**

Dentro da mesma conversa, sim, porque a correção passa a fazer parte do contexto e volta a ser lida a cada iteração do laço. Fora dela, não. Nenhum peso foi alterado, então uma conversa nova começa sem qualquer traço da correção anterior. Se você precisa que um ajuste persista, ele tem que ser reintroduzido no contexto, por instrução de sistema ou por outro mecanismo externo ao modelo.

**Por que respostas longas demoram proporcionalmente ao seu tamanho?**

Porque a geração é sequencial por natureza. Cada iteração do laço produz um token, esse token é anexado à sequência e só então o modelo roda de novo. Não há como produzir o décimo token sem ter produzido o nono, já que ele condiciona o cálculo. O tempo total é, portanto, o preenchimento somado ao custo por token multiplicado pelo número de tokens gerados.

## Checkpoint

1. Escreva a perda de uma posição em função da probabilidade do token correto.

   Menos o logaritmo dessa probabilidade.

2. Quais são as duas passagens do backpropagation e o que cada uma faz?

   A passagem para frente calcula a saída e guarda os intermediários; a passagem para trás propaga as derivadas da perda até cada parâmetro.

3. Explique a diferença entre lote e época.

   O lote é o subconjunto sorteado usado em um passo de atualização; a época é uma passagem completa por todo o conjunto de dados.

4. Descreva o laço autorregressivo em três frases.

   O prompt inteiro é processado e gera um logit para a próxima posição. Um token é escolhido e anexado à sequência. O modelo roda de novo com a sequência aumentada, repetindo até parar.

5. Por que o primeiro token demora mais que os seguintes?

   Porque o preenchimento processa o prompt inteiro de uma vez, enquanto os tokens seguintes aproveitam o cache de chaves e valores e só processam a posição nova.

## Bibliografia

- **Deep Learning**, Ian Goodfellow, Yoshua Bengio e Aaron Courville, MIT Press, 2016, livro aberto. Capítulo 6, Deep Feedforward Networks, e capítulo 8, Optimization for Training Deep Models. O capítulo 6 fecha backpropagation e o 8 explica por que o treino de fato funciona, incluindo lote, momento e Adam.

- **Deep Learning: Foundations and Concepts**, Christopher M. Bishop e Hugh Bishop, Springer, 2024. Capítulos de descida do gradiente e de backpropagation. Versão moderna e mais legível dos mesmos assuntos, com notação alinhada à dos papers atuais.

## Vídeos curados

- [Backpropagation calculus](https://www.youtube.com/watch?v=tIeHLnjs5U8), 3Blue1Brown, Neural Networks cap. 4. Formaliza o que o M3 introduziu como intuição.

- [Let's build GPT: from scratch, in code](https://www.youtube.com/watch?v=kCc8FmEb1nY), Andrej Karpathy. Longo e opcional, mas se você quiser ver treino e inferência acontecendo em código, é a referência. Assista em blocos de trinta minutos.
