Dentro de GPT – I Comprendiendo la generación de texto.

Dentro de GPT-I Comprendiendo la generación de texto.

Una explicación simple sobre el modelo detrás de ChatGPT

young Dostoyevski is introduced to generative AI, created through Midjourney

Al interactuar regularmente con colegas de diversos campos, disfruto del desafío de transmitir conceptos de aprendizaje automático a personas que tienen poco o ningún conocimiento en ciencia de datos. Aquí, intento explicar cómo está conectado GPT en términos simples, pero esta vez por escrito.

Detrás de la popular magia de ChatGPT, hay una lógica impopular. Escribes una instrucción en ChatGPT y este genera texto que, si es preciso, se asemeja a respuestas humanas. ¿Cómo es capaz de entender tu instrucción y generar respuestas coherentes y comprensibles?

Redes Neuronales Transformadoras. La arquitectura diseñada para procesar datos no estructurados en grandes cantidades, en nuestro caso, texto. Cuando hablamos de arquitectura, nos referimos esencialmente a una serie de operaciones matemáticas realizadas en varias capas en paralelo. A través de este sistema de ecuaciones, se introdujeron varias innovaciones que nos ayudaron a superar los desafíos existentes desde hace mucho tiempo en la generación de texto. Desafíos con los que estábamos luchando hasta hace 5 años.

Si GPT ya ha estado aquí durante 5 años (de hecho, el artículo de GPT fue publicado en 2018), ¿no es GPT algo antiguo? ¿Por qué se ha vuelto inmensamente popular recientemente? ¿Cuál es la diferencia entre GPT 1, 2, 3, 3.5 (ChatGPT) y 4?

Todas las versiones de GPT se construyeron sobre la misma arquitectura. Sin embargo, cada modelo siguiente contenía más parámetros y se entrenaba utilizando conjuntos de datos de texto más grandes. Obviamente, también se introdujeron otras novedades en las versiones posteriores de GPT, especialmente en los procesos de entrenamiento, como el aprendizaje por refuerzo a través de retroalimentación humana, que explicaremos en la tercera parte de esta serie de blogs.

Vectores, matrices, tensores. Todas estas palabras sofisticadas son unidades que contienen conjuntos de números. Esos números pasan por una serie de operaciones matemáticas (principalmente multiplicación y suma) hasta que alcanzamos los valores de salida óptimos, que son las probabilidades de los posibles resultados.

¿Valores de salida? En este sentido, ¿es el texto generado por el modelo de lenguaje, verdad? Sí. Entonces, ¿cuáles son los valores de entrada? ¿Es mi instrucción? Sí, pero no completamente. ¿Entonces qué más hay detrás?

Antes de pasar a las diferentes estrategias de decodificación de texto, que serán el tema del siguiente post del blog, es útil eliminar la ambigüedad. Volvamos a la pregunta fundamental que hicimos al principio. ¿Cómo entiende el lenguaje humano?

Transformadores Generativos Pre-entrenados. Tres palabras que representan la abreviatura de GPT. Ya hemos hablado de la parte Transformer, que representa la arquitectura donde se realizan cálculos intensos. Pero, ¿qué calculamos exactamente? ¿De dónde obtienes incluso los números? Es un modelo de lenguaje y todo lo que haces es escribir texto e ingresar algún texto, ¿cómo puedes calcular texto?

Los datos son agnósticos. Todos los datos son iguales, ya sea en forma de texto, sonido o imagen.¹

Tokens. Dividimos el texto en fragmentos pequeños (tokens) y asignamos un número único a cada uno de ellos (ID de token). Los modelos no conocen palabras, imágenes o grabaciones de audio. Aprenden a representarlos en una gran serie de números (parámetros) que nos sirve como una herramienta para ilustrar las características de las cosas en forma numérica. Los tokens son las unidades de lenguaje que transmiten significado y los ID de tokens son los números únicos que codifican los tokens.

Obviamente, cómo tokenizamos el lenguaje puede variar. La tokenización puede implicar dividir el texto en oraciones, palabras, partes de palabras (subpalabras) o incluso caracteres individuales.

Consideremos un escenario en el que tenemos 50,000 tokens en nuestro corpus de lenguaje (similar a GPT-2, que tiene 50,257). ¿Cómo representamos esas unidades después de la tokenización?

Oración: "los estudiantes celebran la graduación con una gran fiesta"Etiquetas de tokens: ['[CLS]', 'los', 'estudiantes', 'celebran', 'la', 'graduación', 'con', 'una', 'gran', 'fiesta', '[SEP]']IDs de tokens: tensor([[ 101, 2493, 8439, 1996, 7665, 2007, 1037, 2502, 2283,  102]])

Arriba se muestra una oración de ejemplo tokenizada en palabras. Los enfoques de tokenización pueden diferir en su implementación. Lo importante para nosotros entender ahora es que adquirimos representaciones numéricas de unidades de lenguaje (tokens) a través de sus correspondientes IDs de tokens. Entonces, ahora que tenemos estos IDs de tokens, ¿podemos simplemente ingresarlos directamente al modelo donde se realizan los cálculos?

La cardinalidad importa en matemáticas. 101 y 2493 como representación de tokens serán importantes para el modelo. Porque recuerda, todo lo que estamos haciendo son principalmente multiplicaciones y sumas de grandes conjuntos de números. Por lo tanto, multiplicar un número con 101 o con 2493 importará. Entonces, ¿cómo podemos asegurarnos de que un token que se representa con el número 101 no sea menos importante que 2493, solo porque lo tokenizamos arbitrariamente? ¿Cómo podemos codificar las palabras sin causar un orden ficticio?

Codificación one-hot. Mapeo disperso de tokens. La codificación one-hot es la técnica donde proyectamos cada token como un vector binario. Eso significa que solo un elemento único en el vector es 1 (“activo”) y el resto es 0 (“inactivo”).

Figura 1: Ejemplo de vector de codificación one-hot

Los tokens se representan con un vector que tiene una longitud total de tokens en nuestro corpus. En términos más simples, si tenemos 50k tokens en nuestro idioma, cada token se representa mediante un vector de 50k en el que solo un elemento es 1 y el resto es 0. Dado que cada vector en esta proyección contiene solo un elemento no nulo, se llama representación dispersa. Sin embargo, como podrás pensar, este enfoque es muy ineficiente. Sí, logramos eliminar la cardinalidad artificial entre los IDs de los tokens, pero no podemos extraer ninguna información sobre la semántica de las palabras. No podemos entender si la palabra “fiesta” se refiere a una celebración o a una organización política mediante el uso de vectores dispersos. Además, representar cada token con un vector de tamaño 50k significará un total de 50k vectores de longitud 50k. Esto es muy ineficiente en términos de memoria y cálculos requeridos. Afortunadamente, tenemos mejores soluciones.

Embeddings. Representación densa de tokens. Las unidades tokenizadas pasan por una capa de embedding donde cada token se transforma en una representación vectorial continua de tamaño fijo. Por ejemplo, en el caso de GPT 3, cada token se representa mediante un vector de 768 números. Estos números se asignan al azar y luego son aprendidos por el modelo después de ver muchos datos (entrenamiento).

Etiqueta de token: "fiesta"Token: 2283Longitud del vector de embedding: 768Forma del tensor de embedding: ([1, 10, 768])Vector de embedding: tensor([ 2.9950e-01, -2.3271e-01,  3.1800e-01, -1.2017e-01, -3.0701e-01,        -6.1967e-01,  2.7525e-01,  3.4051e-01, -8.3757e-01, -1.2975e-02,        -2.0752e-01, -2.5624e-01,  3.5545e-01,  2.1002e-01,  2.7588e-02,        -1.2303e-01,  5.9052e-01, -1.1794e-01,  4.2682e-02,  7.9062e-01,         2.2610e-01,  9.2405e-02, -3.2584e-01,  7.4268e-01,  4.1670e-01,        -7.9906e-02,  3.6215e-01,  4.6919e-01,  7.8014e-02, -6.4713e-01,         4.9873e-02, -8.9567e-02, -7.7649e-02,  3.1117e-01, -6.7861e-02,        -9.7275e-01,  9.4126e-02,  4.4848e-01,  1.5413e-01,  3.5430e-01,         3.6865e-02, -7.5635e-01,  5.5526e-01,  1.8341e-02,  1.3527e-01,        -6.6653e-01,  9.7280e-01, -6.6816e-02,  1.0383e-01,  3.9125e-02,        -2.2133e-01,  1.5785e-01, -1.8400e-01,  3.4476e-01,  1.6725e-01,        -2.6855e-01, -6.8380e-01, -1.8720e-01, -3.5997e-01, -1.5782e-01,         3.5001e-01,  2.4083e-01, -4.4515e-01, -7.2435e-01, -2.5413e-01,         2.3536e-01,  2.8430e-01,  5.7878e-01, -7.4840e-01,  1.5779e-01,        -1.7003e-01,  3.9774e-01, -1.5828e-01, -5.0969e-01, -4.7879e-01,        -1.6672e-01,  7.3282e-01, -1.2093e-01,  6.9689e-02, -3.1715e-01,        -7.4038e-02,  2.9851e-01,  5.7611e-01,  1.0658e+00, -1.9357e-01,         1.3133e-01,  1.0120e-01, -5.2478e-01,  1.5248e-01,  6.2976e-01,        -4.5310e-01,  2.9950e-01, -5.6907e-02, -2.2957e-01, -1.7587e-02,        -1.9266e-01,  2.8820e-02,  3.9966e-03,  2.0535e-01,  3.6137e-01,         1.7169e-01,  1.0535e-01,  1.4280e-01,  8.4879e-01, -9.0673e-01,                                            …                                             …                                             …                           ])

Arriba se encuentra el ejemplo del vector de inserción de la palabra “fiesta”.

Ahora tenemos un tamaño de vectores de 50,000×786, que en comparación con el codificado one-hot de 50,000×50,000 es significativamente más eficiente.

Los vectores de inserción serán las entradas del modelo. Gracias a las representaciones numéricas densas, podremos capturar la semántica de las palabras, los vectores de inserción de los tokens similares estarán más cerca entre sí.

¿Cómo se puede medir la similitud de dos unidades lingüísticas en contexto? Hay varias funciones que pueden medir la similitud entre dos vectores del mismo tamaño. Vamos a explicarlo con un ejemplo.

Consideremos un ejemplo simple en el que tenemos los vectores de inserción de los tokens “gato”, “perro”, “coche” y “plátano”. Para simplificar, usemos un tamaño de inserción de 4. Esto significa que habrá cuatro números aprendidos para representar cada token.

import numpy as npfrom sklearn.metrics.pairwise import cosine_similarity# Ejemplo de vectores de inserción para "gato", "perro", "coche" y "plátano"embedding_gato = np.array([0.5, 0.3, -0.1, 0.9])embedding_perro = np.array([0.6, 0.4, -0.2, 0.8])embedding_coche = np.array([0.5, 0.3, -0.1, 0.9])embedding_plátano = np.array([0.1, -0.8, 0.2, 0.4])

Usando los vectores anteriores, calculemos las puntuaciones de similitud utilizando la similitud del coseno. La lógica humana encontraría las palabras perros y gatos más relacionadas entre sí que las palabras plátano y coche. ¿Podemos esperar que las matemáticas simulen nuestra lógica?

# Calcular similitud del cosenosimilitud = cosine_similarity([embedding_gato], [embedding_perro])[0][0]print(f"Similitud del coseno entre 'gato' y 'perro': {similitud:.4f}")# Calcular similitud del cosenosimilitud_2 = cosine_similarity([embedding_coche], [embedding_plátano])[0][0]print(f"Similitud del coseno entre 'coche' y 'plátano': {similitud:.4f}")

"Similitud del coseno entre 'gato' y 'perro': 0.9832""Similitud del coseno entre 'coche' y 'plátano': 0.1511"

Podemos ver que las palabras “gato” y “perro” tienen una puntuación de similitud muy alta, mientras que las palabras “coche” y “plátano” tienen una puntuación muy baja. Ahora imagina vectores de inserción de longitud 768 en lugar de 4 para cada uno de los 50000 tokens en nuestro corpus de lenguaje. Así es como podemos encontrar las palabras que están relacionadas entre sí.

Ahora, echemos un vistazo a las dos oraciones a continuación, que tienen una mayor complejidad semántica.

"los estudiantes celebran la graduación con una gran fiesta""el líder adjunto es muy respetado en el partido"

La palabra “fiesta” en la primera y segunda oración transmite significados diferentes. ¿Cómo son capaces los modelos de lenguaje grandes de mapear la diferencia entre “fiesta” como una organización política y “fiesta” como un evento social de celebración?

¿Podemos distinguir los diferentes significados del mismo token confiando en las inserciones del token? La verdad es que, aunque las inserciones nos proporcionan una serie de ventajas, no son adecuadas para desentrañar toda la complejidad de los desafíos semánticos del lenguaje humano.

Auto-atención. La solución fue nuevamente ofrecida por las redes neuronales transformadoras. Generamos un nuevo conjunto de pesos que son las matrices de consulta, clave y valor. Esos pesos aprenden a representar los vectores de inserción de los tokens como un nuevo conjunto de inserciones. ¿Cómo? Simplemente tomando el promedio ponderado de las inserciones originales. Cada token “atiende” a cada otro token (incluyéndose a sí mismo) en la oración de entrada y calcula un conjunto de pesos de atención o, en otras palabras, las nuevas inserciones llamadas “contextuales”.

Todo lo que realmente hace es asignar la importancia de las palabras en la oración de entrada asignando un nuevo conjunto de números (pesos de atención) que se calculan utilizando las inserciones de los tokens.

Figura 2: Pesos de atención de un token en diferentes contextos (vista de atención de BertViz)

La visualización anterior muestra la “atención” del token “fiesta” hacia el resto de los tokens en dos oraciones. La intensidad de la conexión se refiere a la importancia o relevancia de los tokens. La atención y “atender” son simplemente una serie de números y su magnitud, que usamos para representar la importancia de las palabras numéricamente. En la primera oración, la palabra “fiesta” se dirige principalmente a la palabra “celebrar”, mientras que en la segunda oración la palabra “líder adjunto” tiene la atención más alta. Así es como el modelo es capaz de incorporar el contexto examinando las palabras circundantes.

Como mencionamos en el mecanismo de atención, derivamos un nuevo conjunto de matrices de pesos, a saber: Consulta, Clave y Valor (simplemente q, k, v). Son matrices en cascada del mismo tamaño (generalmente más pequeñas que los vectores de incrustación) que se introducen en la arquitectura para capturar la complejidad en las unidades de lenguaje. Los parámetros de atención se aprenden para desmitificar la relación entre las palabras, pares de palabras, pares de pares de palabras, pares de pares de pares de palabras, y así sucesivamente. A continuación se muestra la visualización de las matrices de consulta, clave y valor para encontrar la palabra más relevante.

Ilustración de las matrices de consulta, clave y valor y sus probabilidades finales (Softmax)

La visualización muestra los vectores q y k como bandas verticales, donde la intensidad de cada banda refleja su magnitud. Las conexiones entre los tokens indican los pesos determinados por la atención, lo que indica que el vector q para “fiesta” se alinea de manera más significativa con el vector k para “es”, “subdirector” y “respetado”.

Para hacer que el mecanismo de atención y los conceptos de q, k y v sean menos abstractos, imagina que fuiste a una fiesta y escuchaste una canción increíble de la que te enamoraste. Después de la fiesta, estás ansioso por encontrar la canción y escucharla de nuevo, pero solo recuerdas apenas 5 palabras de la letra y parte de la melodía de la canción (consulta). Para encontrar la canción, decides revisar la lista de reproducción de la fiesta (claves) y escuchar (función de similitud) todas las canciones de la lista que se reprodujeron en la fiesta. Cuando finalmente reconoces la canción, anotas el nombre de la canción (valor).

Un último truco importante que introdujeron los transformers es agregar las codificaciones posicionales a las incrustaciones vectoriales. Simplemente porque nos gustaría capturar la información de posición de la palabra. Mejora nuestras posibilidades de predecir el siguiente token con mayor precisión hacia el verdadero contexto de la oración. Es información esencial porque a menudo intercambiar las palabras cambia completamente el contexto. Por ejemplo, las oraciones “Tim persiguió nubes toda su vida” vs “nubes persiguieron a Tim toda su vida” son absolutamente diferentes en esencia.

Todos los trucos matemáticos que hemos explorado hasta ahora a nivel básico tienen el objetivo de predecir el siguiente token, dado la secuencia de tokens de entrada. De hecho, GPT se entrena en una tarea simple que es la generación de texto o, en otras palabras, la predicción del siguiente token. En el fondo, medimos la probabilidad de un token, dado la secuencia de tokens que aparecen antes que él.

Puede que te preguntes cómo los modelos aprenden los números óptimos a partir de números asignados al azar. Ese es un tema para otra publicación de blog, probablemente, sin embargo, eso es realmente fundamental para entender. Además, es una gran señal de que ya estás cuestionando lo básico. Para eliminar la falta de claridad, utilizamos un algoritmo de optimización que ajusta los parámetros en función de una métrica llamada función de pérdida. Esta métrica se calcula comparando los valores predichos con los valores reales. El modelo realiza un seguimiento de las posibilidades de la métrica y, dependiendo de cuán pequeño o grande sea el valor de pérdida, ajusta los números. Este proceso se repite hasta que la pérdida no pueda ser menor dadas las reglas que establecemos en el algoritmo que llamamos hiperparámetros. Un ejemplo de hiperparámetro puede ser con qué frecuencia queremos calcular la pérdida y ajustar los pesos. Esta es la idea rudimentaria detrás del aprendizaje.

Espero que en esta breve publicación haya logrado aclarar un poco la imagen. La segunda parte de esta serie de blogs se centrará en las estrategias de decodificación, es decir, en por qué importa tu indicación. La tercera y última parte estará dedicada al factor clave del éxito de ChatGPT, que es el aprendizaje por refuerzo a través de la retroalimentación humana. Muchas gracias por la lectura. Hasta la próxima.

Referencias:

A. Vaswani, N. Shazeer, N. Parmar, J. Uszkoreit, L. Jones, A. N. Gomez, Ł. Kaiser e I. Polosukhin, “La atención es todo lo que necesitas”, en Avances en el Procesamiento de Información Neural 30 (NIPS 2017), 2017.

J. Vig, “Una visualización multiescala de la atención en el modelo Transformer”, en Actas de la 57ª Reunión Anual de la Asociación de Lingüística Computacional: Demostraciones del Sistema, pp. 37-42, Florencia, Italia, Asociación de Lingüística Computacional, 2019.

L. Tunstall, L. von Werra y T. Wolf, “Procesamiento del Lenguaje Natural con Transformers, Edición Revisada”, O’Reilly Media, Inc., Lanzado en mayo de 2022, ISBN: 9781098136796.

1 – Blog del Programador Perezoso

We will continue to update Zepes; if you have any questions or suggestions, please contact us!

Share:

Was this article helpful?

93 out of 132 found this helpful

Discover more

Ciencia de Datos

Aprendizaje Profundo en Sistemas de Recomendación Una introducción.

Los sistemas de recomendación se encuentran entre las aplicaciones de Aprendizaje Automático industrial de más rápido...

Inteligencia Artificial

Investigadores cultivan matrices precisas de nanoLEDs

Una nueva técnica produce nanocristales de perovskita justo donde se necesitan, para que los materiales extremadament...

Inteligencia Artificial

Investigadores de ETH Zurich y Microsoft presentan SCREWS Un marco de inteligencia artificial para mejorar el razonamiento en modelos de lenguaje grandes.

Los grandes modelos de lenguaje (LLMs) han tenido éxito en varias tareas de razonamiento diferentes. Para garantizar ...

Inteligencia Artificial

Un 'mapa' más preciso de las luces que ves cuando cierras los ojos puede mejorar los resultados de los 'ojos biónicos'.

Un método de mapeo de fosfenos desarrollado por investigadores de la Universidad de Monash en Australia podría ayudar...