Ir para o conteúdo

19. CLIP

Mais sobre PLN

Veja o curso de PLN do Tiago Tavares, que cobre Transformers e outros tópicos avançados: https://tiagoft.github.io/nlp_course/.

Todo modelo generativo dos capítulos anteriores conseguia produzir uma imagem. Nenhum deles conseguia produzir a imagem que você pediu, porque nenhum deles fazia ideia do que uma frase significa. É com o CLIP (Contrastive Language–Image Pre-training, pré-treino contrastivo entre linguagem e imagem) que isso muda e é por isso que este capítulo fica no meio de um módulo sobre geração apesar de não ser, de forma alguma, um modelo generativo.

A ideia2 é de uma simplicidade quase desconcertante. Pegue 400 milhões de pares (imagem, legenda) da internet. Treine um encoder de imagem e um encoder de texto — duas redes separadas, sem pesos compartilhados — juntos, sob uma única instrução: coloque uma imagem e a legenda dela perto uma da outra e todo o resto longe.

Esse é todo o objetivo. O que sai disso é um único espaço vetorial no qual imagens e frases habitam e portanto uma interface: agora dá para fazer perguntas que atravessam a fronteira entre modalidades. "O quão perto esta figura está da frase uma foto de um cachorro?" vira um produto escalar.

Slides

Clique nos slides e use as setas ← → para navegar; F abre em tela cheia e P abre a visão do apresentador, com as notas. Os simuladores e os diagramas desta página rodam dentro dos slides. Abrir os slides numa aba nova

Os componentes

  • Encoder de imagem — um ViT ou uma ResNet modificada (o artigo treina os dois; o melhor modelo é um ViT-L/14 a 336 px: L = Large, 24 camadas de largura 1024; /14 = patches de 14 × 14 pixels), produzindo um vetor de tamanho fixo por imagem.
  • Encoder de texto — um Transformer sobre no máximo 77 tokens, produzindo um vetor por legenda.
  • Uma projeção linear e uma normalização L2 de cada lado. Os dois encoders nem têm a mesma largura; as projeções levam os dois para o mesmo espaço de \(d\) dimensões e a normalização põe todo embedding na esfera unitária, de modo que a similaridade de cosseno é apenas um produto escalar. Toda a arquitetura se resume a esse espaço compartilhado.
  • Uma perda contrastiva (InfoNCE simétrica: uma entropia cruzada de softmax que precisa achar o par certo entre os \(N\) pares do lote) sobre um lote: a diagonal da matriz de similaridade imagem×texto está certa, todo o resto está errado.

No openai/clip-vit-base-patch32, o mais barato dos modelos ViT publicados (50 tokens por imagem) e o que o laboratório usa, um lote de \(N\) pares percorre este caminho:

passo lado da imagem lado do texto
entrada \(N \times 3 \times 224 \times 224\) \(N \times 77\) ids de token (no máximo)
encoder ViT-B/32: 49 patches + [CLS], largura 768, 12 camadas Transformer: largura 512, 12 camadas
saída agregada token [CLS]: \(N \times 768\) token de fim de texto: \(N \times 512\)
projeção \(768 \to 512\), sem viés \(512 \to 512\), sem viés
normalização L2 \(I\): \(N \times 512\), linhas unitárias \(T\): \(N \times 512\), linhas unitárias
similaridade \(S = I\,T^\top\): \(N \times N\) cossenos

O [CLS] é um token extra aprendido cuja saída resume a imagem (capítulo 13). A torre de texto agrega o token de fim de texto porque é causal (cada token só vê os anteriores): o último é o único que viu a legenda inteira.

São cerca de 87,5 milhões de parâmetros do lado da imagem e 63,2 milhões do lado do texto. As torres não compartilham nenhum peso: elas só se encontram na perda, pelo produto escalar e pela temperatura.

Como o CLIP é treinado. Um lote de quatro pares de imagem e legenda. As imagens descem pela torre de imagem (encoder de imagem, projeção, norma L2) e viram as linhas de uma matriz de similaridade 4 por 4; as legendas descem pela torre de texto e viram as colunas. A diagonal guarda os pares que casam. À direita, uma entropia cruzada ao longo de cada linha, outra ao longo de cada coluna e a perda, a média das duas. torre de imagem torre de texto um par que casa UM LOTE DE N = 4 PARES imagem 1 · “um cachorro na grama” imagem 2 · “um ônibus vermelho à noite” imagem 3 · “dois gatos num sofá” imagem 4 · “um navio no mar” imagem 3 × 224 × 224 pixels Encoder de imagem ViT-B/32 · [CLS] de largura 768 Projeção + norma L2 768 → 512 · linha unitária Ii legenda até 77 tokens Encoder de texto Transformer · largura 512 Projeção + norma L2 512 → 512 · linha unitária Tj T1 T2 T3 T4 I1 I2 I3 I4 linhas: imagem → texto softmax(S / τ), certa: coluna i colunas: texto → imagem softmax(S / τ), certa: linha j ℒ = ½ (ℒI→T + ℒT→I) duas entropias cruzadas

O que a perda de fato pede

Repare no que o CLIP não é solicitado a fazer. Ele nunca reconstrói uma imagem, nunca gera uma legenda, nunca prevê um rótulo. Só lhe pedem que distinga pares que casam de pares que não casam — e o espaço que sai de fazer isso em escala acaba codificando uma quantidade enorme de informação sobre a aparência das coisas e sobre como elas se chamam. O artigo mediu as alternativas: um Transformer que prevê a legenda palavra por palavra aprendeu o ImageNet zero-shot (classificar o ImageNet sem treinar nele, só a partir dos nomes das classes; veja abaixo) 3× mais devagar que um modelo que só prevê quais palavras aparecem; o objetivo contrastivo foi ainda 4× mais rápido. Discriminar é um objetivo muito mais barato que gerar.

A perda e as duas decisões de projeto dentro dela

Com \(I\) e \(T\) as matrizes \(N \times d\) dos embeddings normalizados de imagem e de texto (a linha \(i\) de cada uma vem do mesmo par), \(\tau > 0\) a temperatura (abaixo) e \(\text{CE}(Z, \text{diag})\) a entropia cruzada de softmax de cada linha de \(Z\) cuja classe certa é a da diagonal (linha \(i\) → coluna \(i\)):

\[ \mathcal{L} = \tfrac{1}{2}\Big( \underbrace{\text{CE}\big(\tfrac{I T^\top}{\tau},\; \text{diag}\big)}_{\text{imagem} \to \text{texto}} + \underbrace{\text{CE}\big(\tfrac{T I^\top}{\tau},\; \text{diag}\big)}_{\text{texto} \to \text{imagem}} \Big) \]

A linha \(i\) de \(I T^\top / \tau\) é um problema de classificação com \(N\) classes: qual das \(N\) legendas pertence à imagem \(i\)? A resposta certa é a classe \(i\). O segundo termo faz a mesma pergunta do lado de cada legenda, pelas colunas.

A temperatura \(\tau\) escala as similaridades antes do softmax. Um \(\tau\) pequeno afia a distribuição e a perda se concentra no negativo mais difícil (a legenda errada com a maior similaridade); um \(\tau\) grande trata todos os negativos por igual e a representação para de afiar. O CLIP aprende o \(\tau\) em vez de fixá-lo, de modo que o próprio modelo ajusta a dificuldade ao longo do treino. Ele é guardado em escala logarítmica, começa em \(\tau = 0{,}07\) e é limitado para que \(1/\tau \le 100\); os modelos publicados terminam exatamente nesse limite, \(\tau = 0{,}01\). Por que tão baixo: os cossenos de uma legenda certa e de uma errada diferem por poucos centésimos (0,26 contra 0,20 no laboratório) e só multiplicar por \(1/\tau \approx 100\) transforma essa diferença num softmax confiante. Arraste-o no painel: repare que a acurácia de busca não muda — o \(\tau\) afeta a perda, não o ranking.

O tamanho do lote faz parte do objetivo. Cada uma das outras legendas do lote é um negativo, então um lote de 32.768 dá a cada exemplo 32.767 negativos. Um modelo que chuta às cegas paga \(\log N\) (log natural) por exemplo, então um lote maior é uma tarefa mais difícil, não só mais rápida: quanto mais concorrentes, mais finas as distinções que os encoders precisam aprender. Também significou espalhar a matriz de similaridade por centenas de aceleradores e essa restrição de engenharia moldou o aprendizado contrastivo por anos.

A perda, com números

Três pares, em 3 dimensões, para que todo número possa ser conferido à mão. Os textos de propósito não são vetores unitários, porque as saídas dos encoders também não são:

\[ I = \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \end{bmatrix} \qquad T_{\text{cru}} = \begin{bmatrix} 0{,}9 & 0{,}1 & 0{,}0 \\ 0{,}1 & 0{,}8 & 0{,}1 \\ 0{,}0 & 0{,}3 & 0{,}7 \end{bmatrix} \qquad \tau = 0{,}07 \]
  1. Normalizar. As linhas de \(T_{\text{cru}}\) têm normas \(0{,}906\), \(0{,}812\) e \(0{,}762\). Dividindo cada linha pela sua norma:

    \[ T = \begin{bmatrix} 0{,}994 & 0{,}110 & 0 \\ 0{,}123 & 0{,}985 & 0{,}123 \\ 0 & 0{,}394 & 0{,}919 \end{bmatrix} \]
  2. Similaridades. \(S = I\,T^\top\). A linha \(i\) é a imagem \(i\) contra as três legendas:

    \[ S = \begin{bmatrix} 0{,}994 & 0{,}123 & 0 \\ 0{,}110 & 0{,}985 & 0{,}394 \\ 0 & 0{,}123 & 0{,}919 \end{bmatrix} \]

    A diagonal é a maior em toda linha e em toda coluna: as seis buscas já estão certas.

  3. Logits. Divida por \(\tau\):

    \[ S/\tau = \begin{bmatrix} 14{,}20 & 1{,}76 & 0 \\ 1{,}58 & 14{,}07 & 5{,}63 \\ 0 & 1{,}76 & 13{,}13 \end{bmatrix} \]
  4. Imagem → texto: softmax ao longo de cada linha. A linha 2, a que tem um concorrente de verdade: \(p_{2 \to 2}\), a probabilidade que a imagem 2 dá à legenda 2, é $ e^{14{,}07} / (e^{1{,}58} + e^{14{,}07} + e^{5{,}63}) = 0{,}99978$. As três probabilidades da diagonal são \(0{,}999995\), \(0{,}99978\) e \(0{,}999987\), então

    \[ \mathcal{L}_{I \to T} = -\tfrac{1}{3}\big(\log 0{,}999995 + \log 0{,}99978 + \log 0{,}999987\big) = 7{,}9 \times 10^{-5} \]
  5. Texto → imagem: softmax ao longo de cada coluna. Agora a coluna 3 é a difícil: a legenda 3 tem cosseno \(0{,}394\) com a imagem 2, então \(p_{3 \to 3} = e^{13{,}13} / (e^{0} + e^{5{,}63} + e^{13{,}13}) = 0{,}99945\) e \(\mathcal{L}_{T \to I} = 1{,}9 \times 10^{-4}\). As duas direções não dão o mesmo número — é por isso que a perda tira a média delas:

    \[ \mathcal{L} = \tfrac{1}{2}\big(7{,}9 \times 10^{-5} + 1{,}9 \times 10^{-4}\big) = 1{,}3 \times 10^{-4} \]
  6. Os mesmos embeddings, \(\tau = 1\). Os logits agora são o próprio \(S\), o softmax fica quase plano (a linha 2 dá \(0{,}21\); \(0{,}51\); \(0{,}28\)) e \(\mathcal{L} = 0{,}626\) — mais da metade do \(\log 3 = 1{,}10\) que um chute cego paga. O ranking (e portanto a acurácia) é idêntico. A temperatura decide o quanto a perda insiste, não o que o modelo sabe.

O CLIP real faz exatamente isto com \(N = 32.768\) e \(d\) entre 512 e 1024. O gradiente de \(\mathcal{L}\) volta pelas duas projeções até os dois encoders.

A mesma conta, como o laboratório a escreve — perda_clip, linha a linha. Percorra com o exemplo acima (é o caso inicial); depois mude um número, a temperatura ou o caso e veja qual linha se mexe:

I_cru · imagens
T_cru · legendas

SigLIP: o que o substituiu

Troque o objetivo do painel para SigLIP5 e o softmax desaparece. Cada uma das \(N^2\) células vira uma pergunta binária independente — estes dois casam? — sob uma perda sigmoide comum com uma escala \(t\) (faz o papel de \(1/\tau\); é um escalar, não a matriz de texto \(T\)) e um viés \(b\) aprendidos:

\[ \mathcal{L} = \frac{1}{N}\sum_{i}\sum_{j} \log\Big(1 + e^{\,-y_{ij}\,(\,t\,\langle I_i, T_j\rangle + b\,)}\Big), \qquad y_{ij} = \begin{cases} +1 & i = j \\ -1 & i \neq j\end{cases} \]

O viés começa bem negativo (\(b = -10\)) porque \(N - 1\) de cada \(N\) células são negativos; sem ele, os primeiros passos seriam gastos só afastando tudo de tudo. Nada é normalizado sobre o lote: sem all-gather (juntar os embeddings de todos os aceleradores para que cada um normalize sobre o lote inteiro), sem softmax distribuído. No artigo, a perda sigmoide supera o softmax com folga em lotes pequenos e empata em lotes grandes; nos dois casos os ganhos param por volta de um lote de 32 mil. A maioria dos modelos abertos recentes de visão-linguagem (VLMs: modelos de linguagem que também leem imagens), como o PaliGemma, o Idefics2 e 3 e o Gemma 3, usa um encoder de imagem da família SigLIP, então, se você for escolher uma torre de imagem hoje, comece por ela — não pelo CLIP original.

Classificação zero-shot e o que ela realmente é

Classificação zero-shot com o CLIP. Em cima, cada nome de classe vira um prompt, passa pela torre de texto e vira uma linha de uma matriz W, C por d. Embaixo, a imagem passa pela torre de imagem e vira um vetor unitário x. Os logits são W x dividido por tau; a classe com o maior é a previsão. O conjunto é uma camada linear sem viés cujos pesos foram digitados. C NOMES DE CLASSE catdogship · … UM PROMPT POR CLASSE “a photo of a cat.”“a photo of a dog.”“a photo of a ship.” … Torre de texto encoder · proj. · L2 W · C × d wcat wdog wship imagem a que vamos classificar Torre de imagem encoder · projeção · L2 x · d = 512 logits = W x / τ cosseno × 100 cat0,26 → 26 dog0,22 → 22 ship0,19 → 19 ŷ = cat argmax dos logits A MESMA COISA, COMO CAMADA nn.Linear(512, C, bias=False) peso = W: digitado, não treinado

Escreva uma frase por classe — "uma foto de um {classe}" — codifique-as, codifique a imagem, pegue a maior similaridade de cosseno. Sem treino, sem exemplos rotulados e com qualquer conjunto de classes que você consiga descrever em palavras. (Na prática, em inglês: "a photo of a {class}.", a língua das legendas em que o CLIP foi treinado.)

Escrito como camada, é um classificador linear cujos pesos foram digitados em vez de aprendidos. Empilhe os \(C\) embeddings normalizados dos prompts numa matriz \(W \in \mathbb{R}^{C \times d}\); então, para o embedding \(x\) de uma imagem,

\[ \text{logits} = \tfrac{1}{\tau}\, W x, \qquad \hat{y} = \arg\max_c\, \langle w_c, x\rangle \]

em que \(w_c\) é a linha de \(W\) da classe \(c\) e \(\langle \cdot, \cdot \rangle\) o produto escalar. Isso é uma camada nn.Linear(d, C, bias=False) com \(W\) como peso.

Para aplicar o CLIP a uma tarefa nova, tudo que precisamos é "dizer" ao encoder de texto do CLIP os nomes dos conceitos visuais da tarefa e ele produz um classificador linear das representações visuais do CLIP. A acurácia desse classificador é frequentemente competitiva com a de modelos totalmente supervisionados.1

O 'zero-shot' dessa frase promete mais do que parece

O CLIP viu 400 milhões de imagens legendadas. Se as suas classes foram descritas em algum lugar daqueles dados — e, para objetos comuns, foram, muitas vezes — isto não é zero-shot em nenhum sentido forte; é busca num conjunto de treino enorme com um índice em linguagem natural. A parte genuinamente surpreendente não é que funcione com cachorros. É que a interface é linguagem, de modo que o conjunto de classes é definido na inferência por quem estiver digitando.

O laboratório mede isso em 1.000 imagens de teste do CIFAR-10 com o ViT-B/32: 89,5 % de acurácia com "a photo of a {}.", contra 87,4 % com o nome da classe sozinho. Uma sonda linear (linear probe: uma regressão logística treinada sobre os embeddings de imagem do CLIP de \(k\) imagens rotuladas de treino do CIFAR-10 por classe) precisa de 8 a 16 por classe para alcançá-lo.

O espaço compartilhado não é dividido por igual: o gap entre modalidades

Todos os embeddings vivem na mesma esfera unitária, mas não na mesma região dela. Os embeddings de imagem se amontoam num cone estreito e os de texto em outro8. No laboratório, duas imagens ao acaso têm cosseno médio 0,755 e dois prompts ao acaso 0,671, enquanto uma imagem e o seu prompt correto chegam só a 0,258. Um classificador linear separa "este vetor é uma imagem ou uma legenda?" com 100 % de acurácia.

O gap entre modalidades, esboçado em duas dimensões. Oito imagens, em roxo, ficam num cone estreito da esfera unitária e as oito legendas, em verde, em outro; uma imagem fica mais perto das outras imagens que da sua própria legenda. Com o botão, a média de cada modalidade é subtraída e os vetores são normalizados de novo: os dois grupos se espalham pela esfera e cada imagem cai ao lado da sua legenda. imagens legendas

Isso não quebra a classificação zero-shot: o argmax só compara uma imagem com vários textos, então um deslocamento comum a todos os textos se cancela. No laboratório, tirar as duas médias move a acurácia só de 89,5 % para 91,3 %: subtrair a média \(\mu_t\) dos textos desloca a nota de todas as classes pelo mesmo \(\langle \mu_t, x \rangle\), que se cancela no argmax; já subtrair a média \(\mu_i\) das imagens desloca a classe \(c\) por \(\langle w_c, \mu_i \rangle\), que muda de classe para classe (assim como a nova normalização). São esses dois efeitos que movem a acurácia em 1,8 ponto. Mas o gap explica duas coisas que você vai ver na prática: as similaridades do CLIP entre uma imagem e um texto são números pequenos (0,2 a 0,35 para um bom par) e uma imagem costuma ficar mais perto de outras imagens que de qualquer legenda, o que importa quando você mistura as duas num mesmo índice de busca.

As limitações honestas

  • Contagem e relações espaciais


    "Três gatos" e "um gato" ficam próximos no espaço do CLIP. Assim como "a xícara sobre o livro" e "o livro sobre a xícara". O próprio artigo lista a contagem (CLEVRCounts) entre as tarefas em que o CLIP zero-shot é fraco.

  • Ele se comporta como saco de palavras


    Embaralhe as palavras de uma legenda e a busca do CLIP quase não muda7. A estrutura composicional (qual objeto tem qual atributo, quem fez o quê a quem) praticamente não aparece. Esta é a limitação mais profunda conhecida de toda a família.

  • Sensibilidade ao prompt


    No ImageNet, "a photo of a {class}." supera o "{class}" sozinho em 1,3 ponto; tirar a média dos embeddings de 80 templates escritos à mão acrescenta mais 3,5. Isso é um remendo, não uma propriedade.

  • Ele aprendeu as associações da internet


    Inclusive as que você não gostaria que ele aprendesse. Falhas documentadas em raça e gênero, ocupação e aparência. São herdadas por todo modelo construído sobre ele — incluindo geradores de imagem condicionados a embeddings de texto do CLIP.

Onde o CLIP fica neste curso

Este capítulo está aqui porque geração condicionada a texto precisa de um encoder de texto e foi do CLIP que veio um deles.

Uso O que o CLIP fornece
Condicionar um modelo de difusão O Stable Diffusion faz atenção cruzada com embeddings de texto do CLIP (capítulo 20). O SDXL usa dois encoders de texto; SD3 e FLUX acrescentam um encoder T5 (o encoder do Transformer texto-para-texto do Google, bem maior que a torre de texto do CLIP), porque a torre de texto do CLIP é pequena e seu comportamento de saco de palavras limita prompts longos e composicionais.
O encoder de imagem de um VLM A torre de visão que alimenta um modelo de linguagem costuma ser um encoder da família SigLIP (capítulo 13).
Busca Busca texto-para-imagem e imagem-para-imagem, em escala, com um produto escalar por candidato.
Avaliação O CLIPScore — o quanto a imagem gerada casa com o prompt? — é a métrica padrão de aderência ao prompt (capítulo 8.3) e herda todas as limitações acima, inclusive a cegueira à ordem das palavras.
Curadoria de dados Filtrar conjuntos imagem-texto de bilhões de itens por similaridade do CLIP. O LAION (um conjunto aberto de bilhões de pares imagem–texto da web) foi construído assim, o que significa que modelos posteriores herdam o julgamento do CLIP sobre o que é um bom par.

O resultado que importou mais que a arquitetura

Uma reprodução aberta (o benchmark DataComp, construído sobre o código do OpenCLIP) manteve fixos a arquitetura e o orçamento de treino e variou só os dados6. Um conjunto filtrado até uma fração do tamanho original bateu o conjunto inteiro; o melhor conjunto filtrado do DataComp treinou um ViT-L/14 que superou o da própria OpenAI com o mesmo custo computacional. A lição duradoura do CLIP talvez nem seja o aprendizado contrastivo: é que, nesta escala, construir o conjunto de dados é a arquitetura do modelo.

Laboratório: um espaço, medido

O comportamento do modelo descrito nesta página é medido num notebook no Colab com o modelo público openai/clip-vit-base-patch32 em imagens de teste do CIFAR-10 e do CIFAR-100. Ele roda no navegador; uma GPU T4 (gratuita no Colab) o faz levar poucos minutos e ele também roda em CPU, mais devagar. Não é preciso instalar nada. São nove seções, cada uma terminando num checkpoint com valor de verificação:

  1. as duas torres: formatos, larguras, parâmetros e onde ficam as projeções;
  2. a perda contrastiva calculada à mão num lote e conferida contra a do próprio modelo;
  3. a temperatura: o valor aprendido, o que ela muda e o que não muda;
  4. o tamanho do lote como parte do objetivo, de 2 a 100 candidatos;
  5. a classificação zero-shot como uma camada linear cujos pesos são frases;
  6. templates de prompt, do nome da classe sozinho a uma média de vários;
  7. busca imagem–texto nas duas direções;
  8. a geometria do espaço: similaridades de cosseno, o gap entre modalidades, um saco de palavras;
  9. zero-shot contra uma sonda linear (linear probe) treinada com poucos exemplos — e os seus próprios prompts, numa tabela.

Abrir o laboratório no Colab — salve uma cópia no seu Drive (Arquivo → Salvar uma cópia no Drive) para rodar e editar.

Pontos principais

  1. O CLIP treina dois encoders para colocar uma imagem e sua legenda no mesmo espaço. Esse espaço compartilhado é uma interface entre visão e linguagem, não um modelo generativo.
  2. A perda é contrastiva: a diagonal da matriz de similaridade do lote está certa, todo o resto está errado, nas duas direções. Discriminação, não reconstrução.
  3. A temperatura decide o quanto a perda liga para o negativo mais difícil e o CLIP a aprende; ela muda a perda, não o ranking. O tamanho do lote faz parte do objetivo — cada uma das outras legendas é um negativo.
  4. O SigLIP o substituiu: uma sigmoide independente por par, sem normalização sobre o lote, melhor em lotes pequenos e tão bom quanto em lotes grandes. Hoje, use um encoder da família SigLIP.
  5. Classificação zero-shot é um classificador linear cujos pesos são frases codificadas — busca com um índice em linguagem. Impressiona, mas não é mágica; a redação do prompt importa.
  6. O espaço compartilhado tem um gap entre modalidades: imagens e textos ficam em cones separados e um par imagem–texto correto tem cosseno menor que duas imagens sem relação.
  7. O CLIP é próximo de um saco de palavras: contagem, relações espaciais e composicionalidade são fracas e isso flui para todo modelo condicionado a ele.
  8. Neste curso o CLIP é a ponte: é o que permite que do capítulo 20 em diante a geração seja condicionada a uma frase. E a curadoria de dados importou mais que a arquitetura — essa é a lição duradoura.

Adicional

Embeddings L2-normalizados

Um vetor L2-normalizado tem comprimento euclidiano 1. Ele é obtido dividindo cada componente pela norma L2 do vetor3:

\[ \|v\|_2 = \sqrt{v_1^2 + v_2^2 + \dots + v_n^2}, \qquad v' = \frac{v}{\|v\|_2} = \Big[\frac{v_1}{\|v\|_2}, \frac{v_2}{\|v\|_2}, \dots, \frac{v_n}{\|v\|_2}\Big] \]

Por que o CLIP o usa

  • Só a direção é comparada. Depois da normalização o produto escalar é a similaridade de cosseno4, um número em \([-1, 1]\). Um vetor longo não ganha uma comparação só por ser longo.
  • Distância e similaridade viram o mesmo ranking. Para vetores unitários, \(\|a - b\|^2 = 2 - 2\cos(a, b)\), então a busca de vizinhos mais próximos por distância e por cosseno devolve os mesmos itens.
  • A temperatura ganha uma escala fixa sobre a qual agir. Sem normalização os logits poderiam crescer só com o crescimento das normas; com ela, os logits ficam em \([-1/\tau, 1/\tau]\) e só o \(\tau\) decide o quão afiado é o softmax.

A mesma restrição — embeddings numa hiperesfera — é comum onde quer que a saída seja uma similaridade: reconhecimento facial, busca e recomendação.



  1. CLIP: Connecting Text and Images, OpenAI, 2021. ↩

  2. Radford, A., Kim, J. W., Hallacy, C., Ramesh, A., Goh, G., Agarwal, S., Sastry, G., Askell, A., Mishkin, P., Clark, J., Krueger, G., & Sutskever, I. (2021). Learning Transferable Visual Models From Natural Language Supervision — ICML. ↩

  3. How to Normalize a Vector, Nextbridge. ↩

  4. Cosine Similarity, GeeksforGeeks. ↩

  5. Zhai, X., Mustafa, B., Kolesnikov, A., & Beyer, L. (2023). Sigmoid Loss for Language Image Pre-Training — ICCV. SigLIP; o artigo que removeu o softmax sobre o lote. ↩

  6. Gadre, S. Y., et al. (2023). DataComp: In search of the next generation of multimodal datasets — NeurIPS. Arquitetura fixa, dados variados — e os dados vencem. ↩

  7. Yuksekgonul, M., Bianchi, F., Kalluri, P., Jurafsky, D., & Zou, J. (2023). When and why vision-language models behave like bags-of-words, and what to do about it? — ICLR. ↩

  8. Liang, W., Zhang, Y., Kwon, Y., Yeung, S., & Zou, J. (2022). Mind the Gap: Understanding the Modality Gap in Multi-modal Contrastive Representation Learning — NeurIPS. ↩