0. Basic LLM Concepts
Preentrenamiento
El preentrenamiento es la fase fundamental en el desarrollo de un modelo de lenguaje grande (LLM) donde el modelo se expone a grandes y diversas cantidades de datos textuales. Durante esta etapa, el LLM aprende las estructuras, patrones y matices fundamentales del lenguaje, incluyendo gramática, vocabulario, sintaxis y relaciones contextuales. Al procesar estos datos extensos, el modelo adquiere una comprensión amplia del lenguaje y del conocimiento general del mundo. Esta base integral permite al LLM generar texto coherente y contextualmente relevante. Posteriormente, este modelo preentrenado puede someterse a un ajuste fino, donde se entrena aún más en conjuntos de datos especializados para adaptar sus capacidades a tareas o dominios específicos, mejorando su rendimiento y relevancia en aplicaciones específicas.
Componentes principales de LLM
Usualmente, un LLM se caracteriza por la configuración utilizada para entrenarlo. Estos son los componentes comunes al entrenar un LLM:
Parámetros: Los parámetros son los pesos y sesgos aprendibles en la red neuronal. Estos son los números que el proceso de entrenamiento ajusta para minimizar la función de pérdida y mejorar el rendimiento del modelo en la tarea. Los LLM suelen utilizar millones de parámetros.
Longitud del contexto: Esta es la longitud máxima de cada oración utilizada para preentrenar el LLM.
Dimensión de incrustación: El tamaño del vector utilizado para representar cada token o palabra. Los LLM suelen usar miles de millones de dimensiones.
Dimensión oculta: El tamaño de las capas ocultas en la red neuronal.
Número de capas (profundidad): Cuántas capas tiene el modelo. Los LLM suelen usar decenas de capas.
Número de cabezales de atención: En los modelos de transformadores, esta es la cantidad de mecanismos de atención separados que se utilizan en cada capa. Los LLM suelen usar decenas de cabezales.
Dropout: El dropout es algo así como el porcentaje de datos que se eliminan (las probabilidades se convierten en 0) durante el entrenamiento utilizado para prevenir el sobreajuste. Los LLM suelen usar entre 0-20%.
Configuración del modelo GPT-2:
Tensors en PyTorch
En PyTorch, un tensor es una estructura de datos fundamental que sirve como un array multidimensional, generalizando conceptos como escalares, vectores y matrices a dimensiones potencialmente más altas. Los tensores son la forma principal en que los datos se representan y manipulan en PyTorch, especialmente en el contexto del aprendizaje profundo y las redes neuronales.
Concepto Matemático de Tensores
Escalares: Tensores de rango 0, que representan un solo número (cero-dimensional). Como: 5
Vectores: Tensores de rango 1, que representan un array unidimensional de números. Como: [5,1]
Matrices: Tensores de rango 2, que representan arrays bidimensionales con filas y columnas. Como: [[1,3], [5,2]]
Tensores de Rango Superior: Tensores de rango 3 o más, que representan datos en dimensiones superiores (por ejemplo, tensores 3D para imágenes en color).
Tensores como Contenedores de Datos
Desde una perspectiva computacional, los tensores actúan como contenedores para datos multidimensionales, donde cada dimensión puede representar diferentes características o aspectos de los datos. Esto hace que los tensores sean altamente adecuados para manejar conjuntos de datos complejos en tareas de aprendizaje automático.
Tensores de PyTorch vs. Arrays de NumPy
Mientras que los tensores de PyTorch son similares a los arrays de NumPy en su capacidad para almacenar y manipular datos numéricos, ofrecen funcionalidades adicionales cruciales para el aprendizaje profundo:
Diferenciación Automática: Los tensores de PyTorch soportan el cálculo automático de gradientes (autograd), lo que simplifica el proceso de calcular derivadas requeridas para entrenar redes neuronales.
Aceleración por GPU: Los tensores en PyTorch pueden ser movidos y computados en GPUs, acelerando significativamente los cálculos a gran escala.
Creando Tensores en PyTorch
Puedes crear tensores usando la función torch.tensor
:
Tipos de Datos de Tensor
Los tensores de PyTorch pueden almacenar datos de varios tipos, como enteros y números de punto flotante.
Puedes verificar el tipo de dato de un tensor usando el atributo .dtype
:
Los tensores creados a partir de enteros de Python son de tipo
torch.int64
.Los tensores creados a partir de flotantes de Python son de tipo
torch.float32
.
Para cambiar el tipo de datos de un tensor, utiliza el método .to()
:
Operaciones Comunes con Tensores
PyTorch proporciona una variedad de operaciones para manipular tensores:
Accediendo a la Forma: Usa
.shape
para obtener las dimensiones de un tensor.
Reformando Tensores: Usa
.reshape()
o.view()
para cambiar la forma.
Transponiendo Tensores: Usa
.T
para transponer un tensor 2D.
Multiplicación de Matrices: Usa
.matmul()
o el operador@
.
Importancia en el Aprendizaje Profundo
Los tensores son esenciales en PyTorch para construir y entrenar redes neuronales:
Almacenan datos de entrada, pesos y sesgos.
Facilitan las operaciones requeridas para los pasos hacia adelante y hacia atrás en los algoritmos de entrenamiento.
Con autograd, los tensores permiten el cálculo automático de gradientes, agilizando el proceso de optimización.
Diferenciación Automática
La diferenciación automática (AD) es una técnica computacional utilizada para evaluar las derivadas (gradientes) de funciones de manera eficiente y precisa. En el contexto de redes neuronales, AD permite el cálculo de gradientes requeridos para algoritmos de optimización como el descenso de gradiente. PyTorch proporciona un motor de diferenciación automática llamado autograd que simplifica este proceso.
Explicación Matemática de la Diferenciación Automática
1. La Regla de la Cadena
En el corazón de la diferenciación automática está la regla de la cadena del cálculo. La regla de la cadena establece que si tienes una composición de funciones, la derivada de la función compuesta es el producto de las derivadas de las funciones compuestas.
Matemáticamente, si y=f(u)
y u=g(x)
, entonces la derivada de y
con respecto a x
es:
2. Grafo Computacional
En AD, los cálculos se representan como nodos en un grafo computacional, donde cada nodo corresponde a una operación o una variable. Al recorrer este grafo, podemos calcular derivadas de manera eficiente.
Ejemplo
Consideremos una función simple:
Donde:
σ(z)
es la función sigmoide.y=1.0
es la etiqueta objetivo.L
es la pérdida.
Queremos calcular el gradiente de la pérdida L
con respecto al peso w
y al sesgo b
.
4. Cálculo de Gradientes Manualmente
5. Cálculo Numérico
Implementando la Diferenciación Automática en PyTorch
Ahora, veamos cómo PyTorch automatiza este proceso.
Salida:
Retropropagación en Redes Neuronales Más Grandes
1. Ampliación a Redes Multicapa
En redes neuronales más grandes con múltiples capas, el proceso de cálculo de gradientes se vuelve más complejo debido al aumento en el número de parámetros y operaciones. Sin embargo, los principios fundamentales permanecen iguales:
Paso Adelante: Calcular la salida de la red pasando las entradas a través de cada capa.
Calcular Pérdida: Evaluar la función de pérdida utilizando la salida de la red y las etiquetas objetivo.
Paso Atrás (Retropropagación): Calcular los gradientes de la pérdida con respecto a cada parámetro en la red aplicando la regla de la cadena de manera recursiva desde la capa de salida hasta la capa de entrada.
2. Algoritmo de Retropropagación
Paso 1: Inicializar los parámetros de la red (pesos y sesgos).
Paso 2: Para cada ejemplo de entrenamiento, realizar un paso adelante para calcular las salidas.
Paso 3: Calcular la pérdida.
Paso 4: Calcular los gradientes de la pérdida con respecto a cada parámetro utilizando la regla de la cadena.
Paso 5: Actualizar los parámetros utilizando un algoritmo de optimización (por ejemplo, descenso de gradiente).
3. Representación Matemática
Considera una red neuronal simple con una capa oculta:
4. Implementación en PyTorch
PyTorch simplifica este proceso con su motor de autograd.
En este código:
Forward Pass: Calcula las salidas de la red.
Backward Pass:
loss.backward()
calcula los gradientes de la pérdida con respecto a todos los parámetros.Parameter Update:
optimizer.step()
actualiza los parámetros en función de los gradientes calculados.
5. Understanding Backward Pass
Durante el backward pass:
PyTorch recorre el grafo computacional en orden inverso.
Para cada operación, aplica la regla de la cadena para calcular los gradientes.
Los gradientes se acumulan en el atributo
.grad
de cada tensor de parámetro.
6. Advantages of Automatic Differentiation
Efficiency: Evita cálculos redundantes al reutilizar resultados intermedios.
Accuracy: Proporciona derivadas exactas hasta la precisión de la máquina.
Ease of Use: Elimina el cálculo manual de derivadas.
Last updated