¿Qué es la codificación posicional?

¿Qué es la codificación posicional?

La codificación posicional es una técnica que inyecta información sobre la posición de las palabras en una secuencia para arquitecturas del transformador.

El orden de las palabras juega un papel fundamental en la comprensión del significado semántico de una oración. Por ejemplo, "Allen walks dog" y "dog walks Allen" tienen significados completamente diferentes a pesar de tener las mismas palabras o tokens. Al implementar aplicaciones de procesamiento del lenguaje natural (PLN) mediante deep learning y redes neuronales, necesitamos crear un mecanismo por el que las máquinas puedan retener el orden de las palabras en una frase para producir resultados lógicos.  

Tradicionalmente, modelos como las redes neuronales recurrentes (RNN) o las memorias largas a corto plazo (LSTM) tienen un mecanismo incorporado que gestiona el orden de las palabras. Las RNN y las LSTM procesan las entradas de manera secuencial, un token a la vez, memorizando todas las posiciones de las palabras en una secuencia. En otras palabras, el vector de n dimensiones, también llamado "vector de entrada", se procesa uno tras otro, aprendiendo órdenes de forma inherente. Por el contrario, otras arquitecturas que se benefician de las redes neuronales convolucionales (CNN) o los transformadores (Vaswani et al. 2017) no conservan el orden de las palabras y procesan los tokens en paralelo. Por lo tanto, necesitamos implementar un mecanismo que pueda representar explícitamente el orden de las palabras en una secuencia, una técnica conocida como codificación posicional. La codificación posicional permite al transformador retener información del orden de las palabras, lo que permite la paralelización y el entrenamiento eficiente del modelo. A menudo puede encontrar implementaciones de codificación posicional en GitHub.  

Las últimas tendencias en IA, presentadas por expertos

Obtenga conocimientos organizados sobre las noticias más importantes e intrigantes de la IA. Suscríbase a nuestro boletín semanal Think. Consulte la Declaración de privacidad de IBM.

¡Gracias! Está suscrito.

Su suscripción se enviará en inglés. Encontrará un enlace para darse de baja en cada boletín. Puede gestionar sus suscripciones o darse de baja aquí. Consulte nuestra Declaración de privacidad de IBM para obtener más información.

¿Por qué es importante la codificación posicional?

El orden de las palabras en una oración o secuencia dicta el significado inherente de la oración en lenguajes naturales. Además, para el machine learning, la codificación del orden de las palabras nos proporciona un "diccionario" sobre dónde debe ir cada palabra. Esta información se conserva y puede generalizarse a lo largo del entrenamiento de los modelos de transformador, lo que permite la paralelización y supera a las RNN y las LSTM por su eficiencia de entrenamiento.  

Repasemos el ejemplo:

  • "Allen walks dog"
  • "dog walks Allen"

Estas dos oraciones con los mismos tres tokens tienen significados completamente diferentes según el orden de las palabras. Los transformadores, que se basan en la autoatención y el mecanismo de atención multicabezal, no tienen una representación inherente del orden de las palabras y tratarían la palabra individual en una secuencia de forma idéntica si no proporcionamos información posicional explícita. Queremos que el modelo comprenda quién está dando el paseo y quién está siendo paseado, lo que depende totalmente de las posiciones.  

Logramos este objetivo procesando primero cada palabra como un vector que representa su significado; por ejemplo, "dog" se codificará en una matriz de alta dimensión que codifica su concepto. En términos técnicos, cada palabra o subpalabra se asigna a un embedding de entrada de longitud variable. Sin embargo, por sí solo, el vector de significado no nos dice en qué parte de la oración aparece el perro. La codificación posicional añade un segundo vector, uno que codifica el índice de posición, como "primera palabra" o "segunda palabra", y así sucesivamente. A continuación, los dos vectores se suman para representar qué es la palabra y dónde está. Este vector resultante suele denominarse vector de codificación posicional.   

Hay varias formas de crear codificación posicional. En este artículo, exploramos el ejemplo más conocido del uso de una función sinusoidal introducida por los autores en Attention is all you need1 para crear codificación posicional.  

Mixture of Experts | 12 de diciembre, episodio 85

Descifrar la IA: resumen semanal de noticias

Únase a nuestro panel de ingenieros, investigadores, responsables de producto y otros profesionales de talla mundial que se abren paso entre el bullicio de la IA para ofrecerle las últimas noticias y conocimientos al respecto.

Codificación posicional en transformadores

En el artículo original presentado por Vaswani et al. 2017, la idea clave es generar una codificación fija y determinista para cada posición en una secuencia mediante el uso de una función sinusoidal (en particular, la función seno) sin(x) y la función coseno cos(x) .  

¿Qué son las funciones sinusoidales?

Las funciones sinusoidales son un concepto matemático fundamental que produce un patrón de longitud de onda suave. En particular, los autores utilizan las funciones coseno y seno en las funciones de transformador originales para ayudar a la codificación posicional.

Si trazamos sin(x) y  cos(x) , veremos una curva que sube y baja entre -1 y 1 en un patrón periódico repetitivo.

Algunas propiedades del seno que lo hacen potente para la codificación posicional: 

  • Es periódico: se repite regularmente a intervalos, lo que es útil para representar patrones repetidos.

  • Es suave y continuo: pequeños cambios en la entrada dan lugar a pequeños cambios en el resultado, lo que nos proporciona una forma de representar posiciones en un espacio diferenciable.

  • Al variar la frecuencia de las longitudes de onda a través de las dimensiones, podemos crear una representación rica y multiescala de la posición. 

Tracemos las ondas seno y coseno para visualizar su aspecto:

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() 

La función seno

Gráfico de la función seno, una curva repetitiva con un rango positivo y negativo.

Y ahora veamos cómo podemos trazar la función coseno:

#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() 
Un gráfico de la función coseno, que ilustra su naturaleza periódica y sus características clave.

Las fórmulas de codificación de posición sinusoidal, definidas por los autores del artículo original de transformadores (Vaswani et al. 2017), se muestran a continuación:

Para posiciones pares:

 PEpos,2i=sin(pos100002i/dmodel) 

Para posiciones impares:

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

  •  k : la posición de la palabra en la oración (por ejemplo, 0 para la primera palabra, 1 para la segunda, etc.)

  •  i : el índice de dimensión del vector de embedding. se asigna al índice de columna. 2i indicará una posición par y 2i+1 indicará una posición impar

  •  dmodel : la dimensionalidad predefinida de los embeddings de los tokens (por ejemplo, 512)

  •  n : valor de escalador definido por el usuario (por ejemplo, 10 000)

  •  PE : función de posición para mapear la posición k en la secuencia de entrada para obtener el mapeo posicional

     

 

Con esta fórmula, cada palabra, en la posición k, tendrá un valor de embedding basado en la posición de la palabra. Tomemos el ejemplo que usamos, "Allen walks dog"; podemos calcular el embedding posicional de cada palabra:

-  k1 = "Allen"

-  k2 = "walks"

-  k3 ="dog"

Escribamos una función Python sencilla para calcular el 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 

Una vez llamada la función e introducido el valor correspondiente en nuestro ejemplo, donde la longitud de la secuencia es 3, con una dimensión simplificada de  d=4  y  n=10000 

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

print(P) 

Obtenemos la siguiente matriz de codificación (también conocida como tensor):

[[ 0.                      1.                      0.                       1.        ]

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

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

Para representar este resultado de manera más concreta, obtenemos

Posición de la palabraDim 0
sen(pos ÷ 10000^(0 ÷ 4))
Dim 1
cos(pos ÷ 10000^(0 ÷ 4))
Dim 2
sen(pos ÷ 10000^(2 ÷ 4))
Dim 3
cos(pos ÷ 10000^(2 ÷ 4))
“Allen” k = 00,00000,00000,00001,0000
"walks" k = 10,8414710,5403020,0100000,999950
"dog" k = 20,909297-0,4161470,0200000,999800

Aquí podemos ver el valor concreto de cada palabra y su correspondiente valor de embedding posicional. Sin embargo, no podemos utilizar estos embeddings de palabras directamente para interpretar el orden de las mismas. El valor calculado aquí se utiliza para inyectar información sobre la posición en un vector de entrada del transformador. Como las entradas de sin(x)  y  cos(x) son diferentes, cada posición  k  responderá a una función sinusoidal diferente. La posición correspondiente de las diferentes funciones sinusoidales nos da información sobre la posición absoluta y la posición relativa de la palabra en "Allen walks dog". En otras palabras, esta información puede ser utilizada por el modelo de tal forma que este aprenda a asociar estos patrones con el orden, el espaciado y la estructura.  

Ahora implementemos una función de Python para visualizar la 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 sinusoidal

Reflexiones finales

Como podemos ver con las diferentes frecuencias basadas en valores de x, cada posición correspondiente de la palabra de entrada k diferirá en una escala de  [-1.1] —el rango de la función  sin(x) . A partir de ahí, nuestro modelo de transformador basado en codificador y decodificador aprenderá y conservará las diferentes posiciones de codificación de cada palabra, lo que permitirá que el modelo conserve la información para el entrenamiento. El vector de posición codificado permanece estático durante el entrenamiento, lo que permite el cálculo paralelo.

Soluciones relacionadas
IBM watsonx.ai

Entrene, valide, ajuste e implemente IA generativa, modelos fundacionales y capacidades de machine learning con IBM watsonx.ai, un estudio empresarial de nueva generación para desarrolladores de IA. Cree aplicaciones de IA en menos tiempo y con menos datos.

Descubra watsonx.ai
Soluciones de inteligencia artificial

Ponga la IA a trabajar en su negocio con la experiencia líder en IA del sector de IBM y junto a su cartera de soluciones.

Explore las soluciones de IA
Consultoría y servicios de IA

Reinvente las operaciones y flujos de trabajo críticos añadiendo IA para maximizar las experiencias, la toma de decisiones en tiempo real y el valor empresarial.

Explore los servicios de IA
Dé el siguiente paso

Obtenga acceso único a capacidades que abarcan el ciclo de vida de desarrollo de la IA. Produzca potentes soluciones de IA con interfaces intuitivas, flujos de trabajo y acceso a API y SDK estándar del sector.

Explore watsonx.ai Solicite una demostración en directo
Notas a pie de página

1. “Attention Is All You Need”, Ashish Vaswani et al. Actas de la 31ª International Conference on Neural Information Processing Systems. arXiv:1706.03762v7. Revisado el 2 de agosto de 2023.

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

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