¿Cómo seleccionar una función de pérdida y un optimizador en PyTorch?
Seleccionar la función de pérdida y el optimizador adecuados es crucial para entrenar efectivamente un modelo de regresión lineal. PyTorch facilita este proceso al ofrecer una variedad de opciones dentro de sus módulos nn y torch.optim. La documentación de PyTorch es una excelente fuente de información para explorar estas alternativas, junto con frameworks similares como NumPy, que también ofrecen una serie de funciones de pérdida.
¿Qué es la función de pérdida L1Loss y por qué es recomendable?
La función de pérdida es esencial para medir cuán lejos están las predicciones del modelo de los valores reales. Para este ejemplo de regresión lineal, utilizamos la función de pérdida L1Loss, también conocida como error absoluto medio (MAE). Esta función es popular para datos tabulares con variables continuas, ya que mide la magnitud promedio de los errores en un conjunto de predicciones sin considerar su dirección.
Para implementar L1Loss en PyTorch, se utiliza de la siguiente manera:
import torch.nn as nn
# Definir la función de pérdidafn_perdida = nn.L1Loss()
¿Cómo configurar un optimizador como SGD?
El proceso de optimización es clave para mejorar los parámetros de nuestro modelo a través de métodos como el Descenso del Gradiente Estocástico (SGD). Para configurarlo en PyTorch, es importante definir la tasa de aprendizaje, un hiperparámetro que determina la magnitud de las actualizaciones de los parámetros.
Una práctica recomendada al establecer la tasa de aprendizaje es comenzar con un valor como 0.01, experimentando posteriormente para encontrar el valor óptimo. La configuración del optimizador se realiza así:
import torch.optim as optim
# Definir el optimizadoroptimizador = optim.SGD(modelo.parameters(), lr=0.01)
¿Cómo entrenar un modelo de regresión lineal?
El entrenamiento de un modelo implica múltiples etapas, comenzando con la inicialización de hiperparámetros importantes como el número de épocas. Estas determinan cuántas veces se revisarán los datos de entrenamiento.
¿Cuáles son los pasos del bucle de entrenamiento?
Modo Train: Configuramos el modelo en modo de entrenamiento, permitiendo mejorar los parámetros y calcular los gradientes.
Predicción y cálculo de pérdida: Realizar una predicción con los datos de entrenamiento y calcular la pérdida resultante:
Reseteo de gradientes: Es crucial reiniciar los gradientes para obtener nuevos valores limpios en cada iteración.
optimizador.zero_grad()
Retropropagación: Calculamos los gradientes de la función de pérdida respecto a los parámetros.
perdida.backward()
Actualización de parámetros: Aplicamos la tasa de aprendizaje para ajustar los parámetros.
optimizador.step()
¿Cómo evaluar el modelo después del entrenamiento?
El modo de evaluación, al contrario del de entrenamiento, no modifica los parámetros del modelo. Sirve para validar cómo este predice los datos cuando no se entrena:
with torch.no_grad():# Desactiva el cálculo de gradientes modelo.eval() y_pred_prueba = modelo(x_prueba) perdida_prueba = fn_perdida(y_pred_prueba, y_prueba.float())
Elegir y adaptar correctamente estos elementos según las características de los datos es vital para maximizar el rendimiento del modelo. A medida que avanzas en aplicaciones más complejas, la experimentación y ajustes continuos de estos hiperparámetros te llevarán a obtener resultados más precisos. ¡Adelante, sigue explorando y optimizando tus modelos!
Para los que no comprendan aun bien que es el Stochastic Gradient Descent
El Stochastis Gradient Descent que es el optimizador que utilizamos aqui es uno de los optimizadores mas comunes, simplemente es hacer un Gradient Descent pero en vez de tomar todos los datos y hacer calculos a partir de ellos, tomamos pequenos lotes, es decir una muestra de los datos para hacer los calculos sobre esto, que nos ahorra mucho el tiempo de entrenamiento del modelo.
Si no entiendes que es el Gradient Descent
Nota: Gradient o gradiente es una forma de decirle a las derivadas parciales de una funcion, a la manera más simple, siempre que leas gradiente entiende muchas derivadas de una funcion.
💡 De manera simple es ir viendo como bajamos la funcion de error, por medio de ver que tan lejos estamos del numero optimo de error que buscamos, y vamos modificando por iteracion. El gradiente no es mas que derivar, ver si hay que subir o bajar el gradiente y entonces le restamos este gradiente al parametro actual.
Por que restamos? porque el gradiente calcula hacia donde va la funcion y para moverla al lado contrario con tal de llegar a 0. Es decir, si lo vemos como una brujula, el gradiente nos dice que vamos subiendo, cuando en realidad queremos bajar entonces por eso la resta.
Videos (En ingles) que puede funcionar entender a profundidad estos temas
Gradient Descent
Stochastic Gradien Descent
¿Pero por cual función nos estamos moviendo con el descenso de gradiente? por la función de error, en este caso MAE. En otros casos se usa la función de error Entropia Cruzada.
Lo digo porque tenia esa confusión. Todos dicen, hay que hacer descenso de gradiente. Ok, se saca la derivada de la función, eso nos entrega la pendiente de la tangente en ese punto y nos movemos en dirección contraria de la pendiente el numero de unidides lamda (o tasa de aprendizaje)... Pero ¡¡¿cual función voy a derivar (bueno la libreria deriva)?!! Pues la función error panita!
Es la funcion de perdida amigo
En PyTorch, el proceso de entrenamiento de un modelo implica definir una **función de pérdida** (loss function) y un **optimizador**, que se encargan de actualizar los pesos del modelo en función del error entre las predicciones del modelo y los valores reales. Aquí te explico cada uno de estos elementos y te doy un ejemplo práctico.
### Entrenamiento en PyTorch: Conceptos Clave
1. **Función de Pérdida (Loss Function):**
La función de pérdida mide la diferencia entre las predicciones del modelo y los valores verdaderos. Su valor se minimiza durante el entrenamiento. Algunas funciones comunes son:
- nn.MSELoss: Para problemas de regresión (Minimiza el error cuadrático medio).
- nn.CrossEntropyLoss: Para problemas de clasificación múltiple.
- nn.BCELoss: Para problemas de clasificación binaria.
2. **Optimizador:**
El optimizador es el algoritmo que ajusta los pesos del modelo para reducir la función de pérdida. Un optimizador popular es **Stochastic Gradient Descent (SGD)**, pero PyTorch también ofrece otros optimizadores como **Adam**.
- torch.optim.SGD: Descenso de gradiente estocástico.
- torch.optim.Adam: Un optimizador más avanzado, que a menudo funciona mejor en redes más complejas.
3. **Ciclo de Entrenamiento:**
- **Paso 1:** Pasar los datos de entrada a través del modelo.
- **Paso 2:** Calcular la pérdida entre las predicciones y los valores reales.
- **Paso 3:** Retropropagar el error (backpropagation).
- **Paso 4:** Actualizar los pesos utilizando el optimizador.
### Ejemplo Completo
Este es un ejemplo de entrenamiento de un modelo simple con una función de pérdida y un optimizador.
import torch
import torch.nn as nn
import torch.optim as optim
\# Definición del modelo (similar al ejemplo anterior)classSimpleNN(nn.Module):  def \_\_init\_\_(self, input\_size, hidden\_size, output\_size):  super(SimpleNN, self).\_\_init\_\_()  self.fc1 = nn.Linear(input\_size, hidden\_size) # Capa oculta  self.fc2 = nn.Linear(hidden\_size, output\_size) # Capa de salida  self.relu = nn.ReLU() # Función de activación ReLU  def forward(self, x):  x = self.fc1(x)  x = self.relu(x)  x = self.fc2(x)  return x\# Parámetros del modelo
input\_size =10hidden\_size =5output\_size =1learning\_rate =0.01\# Crear una instancia del modelo
model = SimpleNN(input\_size, hidden\_size, output\_size)
\# Definir la función de pérdida y el optimizador
criterion = nn.MSELoss()# Pérdida para regresiónoptimizer = optim.SGD(model.parameters(), lr=learning\_rate)# Optimizador SGD
\# Datos ficticios para entrenamiento
inputs = torch.randn(100,input\_size)# 100 ejemplos, 10 característicastargets = torch.randn(100, output\_size)# 100 etiquetas de salida\# Entrenamiento del modelo
num\_epochs =100for epoch inrange(num\_epochs):  \# Paso hacia adelante (Forward pass): calcular predicciones  outputs = model(inputs)     \# Calcular la pérdida  loss = criterion(outputs, targets)     \# Paso hacia atrás (Backward pass): retropropagación  optimizer.zero\_grad() # Resetear los gradientes  loss.backward() # Calcular los gradientes     \# Actualizar los pesos  optimizer.step() # Actualizar los parámetros del modelo     \# Imprimir la pérdida en intervalos  if (epoch+1) % 10 == 0:  print(f'Epoch \[{epoch+1}/{num\_epochs}], Loss: {loss.item():.4f}')
\# Predicción con el modelo entrenado
test\_input = torch.randn(1,input\_size)predicted\_output = model(test\_input)print(f'Predicted Output: {predicted\_output}')
### Explicación Paso a Paso
1. **Modelo:** Usamos una red neuronal simple con una capa oculta y una función de activación ReLU.
2. **Función de pérdida (criterion):** Se utiliza MSELoss (Error Cuadrático Medio) para este ejemplo de regresión.
3. **Optimizador (optimizer):** Se usa SGD (Stochastic Gradient Descent) con una tasa de aprendizaje de 0.01.
4. **Datos de Entrenamiento:** Generamos datos ficticios aleatorios para los ejemplos y etiquetas.
5. **Ciclo de Entrenamiento:**
- Se calculan las predicciones del modelo.
- Se calcula la pérdida comparando las predicciones con las etiquetas reales.
- Se retropropaga el error para calcular los gradientes.
- Se actualizan los pesos del modelo con el optimizador.
6. **Impresión del Progreso:** Se imprime la pérdida cada 10 épocas.
### Otras Funciones de Pérdida y Optimizadores
#### Funciones de Pérdida Comunes:
- nn.CrossEntropyLoss: Para clasificación múltiple.
- nn.BCELoss: Para clasificación binaria.
#### Optimizadores Comunes:
- torch.optim.Adam: Un optimizador avanzado que usa tasas de aprendizaje adaptativas.
- torch.optim.RMSprop: Similar a Adam, pero con algunas diferencias en cómo actualiza los parámetros.
Este es el flujo básico del entrenamiento de modelos en PyTorch. ¿Te gustaría ver más ejemplos o detalles sobre algún otro optimizador o tipo de función de pérdida?
{"Función de Pérdida (Loss Function)":"La función de pérdida mide la diferencia entre las predicciones del modelo y los valores verdaderos.","Optimizador":"El optimizador ajusta los pesos del modelo para reducir la función de pérdida."}
Los 5 pasos del entrenamiento mencionados son comunes en muchos modelos de aprendizaje automático, incluidos aquellos que utilizan PyTorch. Estos pasos incluyen:
Modo entrenamiento: Preparar el modelo para entrenar.
Predicción: Calcular la salida del modelo con datos de entrada.
Cálculo de la pérdida: Comparar las predicciones con las etiquetas reales.
Cálculo de gradientes: Ajustar los gradientes para optimizar los parámetros.
Optimización: Actualizar los parámetros del modelo.
Aunque la estructura puede variar, estos principios fundamentales son aplicables a la mayoría de los modelos de deep learning.
Creo que hay un error en la guía, el MAE es el error absoluto medio, no cuadrático
importtorchfrom torch import nn
import torch.optimas optim
import matplotlib.pyplotas plt
# ============================================================# 0)MODELO:Regresión lineal simple y = w*x + b
# ============================================================classModeloRegresion(nn.Module): def __init__(self):super().__init__() # Defino los parámetros entrenables del modelo
# volumen representa el peso(w) y sesgo el bias(b) self.volumen= nn.Parameter(torch.rand(1, dtype=torch.float, requires_grad=True)) self.sesgo= nn.Parameter(torch.rand(1, dtype=torch.float, requires_grad=True)) def forward(self,x: torch.Tensor)-> torch.Tensor: # Implemento la ecuación de la recta: y = w*x + b
return self.volumen* x + self.sesgo# ============================================================# 1)INICIALIZACIÓN: semilla y modelo
# ============================================================torch.manual_seed(42)modelo1 =ModeloRegresion()# ============================================================# 2)FUNCIÓNDEPÉRDIDAYOPTIMIZADOR# ============================================================# UsoL1Loss(MAE) para medir el error absoluto promedio
fn_perdida = nn.L1Loss()# Configuro el optimizador SGD con tasa de aprendizaje de 0.025optimizador = optim.SGD(modelo1.parameters(), lr=0.025)# ============================================================# 3)LISTASPARAGUARDARHISTORIALDEPÉRDIDAS(para graficar)# ============================================================train_losses =[]test_losses =[]# ============================================================# 4)ENTRENAMIENTO# ============================================================epochs =400for epoch inrange(epochs): # ----------------------------- # MODOENTRENAMIENTO # ----------------------------- modelo1.train() # Genero las predicciones del modelo con los datos de entrenamiento
y_pred =modelo1(X_train) # Calculo la pérdida comparando predicciones con valores reales
perdida =fn_perdida(y_pred,Y_train) # Reseteo los gradientes antes del backward pass
optimizador.zero_grad() # Calculo los gradientes mediante backpropagation
perdida.backward() # Actualizo los parámetros usando los gradientes calculados
optimizador.step() # ----------------------------- # MODOEVALUACIÓN(TEST) # ----------------------------- modelo1.eval()with torch.no_grad(): y_pred_prueba =modelo1(X_test) perdida_prueba =fn_perdida(y_pred_prueba,Y_test.float()) # Almaceno las pérdidas para análisis posterior
train_losses.append(perdida.item()) test_losses.append(perdida_prueba.item()) # Muestro el progreso cada 20 iteraciones
if epoch %20==0:print(f"Epoch {epoch} | Train Loss: {perdida.item():.5f} | Test Loss: {perdida_prueba.item():.5f}")# ============================================================# 5)GRÁFICA1:Curva de aprendizaje(loss vs épocas)# ============================================================plt.figure()plt.plot(train_losses, label="Train Loss (MAE)")plt.plot(test_losses, label="Test Loss (MAE)")plt.xlabel("Épocas")plt.ylabel("Pérdida (MAE)")plt.title("Curva de aprendizaje")plt.legend()plt.show()# ============================================================# 6)GRÁFICA2:Datos reales vs predicción final del modelo
# ============================================================modelo1.eval()with torch.no_grad(): predicciones =modelo1(X_test)# Convierto los tensores a numpy para visualización
x =X_test.detach().cpu().numpy()y_real =Y_test.detach().cpu().numpy()y_pred = predicciones.detach().cpu().numpy()plt.figure()plt.scatter(x, y_real, label="Datos reales")plt.plot(x, y_pred, label="Modelo aprendido")plt.xlabel("X")plt.ylabel("Y")plt.title("Regresión lineal aprendida (y = w*x + b)")plt.legend()plt.show()# ============================================================# 7)EXTRA:Imprimir parámetros finales aprendidos
# ============================================================print("Peso aprendido (w / volumen):", modelo1.volumen.item())print("Sesgo aprendido (b):", modelo1.sesgo.item())
Con SGD, lo que pasa es que si pudieramos visualizar es que la "convergencia" hacia el minimo global se hace mas "saltarin" coin respecto al Gradient Descendent - el cual actualiza los pesos en toda el dataset de entrenamiento. Si SGD lo combinamos con el momentun (otro parametro del optimizador), lo que hace es que eventualmente en funciones de perdida con valles , el SGD + momentum , hace que "brinque" los minimos locales y siga buscando el minimo global
■ Resumen:
La elección de la función de pérdida y el optimizador debe estar guiada por la naturaleza del problema, la arquitectura del modelo, la estabilidad y la convergencia deseada, y los recursos disponibles. Para la mayoría de los casos SGD funciona bien, pero dataset más complejos, precisarán de otras funciones.
Seleccionaremos una función de pérdida y el optimizador para el entrenamiento de modelo. La función de pérdida mide que tan equivocadas están las predicciones del modelo, y_pred en comparación con las etiquetas.
El optimizador le indica a los modelos como actualizar sus parámetros internos para reducir la pérdida.
Para el siguiente ejemplo podremos usar el Error cuadrático medio, como la función de pérdida torch.nn-L1Loss para medir la diferencia absoluta entre dos puntos y tomar la media en todos los ejemplos.
Para el optimizador usaremos Stocastic Gradient Descent SGD como optimizador donde los parámetros serán el volume y el bias, lr es la tasa de aprendizaje para que el optimizador actualice los pesos. (O cuales sean tus parámetros)
El descenso de gradiente estocástico (SGD) es como bajar una montaña a ciegas. En cada paso, sientes la pendiente justo debajo de ti y das un paso en esa dirección. Repites esto muchas veces hasta llegar al punto más bajo (o casi). Es rápido pero a veces puede no ser la ruta más directa.