O que é codificação posicional?

O que é codificação posicional?

A codificação posicional é uma técnica que injeta informações sobre a posição das palavras em uma sequência para arquiteturas de transformação.

A ordem das palavras desempenha um papel fundamental na compreensão do significado semântico de uma frase. Por exemplo, "Allen leva o cachorro para passear" e "o cachorro leva Allen para passear" têm significados totalmente diferentes, apesar de terem as mesmas palavras ou tokens. Ao implementar aplicações de processamento de linguagem natural (NLP) utilizando deep learning e redes neurais, precisamos criar um mecanismo pelo qual as máquinas possam reter as ordens das palavras em uma frase para produzir saídas lógicas.  

Tradicionalmente, modelos como redes neurais recorrentes (RNNs), ou memórias de longo curto prazo (LSTM), têm um mecanismo integrado que lida com a ordem das palavras. RNNs e LSTMs processam as entradas sequencialmente, um token de cada vez, memorizando todas as posições de palavras em uma sequência. Em outras palavras, o vetor de dimensão n, também chamado de "vetor de entrada", é processado um após o outro, aprendendo ordens de forma inerente. Ao contrário, outras arquiteturas que aproveitam redes neurais convolucionais (CNNs) ou transformadores (Vaswani et al. 2017) não retêm a ordem das palavras e processam tokens em paralelo. Portanto, precisamos implementar um mecanismo que possa representar explicitamente a ordem das palavras em uma sequência — uma técnica conhecida como codificação posicional. A codificação posicional permite que o transformador retenha informações da ordem das palavras, possibilitando a paralelização e o treinamento eficiente do modelo. É possível encontrar implementações de codificação posicional no GitHub com frequência.  

As mais recentes tendências em IA, trazidas a você por especialistas

Receba insights selecionados sobre as notícias mais importantes (e intrigantes) sobre IA. Inscreva-se no nosso boletim informativo semanal Think. Consulte a Declaração de privacidade da IBM.

Agradecemos a você! Você se inscreveu.

Sua assinatura será entregue em inglês. Você encontrará um link para cancelar a assinatura em cada boletim informativo. Você pode gerenciar suas assinaturas ou cancelar a assinatura aqui. Consulte nossa Declaração de privacidade da IBM para obter mais informações.

Por que a codificação posicional é importante?

A ordem das palavras em uma frase ou sequência dita o significado inerente da frase em linguagens naturais. Além disso, para o aprendizado de máquina, a codificação da ordem das palavras nos fornece um "dicionário" onde cada palavra deve estar. Essas informações são retidas e podem ser generalizadas durante todo o treinamento de modelos de transformadores, permitindo a paralelização e superando RNNs e LSTMs por sua eficiência de treinamento.  

Vamos revisitar o exemplo:

  • "Allen leva o cão para passear"
  • "O cão leva Allen para passear"

Essas duas frases com os mesmos três tokens têm significados totalmente diferentes com base nas ordens de palavras. Os transformadores, que dependem da autoatenção e do mecanismo de atenção multicabeças, não têm representação inerente de ordens de palavras e tratariam a palavra individual em uma sequência de forma idêntica se não fornecêssemos informações posicionais explícitas. Queremos que o modelo entenda quem está passeando e quem está sendo levado para passear, o que depende totalmente das posições.  

Alcançamos esse objetivo processando primeiro cada palavra como um vetor que representa seu significado — por exemplo, "cão" será codificado em uma matriz de alta dimensão que codifica seu conceito. Em termos técnicos, cada palavra ou subpalavra é mapeada para uma embedding de entrada de comprimentos variados. No entanto, por si só, o vetor de significado não nos diz onde o cachorro aparece na frase. A codificação posicional adiciona um segundo vetor, um que codifica o índice de posição, como "primeira palavra" ou "segunda palavra" e assim por diante. Os dois vetores são, então, adicionados para representar o que a palavra é e onde ela se encontra. Esse vetor resultante é geralmente chamado de vetor de codificação posicional.   

Há várias maneiras de criar codificação posicional. Neste artigo, exploramos o exemplo mais conhecido do uso de uma função senoidal apresentado pelos autores em Attention is all you need1 para criar codificação posicional.  

Mixture of Experts | 28 de agosto, episódio 70

Decodificando a IA: resumo semanal das notícias

Participe do nosso renomado painel de engenheiros, pesquisadores, líderes de produtos e outros enquanto filtram as informações sobre IA para trazerem a você as mais recentes notícias e insights sobre IA.

Codificação posicional em transformadores

No artigo original apresentado por Vaswani et al. 2017, a ideia fundamental é gerar uma codificação fixa e determinística para cada posição em uma sequência usando uma função senoidal — particularmente, a função seno sin(x) e a função cosseno cos(x) .  

O que são funções senoidais?

As funções seno são um conceito matemático fundamental que produz um padrão de comprimento de onda suave. Em particular, as funções cosseno e seno são usadas pelos autores nas funções originais do transformador para auxiliar na codificação posicional.

Se plotarmos sin(x) e  cos(x) , veremos uma curva que sobe e desce entre -1 e 1 em um padrão periódico repetido.

Algumas propriedades do seno que o tornam poderoso para codificação posicional: 

  • É periódico: repete-se regularmente em intervalos, o que é útil para representar padrões repetidos.

  • É suave e contínuo: pequenas mudanças na entrada resultam em pequenas mudanças na saída, o que nos dá uma maneira de representar posições em um espaço diferenciável.

  • Ao variar a frequência dos comprimentos de onda em todas as dimensões, podemos criar uma representação multiescalas rica da posição. 

Vamos plotar as ondas de seno e cosseno para visualizar como elas são:

import numpy as np 
import matplotlib.pyplot as plt 

# Create an array of 100 x values evenly spaced from 0 to 2π (approx 6.28)
x = np.linspace(0, 2 * np.pi, 100) 

# Compute the sine and cosine of each x value 
sin_values = np.sin(x) 

# Create the plot 
plt.figure(figsize=(5, 2)) 
plt.plot(x, sin_values, label='sin(x)', color='blue') 

# Customize the plot 
plt.title('Sine Function') 
plt.xlabel('x') 
plt.ylabel('Function value') 
plt.axhline(0, color='black', linewidth=0.5) # horizontal line at y=0 
plt.axvline(0, color='black', linewidth=0.5) # vertical line at x=0 
#plt.grid(True, linestyle='--', alpha=0.5) 
plt.legend() 
plt.tight_layout() 

# Show the plot 
plt.show() 

A função seno

Gráfico da função seno, uma curva repetida com um intervalo positivo e negativo.

E agora vejamos como podemos plotar a função cosseno:

#apply the cosine function to the same array, x
cosine = np.cos(x) 

plt.figure(figsize = (5,2)) 
plt.plot(x, cosine, label = 'cos(x)', color = 'blue') 
plt.title('The Cosine Function') 
plt.xlabel('x') 
plt.ylabel('Function value') 
plt.axhline(0, color='black', linewidth=0.5) # horizontal line at y=0 
plt.axvline(0, color='black', linewidth=0.5) # vertical line at x=0 
#plt.grid(True, linestyle='--', alpha=0.5) 
plt.legend() 
plt.tight_layout() 
Um gráfico da função cosseno, ilustrando sua natureza periódica e suas principais características.

As fórmulas de codificação da posição senoidal, definidas pelos autores do artigo original sobre transformadores (Vaswani et al. 2017), são mostradas da seguinte forma:

Para posições pares:

 PEpos,2i=sin(pos100002i/dmodel) 

Para posições ímpares:

 PEpos,2i+1=cos(pos100002i/dmodel) 

  •  k : a posição da palavra na frase (por exemplo, 0 para a primeira palavra, 1 para a segunda e assim por diante.)

  •  i : o índice de dimensão do vetor de embedding. mapeia para o índice da coluna. 2i indicará uma posição par, e 2i+1 indicará uma posição impar

  •  dmodel : a dimensionalidade predefinida das embeddings de tokens (por exemplo, 512)

  •  n : valor do escalonador definido pelo usuário (por exemplo, 10000)

  •  PE : função de posição para mapear a posição k na sequência de entrada para obter o mapeamento posicional

     

 

Usando essa fórmula, cada palavra, na posição k, terá um valor de embedding baseado na posição da palavra. No exemplo que usamos, "Allen leva o cachorro para passear", podemos calcular a embedding para cada palavra:

-  k1 = "Allen"

-  k2 = "caminhar"

-  k3 ="cão"

Vamos escrever uma função simples em Python para calcular o valor de  PE(k) :

import numpy as np 

import matplotlib.pyplot as plt 

  

# create the positional encoding function using the formula above 

def getPositionEncoding(seq_len, d, n=10000): 

    # instantiate an array of 0s as a starting point 

    P = np.zeros((seq_len, d)) 

    # iterate through the positions of each word  

    for k in range(seq_len): 

        #calculate the positional encoding for even and odd position of each word 

        for i in np.arange(int(d/2)): 

            denominator = np.power(n, 2*i/d) 

            P[k, 2*i] = np.sin(k/denominator) 

            P[k, 2*i+1] = np.cos(k/denominator) 
    return P 

Depois de chamarmos a função e inserirmos o valor correspondente em nosso exemplo, onde o comprimento da sequência é 3, com uma dimensão simplificada de  d=4  e  n=10000 

P = getPositionEncoding(seq_len=3, d=4, n=10000) 

print(P) 

Obtemos a seguinte matriz de codificação (também chamada de tensor):

[[ 0.                      1.                      0.                       1.        ]

 [ 0,84147098  0,54030231  0,09983342  0,99500417]

 [ 0,90929743 -0,41614684  0,19866933  0,98006658]]

Para representar esse resultado de forma mais concreta, temos

Posição da palavraDim 0
sin(pos ÷ 10000^(0 ÷ 4))
Dim 1
cos(pos ÷ 10000^(0 ÷ 4))
Dim 2
sin(pos ÷ 10000^(2 ÷ 4))
Dim 3
cos(pos ÷ 10000^(2 ÷ 4))
“Allen” k = 00,00000,00000,00001,0000
"caminhar" k = 10,8414710,5403020,0100000,999950
"cão" k = 20,909297-0,4161470,0200000,999800

Aqui podemos ver o valor concreto de cada palavra e o valor de sua embedding correspondente. No entanto, não podemos usar essas embeddings de palavras diretamente para interpretar a ordem das palavras. O valor calculado aqui é usado para injetar informações sobre a posição em um vetor de entrada do transformador. Como a entrada de sin(x)  e  cos(x) são diferentes, cada posição  k  responderá a uma função senoidal diferente. A posição correspondente da diferente função senoidal nos dá informações sobre a posição absoluta e a posição relativa da palavra em "Allen leva o cão para caminhar". Em outras palavras, essas informações podem ser usadas pelo modelo de tal forma que o modelo pode aprender a associar esses padrões à ordem, ao espaçamento e à estrutura.  

Agora vamos implementar uma função em Python para visualizar a matriz posicional

import numpy as np 

import matplotlib.pyplot as plt 

  

def get_position_encoding(seq_len, d_model, n=10000): 

    P = np.zeros((seq_len, d_model)) 

    for pos in range(seq_len): 

        for i in range(d_model): 

            angle = pos / np.power(n, (2 * (i // 2)) / d_model) 

            P[pos, i] = np.sin(angle) if i % 2 == 0 else np.cos(angle) 

    return P 

  

# Parameters 

seq_len = 100   # Number of tokens 

d_model = 512   # Embedding dimensions 

  

# Generate positional encoding 

P = get_position_encoding(seq_len, d_model) 

  

# Plot 

plt.figure(figsize=(10, 6)) 

cax = plt.matshow(P, cmap='viridis', aspect='auto') 

plt.title("Sinusoidal Positional Encoding Heatmap") 

plt.xlabel("Embedding Dimension") 

plt.ylabel("Token Position") 

plt.colorbar(cax) 

plt.tight_layout() 

plt.show() 
Mapa de calor senoidal

Considerações finais

Como podemos ver com as diferentes frequências baseadas nos valores de x, cada posição correspondente da palavra de entrada k será diferente em uma escala de  [-1.1]  — o alcance da  sin(x)  função. A partir daí, nosso modelo de transformador baseado em codificador e decodificador aprenderá e preservará a codificação de posição diferente de cada palavra, permitindo que o modelo retenha as informações para treinamento. O vetor de posição codificado permanece estático durante o treinamento, permitindo a computação paralela.

Soluções relacionadas
IBM watsonx.ai

Treine, valide, ajuste e implemente recursos de IA generativa, modelos de base e recursos de aprendizado de máquina com o IBM watsonx.ai, um estúdio empresarial de última geração para construtores de IA. Crie aplicações de IA em uma fração do tempo com uma fração dos dados.

Conheça o watsonx.ai
Soluções de inteligência artificial

Use a IA a serviço de sua empresa com a experiência e o portfólio de soluções líder do setor da IBM à sua disposição.

Explore as soluções de IA
Consultoria e serviços em IA

Reinvente os fluxos de trabalho e operações críticos adicionando IA para maximizar experiências, tomadas de decisão em tempo real e valor de negócios.

Explore os serviços de IA
Dê o próximo passo

Obtenha acesso completo aos recursos que abrangem o ciclo de vida do desenvolvimento da IA. Produza soluções poderosas de IA com interfaces fáceis de usar, fluxos de trabalhos e acesso a APIs e SDKs padrão do setor.

Explore o watsonx.ai Agende uma demonstração em tempo real
Notas de rodapé

1. “Attention Is All You Need”, Ashish Vaswani et al., Proceedings of the 31st International Conference on Neural Information Processing Systems, arXiv:1706.03762v7, revisado em 2 de agosto de 2023.

2. “Long Short-Term Memories”, Sepp Hochreiter and Jürgen Schmidhuber. 1997. Long Short-Term Memory. Neural Comput. 9, 8 (15 de novembro de 1997), 1735–1780., 

3. “Foundations of Recurrent Neural Networks (RNNs) and Long Short-Term Memories” Alex Sherstinsky et al., Elsevier “Physica D: Nonlinear Phenomena” journal, Volume 404, março de 2020: Special Issue on Machine Learning and Dynamical Systems