Última actualización el 25 de septiembre de 2022
En la parte 1: Una breve introducción a la codificación posicional en modelos de transformadores, discutimos la capa de codificación posicional del modelo de transformadores. También mostramos cómo puede implementar esta capa y sus funciones usted mismo en Python. En este tutorial, implementaremos la capa de codificación posicional en Keras y Tensorflow. A continuación, puede utilizar esta capa en un modelo de transformador completo.
Después de completar este tutorial, sabrás:
- Vectorización de texto en Keras
- Capa de incrustación en Keras
- Cómo subclasificar la capa de incrustación y escribir su propia capa de codificación posicional.
Empecemos.

La capa de codificación posicional del transformador en Keras, parte 2.
Foto de Ijaz Rafi. algunos derechos reservados
Descripción general del tutorial
Este tutorial se divide en 3 partes; están:
- Vectorización de texto y capa de incrustación en Keras
- Escribiendo tu propia capa de codificación posicional en Keras
- Embebidos aleatoriamente inicializados y sintonizables
- Embebidos de peso fijo desde La atención es todo lo que necesitas
- Vista gráfica de la salida de la capa de codificación posicional
Primero, escribamos la sección para importar todas las bibliotecas requeridas:
importar tensorflow como tf de tensorflow importar convert_to_tensor, cadena de tensorflow.keras.layers importar TextVectorization, Embedding, Layer de tensorflow.data importar Dataset importar numpy como np importar matplotlib.pyplot como plt
importar tensorflow como t.f. de tensorflow importar convertir_a_tensor, cuerda de tensorflow.queras.capas importar TextoVectorización, incrustación, Capa de tensorflow.datos importar conjunto de datos importar entumecido como notario público importar matplotlib.pyplot como por favor |
Comenzaremos con un conjunto de frases en inglés, que ya están preprocesadas y limpiadas. La capa de vectorización de texto crea un diccionario de palabras y reemplaza cada palabra por su índice correspondiente en el diccionario. Veamos cómo podemos mapear estas dos oraciones usando la capa de vectorización de texto:
- Soy un robot
- tú también robot
Tenga en cuenta que ya convertimos el texto a minúsculas y eliminamos todos los signos de puntuación y el ruido en el texto. Convertiremos estas dos frases en vectores de una longitud fija 5. El TextVectorization
capa de Keras requiere un tamaño de vocabulario máximo y la longitud necesaria de la secuencia de salida para la inicialización. La salida de la capa es un tensor de forma:
(number of sentences, output sequence length)
El siguiente fragmento de código utiliza el adapt
método para generar un vocabulario. A continuación, crea una representación vectorizada de texto.
output_sequence_length = 5 vocab_size = 10 oraciones = [[«I am a robot»], [«you too robot»]]sentencia_datos = Conjunto de datos.from_tensor_slices(frases) # Crear la capa TextVectorization vectorize_layer = TextVectorization( output_sequence_length=output_sequence_length, max_tokens=vocab_size) # Entrenar la capa para crear un diccionario vectorize_layer.adapt(sentence_data) # Convertir todas las oraciones en tensores word_tensors = convert_to_tensor( oraciones, dtype=tf.string) # Usa los tensores de palabras para obtener frases vectorizadas vectorized_words = vectorize_layer(word_tensors) print(«Vocabulary: «, vectorize_layer.get_vocabulary()) print(«Vocabulary word: «, vectorized_words)
longitud_secuencia_salida = 5 tamaño_vocabulario = 10 oraciones = [[«I am a robot»], [«you too robot»]] datos_oracion = conjunto de datos.from_tensor_slices(oraciones) # Crear la capa TextVectorization vectorizar_capa = TextoVectorización( longitud_secuencia_salida=longitud_secuencia_salida, max_tokens=tamaño_vocabulario) # Entrenar la capa para crear un diccionario vectorizar_capa.adaptar(datos_oracion) # Convertir todas las oraciones a tensores tensores_de_palabras = convertir_a_tensor(oraciones, tipo de d=t.f..cuerda) # Use los tensores de palabras para obtener frases vectorizadas palabras_vectorizadas = vectorizar_capa(tensores_de_palabras) impresión(«Vocabulario: «, vectorizar_capa.obtener_vocabulario()) impresión(«Palabras vectorizadas: «, palabras_vectorizadas) |
Vocabulario: [», ‘[UNK]’, ‘robot’, ‘tú’, ‘también’, ‘yo’, ‘soy’, ‘a’]Palabras vectorizadas: tf.Tensor(
[[5 6 7 2 0]
[3 4 2 0 0]], forma=(2, 5), dtipo=int64)
Vocabulario: [», ‘[UNK]’, ‘robot’, ‘tú’, ‘también’, ‘yo’, ‘soy’, ‘a’] Palabras vectorizadas: tf.Tensor( [[5 6 7 2 0] [3 4 2 0 0]], forma=(2, 5), dtipo=int64) |
Las Keras Embedding
capa convierte números enteros en vectores densos. Esta capa asigna estos enteros a números aleatorios, que luego se ajustan durante la fase de entrenamiento. Sin embargo, también tiene la opción de establecer el mapeo en algunos valores de peso predefinidos (que se muestran más adelante). Para inicializar esta capa, necesitamos especificar el valor máximo de un número entero para mapear, junto con la longitud de la secuencia de salida.
Las incrustaciones de palabras
Veamos cómo la capa convierte nuestra vectorized_text
a los tensores.
longitud_salida = 6 capa_incrustación_palabra = Incrustación(tamaño_vocablo, longitud_salida) palabras_incrustadas = capa_incrustación_palabra(palabras_vectorizadas) imprimir(palabras_incrustadas)
longitud_de_salida = 6 palabra_incrustación_capa = incrustación(tamaño_vocabulario, longitud_de_salida) palabras_incrustadas = palabra_incrustación_capa(palabras_vectorizadas) impresión(palabras_incrustadas) |
He anotado el resultado con mis comentarios como se muestra a continuación. Tenga en cuenta que verá un resultado diferente cada vez que ejecute este código porque los pesos se inicializaron aleatoriamente.

Incrustaciones de palabras. Esta salida será diferente cada vez que ejecute el código debido a los números aleatorios involucrados.
También necesitamos las incrustaciones para las posiciones correspondientes. Las posiciones máximas corresponden a la longitud de la secuencia de salida del TextVectorization
capa.
position_embedding_layer = Embedding(output_sequence_length, output_length) position_indices = tf.range(output_sequence_length) incrustados_índices = position_embedding_layer(position_indices) print(incrustados_índices)
position_embedding_layer = incrustación(longitud_secuencia_salida, longitud_de_salida) índices_de_posición = t.f..rango(longitud_secuencia_salida) incrustados_índices = position_embedding_layer(índices_de_posición) impresión(incrustados_índices) |
La salida se muestra a continuación:

Incrustación de índices de posición.
En un modelo de transformador, la salida final es la suma de las incrustaciones de palabras y las incrustaciones de posición. Por lo tanto, cuando configura ambas capas incrustadas, debe asegurarse de que el output_length
es el mismo para ambos.
incrustación_salida_final = palabras_incrustadas + índices_incrustados print(«Salida final: «, incrustación_salida_final)
final_output_embedding = palabras_incrustadas + incrustados_índices impresión(«Salida final:», final_output_embedding) |
El resultado se muestra a continuación, anotado con mis comentarios. Nuevamente, esto será diferente de su ejecución del código debido al peso aleatorio inicialización

El resultado final después de agregar la incrustación de palabras y la incrustación de posición
Al implementar un modelo de transformador, deberá escribir su propia capa de codificación de posición. Esto es bastante simple ya que la funcionalidad básica ya se proporciona para usted. Este Ejemplo de Keras muestra cómo puede subclasificar el Embedding
capa para implementar su propia funcionalidad. Puede agregarle más métodos según lo requiera.
class PositionEmbeddingLayer(Capa): def __init__(self, secuencia_longitud, vocab_size, output_dim, **kwargs): super(PositionEmbeddingLayer, self).__init__(**kwargs) self.word_embedding_layer = Embedding( input_dim=vocab_size, output_dim=output_dim ) self .position_embedding_layer = Embedding( input_dim=secuencia_longitud, output_dim=output_dim ) def call(self, entradas): position_indices = tf.range(tf.shape(entradas)[-1]) palabras_incrustadas = self.word_embedding_layer(entradas) incrustados_índices = self.position_embedding_layer(position_indices) return palabras_incrustadas + índices_incrustados
clase PosiciónEmbeddingLayer(Capa): definitivamente __en eso__(uno mismo, secuencia_longitud, tamaño_vocabulario, salida_dim, **kwargs): súper(PosiciónEmbeddingLayer, uno mismo).__en eso__(**kwargs) uno mismo.palabra_incrustación_capa = incrustación( entrada_dim=tamaño_vocabulario, salida_dim=producción_oscuro ) uno mismo.position_embedding_layer = incrustación( entrada_dim=secuencia_longitud, salida_dim=producción_oscuro ) definitivamente llamar(uno mismo, entradas): índices_de_posición = t.f..rango(t.f..forma(entradas)[–1]) palabras_incrustadas = uno mismo.palabra_incrustación_capa(entradas) incrustados_índices = uno mismo.position_embedding_layer(índices_de_posición) devolver palabras_incrustadas + incrustados_índices |
Ejecutemos esta capa.
my_embedding_layer = PositionEmbeddingLayer(output_sequence_length, vocab_size, output_length) Embedded_layer_output = my_embedding_layer(vectorized_words) print(«Salida de my_embedding_layer: «, Embedded_layer_output)
mi_capa_incrustada = PosiciónEmbeddingLayer(longitud_secuencia_salida, tamaño_vocabulario, longitud_de_salida) salida_de_capa_incrustada = mi_capa_incrustada(palabras_vectorizadas) impresión(«Salida de my_embedded_layer:», salida_de_capa_incrustada) |
Salida de my_embedded_layer: tf.Tensor(
[[[ 0.06798736 -0.02821309 0.00571618 0.00314623 -0.03060734
0.01111387]
[-0.06097465 0.03966043 -0.05164248 0.06578685 0.03638128
-0.03397174]
[ 0.06715029 -0.02453769 0.02205854 0.01110986 0.02345785
0.05879898]
[-0.04625867 0.07500569 -0.05690887 -0.07615659 0.01962536
0.00035865]
[ 0.01423577 -0.03938593 -0.08625181 0.04841495 0.06951572
0.08811047]]
[[ 0.0163899 0.06895607 -0.01131684 0.01810524 -0.05857501
0.01811318]
[ 0.01915303 -0.0163289 -0.04133433 0.06810946 0.03736673
0.04218033]
[ 0.00795418 -0.00143972 -0.01627307 -0.00300788 -0.02759011
0.09251165]
[ 0.0028762 0.04526488 -0.05222676 -0.02007698 0.07879823
0.00541583]
[ 0.01423577 -0.03938593 -0.08625181 0.04841495 0.06951572
0.08811047]]], forma=(2, 5, 6), dtype=float32)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 dieciséis 17 18 19 20 21 22 |
Salida de my_embedded_layer: tf.Tensor( [[[ 0.06798736 -0.02821309 0.00571618 0.00314623 -0.03060734 0.01111387] [-0.06097465 0.03966043 -0.05164248 0.06578685 0.03638128 -0.03397174] [ 0.06715029 -0.02453769 0.02205854 0.01110986 0.02345785 0.05879898] [-0.04625867 0.07500569 -0.05690887 -0.07615659 0.01962536 0.00035865] [ 0.01423577 -0.03938593 -0.08625181 0.04841495 0.06951572 0.08811047]] [[ 0.0163899 0.06895607 -0.01131684 0.01810524 -0.05857501 0.01811318] [ 0.01915303 -0.0163289 -0.04133433 0.06810946 0.03736673 0.04218033] [ 0.00795418 -0.00143972 -0.01627307 -0.00300788 -0.02759011 0.09251165] [ 0.0028762 0.04526488 -0.05222676 -0.02007698 0.07879823 0.00541583] [ 0.01423577 -0.03938593 -0.08625181 0.04841495 0.06951572 0.08811047]]], forma=(2, 5, 6), dtype=float32) |
Codificación posicional en transformadores: todo lo que necesita es atención
Tenga en cuenta que la clase anterior crea una capa de incrustación que tiene pesos entrenables. Por lo tanto, los pesos se inicializan aleatoriamente y se ajustan en la fase de entrenamiento.
begin
P(k, 2i) &=& sinGrande(fracGrande)\
P(k, 2i+1) &=& cosGrande(fracGrande)
end
Embedding
capa, debe proporcionar la matriz de codificación posicional como pesos junto con trainable=False
. Vamos a crear otra clase de incrustación posicional que haga exactamente esto.class PositionEmbeddingFixedWeights(Layer): def __init__(self, secuencia_longitud, vocab_size, output_dim, **kwargs): super(PositionEmbeddingFixedWeights, self).__init__(**kwargs) word_embedding_matrix = self.get_position_encoding(vocab_size, output_dim) position_embedding_matrix = self.get_position_encoding (longitud_secuencia, dim_salida) self.palabra_embedding_capa = Incrustación(dim_entrada=tamaño_vocablo, dim_salida=dim_salida, pesos=[word_embedding_matrix]entrenable=Falso) self.position_embedding_layer = Incrustación (input_dim=longitud_secuencia, output_dim=output_dim, pesos=[position_embedding_matrix]trainable=False ) def get_position_encoding(self, seq_len, d, n=10000): P = np.zeros((seq_len, d)) for k in range(seq_len): for i in np.arange(int(d/ 2)): denominador = np.potencia(n, 2*i/d) P[k, 2*i] = np.sen(k/denominador) P[k, 2*i+1] = np.cos(k/denominador) return P def call(self, entradas): position_indices = tf.range(tf.shape(entradas)[-1]) palabras_incrustadas = self.word_embedding_layer(entradas) incrustados_índices = self.position_embedding_layer(position_indices) return palabras_incrustadas + índices_incrustados
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 dieciséis 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
clase PosiciónIncrustaciónPesos fijos(Capa): definitivamente __en eso__(uno mismo, secuencia_longitud, tamaño_vocabulario, salida_dim, **kwargs): súper(PosiciónIncrustaciónPesos fijos, uno mismo).__en eso__(**kwargs) word_embedding_matrix = uno mismo.get_position_encoding(tamaño_vocabulario, salida_dim) position_embedding_matrix = uno mismo.get_position_encoding(secuencia_longitud, salida_dim) uno mismo.palabra_incrustación_capa = incrustación( entrada_dim=tamaño_vocabulario, salida_dim=salida_dim, pesos=[word_embedding_matrix], entrenable=Falso ) uno mismo.position_embedding_layer = incrustación( entrada_dim=secuencia_longitud, salida_dim=salida_dim, pesos=[position_embedding_matrix], entrenable=Falso )
definitivamente get_position_encoding(uno mismo, seq_len, d, norte=10000): PAGS = notario público.ceros((seq_len, d)) por k en rango(seq_len): por i en notario público.naranja(En t(d/2)): denominador = notario público.energía(norte, 2*i/d) PAGS[k, 2*i] = notario público.pecado(k/denominador) PAGS[k, 2*i+1] = notario público.porque(k/denominador) devolver PAGS definitivamente llamar(uno mismo, entradas): índices_de_posición = t.f..rango(t.f..forma(entradas)[–1]) palabras_incrustadas = uno mismo.palabra_incrustación_capa(entradas) incrustados_índices = uno mismo.position_embedding_layer(índices_de_posición) devolver palabras_incrustadas + incrustados_índices |
A continuación, configuramos todo para ejecutar esta capa.
attnisallyouneed_embedding = PositionEmbeddingFixedWeights(output_sequence_length, vocab_size, output_length) attnisallyouneed_output = attnisallyouneed_embedding(vectorized_words) print(«Salida de mi_capa_incrustada: «, attnisallyouneed_output)
attnisallyouneed_embedding = PosiciónIncrustaciónPesos fijos(longitud_secuencia_salida, tamaño_vocabulario, longitud_de_salida) attnisallyyouneed_output = attnisallyouneed_embedding(palabras_vectorizadas) impresión(«Salida de my_embedded_layer:», attnisallyyouneed_output) |
Salida de my_embedded_layer: tf.Tensor(
[[[-0.9589243 1.2836622 0.23000172 1.9731903 0.01077196
1.9999421 ]
[ 0.56205547 1.5004725 0.3213085 1.9603932 0.01508068
1.9999142 ]
[ 1.566284 0.3377554 0.41192317 1.9433732 0.01938933
1.999877 ]
[ 1.0504174 -1.4061394 0.2314966 1.9860148 0.01077211
1.9999698 ]
[-0.7568025 0.3463564 0.18459873 1.982814 0.00861763
1.9999628 ]]
[[ 0.14112 0.0100075 0.1387981 1.9903207 0.00646326
1.9999791 ]
[ 0.08466846 -0.11334133 0.23099795 1.9817369 0.01077207
1.9999605 ]
[ 1.8185948 -0.8322937 0.185397 1.9913884 0.00861771
1.9999814 ]
[ 0.14112 0.0100075 0.1387981 1.9903207 0.00646326
1.9999791 ]
[-0.7568025 0.3463564 0.18459873 1.982814 0.00861763
1.9999628 ]]], forma=(2, 5, 6), dtype=float32)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 dieciséis 17 18 19 20 21 22 |
Salida de my_embedded_layer: tf.Tensor( [[[-0.9589243 1.2836622 0.23000172 1.9731903 0.01077196 1.9999421 ] [ 0.56205547 1.5004725 0.3213085 1.9603932 0.01508068 1.9999142 ] [ 1.566284 0.3377554 0.41192317 1.9433732 0.01938933 1.999877 ] [ 1.0504174 -1.4061394 0.2314966 1.9860148 0.01077211 1.9999698 ] [-0.7568025 0.3463564 0.18459873 1.982814 0.00861763 1.9999628 ]] [[ 0.14112 0.0100075 0.1387981 1.9903207 0.00646326 1.9999791 ] [ 0.08466846 -0.11334133 0.23099795 1.9817369 0.01077207 1.9999605 ] [ 1.8185948 -0.8322937 0.185397 1.9913884 0.00861771 1.9999814 ] [ 0.14112 0.0100075 0.1387981 1.9903207 0.00646326 1.9999791 ] [-0.7568025 0.3463564 0.18459873 1.982814 0.00861763 1.9999628 ]]], forma=(2, 5, 6), dtype=float32) |
Para visualizar las incrustaciones, tomemos dos oraciones más grandes, una técnica y la otra solo una cita. Configuraremos el TextVectorization
capa junto con la capa de codificación posicional y vea cómo se ve el resultado final.
Technical_phrase = «para comprender los algoritmos de aprendizaje automático, necesita» + » comprender conceptos como el gradiente de una función «+ «Hessians de una matriz y optimización, etc.» wise_phrase = «patrick henry dijo dame libertad o dame la muerte «+ «cuando se dirigió a la segunda convención de virginia en marzo» vocabulario_total = 200 longitud_secuencia = 20 longitud_salida_final = 50 capa_vectorización_frase = TextVectorization(longitud_secuencia_salida=longitud_secuencia, max_tokens=vocabulario_total) # Aprende el diccionario capa_vectorización_frase.adapt([technical_phrase, wise_phrase]) # Convertir todas las oraciones a tensores tensores_de_frase = convertir_a_tensor([technical_phrase, wise_phrase]dtype=tf.string) # Use the word tensors to get vectorized phrases vectorized_phrases = phrase_vectorization_layer(phrase_tensors) random_weights_embedding_layer = PositionEmbeddingLayer(sequence_length, total_vocabulary, final_output_len) fixed_weights_embedding_layer = PositionEmbeddingFixedWeights(sequence_length, total_vocabulary, final_output_len) random_embedding = random_weights_embedding_layer(vectorized_phrases) fixed_embedding = fixed_weights_embedding_layer(vectorized_phrases)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 dieciséis 17 18 19 20 21 22 23 24 25 26 27 28 |
frase_técnica = «para comprender los algoritmos de aprendizaje automático que necesita» + » comprender conceptos como el gradiente de una función «+ «Hessians de una matriz y optimización, etc» frase_sabia = «patrick henry dijo dame libertad o dame la muerte»+ «cuando se dirigió a la segunda convención de Virginia en marcha» vocabulario_total = 200 secuencia_longitud = 20 longitud_de_salida_final = 50 frase_vectorización_capa = TextoVectorización( longitud_secuencia_salida=secuencia_longitud, max_tokens=vocabulario_total) # Aprende el diccionario frase_vectorización_capa.adaptar([technical_phrase, wise_phrase]) # Convertir todas las oraciones a tensores tensores_de_frase = convertir_a_tensor([technical_phrase, wise_phrase], tipo de d=t.f..cuerda) # Use los tensores de palabras para obtener frases vectorizadas frases_vectorizadas = frase_vectorización_capa(tensores_de_frase) capa_incrustación_pesos_aleatorios = PosiciónEmbeddingLayer(secuencia_longitud, vocabulario_total, longitud_de_salida_final) capa_de_incrustación_de_pesos_fijos = PosiciónIncrustaciónPesos fijos(secuencia_longitud, vocabulario_total, longitud_de_salida_final) incrustación_aleatoria = capa_incrustación_pesos_aleatorios(frases_vectorizadas) incrustación_fija = capa_de_incrustación_de_pesos_fijos(frases_vectorizadas) |
Ahora veamos cómo se ven las incrustaciones aleatorias para ambas frases.
fig = plt.figure(figsize=(15, 5)) title = [«Tech Phrase», «Wise Phrase»]for i in range(2): ax = plt.subplot(1, 2, 1+i) matrix = tf.reshape(random_embedding[i, :, :](longitud_secuencia, longitud_salida_final)) cax = ax.matshow(matriz) plt.gcf().colorbar(cax) plt.title(título[i]y=1.2) fig.suptitle(«Incrustación aleatoria») plt.show()
higo = por favor.figura(tamaño de higo=(15, 5)) título = [«Tech Phrase», «Wise Phrase»] por i en rango(2): hacha = por favor.subtrama(1, 2, 1+i) matriz = t.f..remodelar(incrustación_aleatoria[i, :, :], (secuencia_longitud, longitud_de_salida_final)) cax = hacha.matshow(matriz) por favor.mcd().barra de color(cax) por favor.título(título[i], y=1.2) higo.subtítulo(«Incrustación aleatoria») por favor.mostrar() |

Incrustaciones aleatorias
La incrustación de la capa de pesos fijos se visualiza a continuación.
fig = plt.figure(figsize=(15, 5)) title = [«Tech Phrase», «Wise Phrase»]for i in range(2): ax = plt.subplot(1, 2, 1+i) matrix = tf.reshape(fixed_embedding[i, :, :](longitud_secuencia, longitud_salida_final)) cax = ax.matshow(matriz) plt.gcf().colorbar(cax) plt.title(título[i]y=1.2) fig.suptitle(«La incrustación de peso fijo desde Atención es todo lo que necesita») plt.show()
higo = por favor.figura(tamaño de higo=(15, 5)) título = [«Tech Phrase», «Wise Phrase»] por i en rango(2): hacha = por favor.subtrama(1, 2, 1+i) matriz = t.f..remodelar(incrustación_fija[i, :, :], (secuencia_longitud, longitud_de_salida_final)) cax = hacha.matshow(matriz) por favor.mcd().barra de color(cax) por favor.título(título[i], y=1.2) higo.subtítulo(«La incrustación de peso fijo desde Atención es todo lo que necesita») por favor.mostrar() |

Incrustación mediante codificación posicional sinusoidal
Podemos ver que la capa de incrustación inicializada usando el parámetro predeterminado genera valores aleatorios. Por otro lado, los pesos fijos generados usando sinusoides crean una firma única para cada frase con información sobre cada posición de palabra codificada dentro de ella.
Puede experimentar con implementaciones ajustables o de peso fijo para su aplicación en particular.
Esta sección proporciona más recursos sobre el tema si desea profundizar más.
Libros
Documentos
Artículos
Resumen
En este tutorial, descubrió la implementación de la capa de codificación posicional en Keras.
Específicamente, aprendiste:
- Capa de vectorización de texto en Keras
- Capa de codificación posicional en Keras
- Crear tu propia clase para la codificación posicional
- Configuración de sus propios pesos para la capa de codificación posicional en Keras
¿Tiene alguna pregunta sobre la codificación posicional discutida en esta publicación? Haga sus preguntas en los comentarios a continuación y haré todo lo posible para responder.