Ya tenemos todas las configuraciones previas para programar nuestra red, lo siguiente será definir una arquitectura, compilar el modelo y revisar el rendimiento de la red.
Creando el modelo de red neuronal
Definiremos un modelo con la clase Sequential de Keras, esta nos permitirá apilar varias capas una encima de otra para lograr el efecto de aprendizaje profundo.
La primer capa será de entrada, donde recibiremos una imagen de 28x28 pixeles en un solo canal, una vez recibida será aplanada para ser procesada como un array unidimensional.
Las siguientes 2 capas serán capas profundas con 256 y 128 neuronas respectivamente, y tendrán como función de activación la ReLU.
La capa de salida será una capa de 24 neuronas (una por cada posible clase) de activación Softmax que nos retornará un array con las probabilidades de cada letra.
Compilaremos el modelo definiendo un optimizador, para este caso determinamos adam, un algoritmo que permite actualizar automáticamente el learning rate según el desempeño de la red. Como función de pérdida aplicaremos categorical cross entropy y la métrica de éxito será la precisión.
Entrenaremos el modelo con el image generator de entrenamiento, durante 20 épocas y con los datos de validación.
Para entender más gráficamente lo que sucedió, crearemos la función de visualización de resultados, que comparará el rendimiento del entrenamiento sobre el rendimiento de validación tanto términos de accuracy como de loss.
defvisualizacion_resultados(history): epochs =[i for i inrange(20)] fig, ax = plt.subplots(1,2) train_acc = history.history["accuracy"] train_loss = history.history["loss"] val_acc = history.history["val_accuracy"] val_loss = history.history["val_loss"] fig.set_size_inches(16,9) ax[0].plot(epochs, train_acc,"go-", label ="Train accuracy") ax[0].plot(epochs, val_acc,"ro-", label ="Validation accuracy") ax[0].set_title("Train and Val accuracy") ax[0].legend() ax[0].set_xlabel("Epochs") ax[0].set_ylabel("Accuracy") ax[1].plot(epochs, train_loss,"go-", label ="Train Loss") ax[1].plot(epochs, val_loss,"ro-", label ="Validation Loss") ax[1].set_title("Train and Val loss") ax[1].legend() ax[1].set_xlabel("Epochs") ax[1].set_ylabel("Loss") plt.show()
Si corremos la función obtendremos información valiosísima con respecto al comportamiento del modelo.
visualizacion_resultados(history)
Puedes notar una diferencia abrupta tanto en el accuracy como en el loss, en la etapa de entrenamiento la red aprendió óptimamente y redujo la pérdida de manera constante, mientras que en validación sufrió de un rápido estancamiento, esto puede ser señal de overfitting, donde la red calcó los ejemplos y no los patrones.
si, es un vivo ejemplo de overfitting, y el curso esta confirmando de forma mucho mas practica todo el background que se debe de tener en NN
Trabajando con el dataset de Malaria se obtienen los siguientes resultados:
Existe una buena relación entre la curva de entrenamiento y la curva de validación, se podría decir que el modelo se ha generalizado correctamente, aunque debemos tomar en cuenta que solamente se ha logrado una precisión de 0.72.
cada vez se pone mejor el curso :)
El split de validación siempre debe salir de training, es por esto que solo existen las etiquetas "training" y "validation" para los subset.
*
En el dataset de señales, hay en total 27455 imágenes de train y 7172 de test.
*
Si saco el 0.2 de validación del dataset de training al final obtengo:
train: 21974
validation: 5481
test: 7172
Es decir, las imágenes de validación no se tienen en cuenta en el training.
*
Sin embargo, si saco el 0.2 de validación del dataset de testeo (como lo hizo el profesor), obtengo:
train: 27455
validation: 1425
test: 7172
Es decir, las imágenes que estoy usando en validación, son imágenes que luego uso en el test, ya que estas no son descontadas del otro generador sino copiadas.
Sí, totalmente de acuerdo, al hacer el split en test, nos quedan muy pocas imágenes para validation, es por eso que tomarlo de train es mejor, ya que son más y el modelo puede generalizar más. :)
Además de que como dices, estamos usando las mismas imagenes de test que para validation, lo cual es malo.
En la parte de la derecha con el respectivo accuracy podemos ver como de la nada empezó a crecer muy rápido lo que puede ser porque posiblemente en su optimización su LR sea muy elevado y se paso de la convergencia , también se ve como en un punto el accuracy en mas de 5 es casi el mismo lo que nos indica que el modelo técnicamente no está aprendiendo mas por lo que pudo reaprender cosas ya vistas antes y tender al overfitting
Otra conclusión mas fácil de entender sin tanta terminología
Hagan de cuenta el ejemplo previo del papá enseñándole al hijo acerca los helados o tipos de helados , se puede ver como cuando el hijo aprende algo y le pregunta cual es este el tiende a fallar es decir dice algo que no era el resultado que se esperaba lo que nos indica que no está aprendiendo bien
Se que no es muy común en deep learning usar cross-validations, pero he visto que para casos de datasets pequeños, como imágenes clinicas, o publicaciones donde se quiere validar con más detalle estadístico algún modelo, suelen aplicar 2 a 4 folds. Entonces me entro la duda de cómo se pude hacer un KFold cross-validation con generadores. Investigando, les resumo lo que encontré:
Para poder usar ImageGenerator es necesario tener la estructura de carpetas train/class/img_n.png de lo contrario con flow_from_directory no podrá leer las imágenes. Keras no tiene integrado Kfold pero podemos usar una combinación de flow_from_dataframe con sklearn.model_selection.KFold
Entonces es necesario realizar un dataframe que tenga clase y ruta de cada imagen
Con ese dataframe usamos KFold de sklearn para dividir
Para Fold creamos un generador con ImageGenerator
Entrenamos la red con cada Fold
Comparto un ejemplo pequeño en código en los comentarios de como quedaria implementado.
# histories and generator
histories =[]datagen =ImageDataGenerator(rescale=1/255)# Examplefor2 folds
kf =KFold(n_splits=2, shuffle=True, random_state=42)
# loop
for fold,(train_idx, val_idx)inenumerate(kf.split(df)):print(f"\n🔹 Fold {fold+1}")
# train and validation sets
train_df = df.iloc[train_idx] val_df = df.iloc[val_idx] # Generators train_gen = datagen.flow_from_dataframe( dataframe=train_df, directory="data/", x_col="filename", y_col="class", target_size=img_size, batch_size=batch_size, class_mode="categorical") val_gen = datagen.flow_from_dataframe( dataframe=val_df, directory="data/", x_col="filename", y_col="class", target_size=img_size, batch_size=batch_size, class_mode="categorical") # NN model = models.Sequential([ layers.Flatten(input_shape=img_size+(3,)), layers.Dense(16, activation="relu"), layers.Dense(2, activation="softmax")]) model.compile(optimizer="adam", loss="categorical_crossentropy", metrics=["accuracy"]) # Train fold
history = model.fit(train_gen, validation_data=val_gen, epochs=5)
# save fold history
histories.append(history)
2025 August: Estoy haciendo todo con codigo actualizado en este repo
Hola!
Lo que yo creo que está sucediendo es Overfitting, si vemos los resultados con la data de training son muy buenos, pero con los de validación no, así que no está generalizando bien, y se está aprendiendo caracteristicas que solo están en el dataset de training
no entiendo cuando hace la función de gráfica pone go- y ro- en los argumentos de ax. plot ,¿para qué es ?
Claro que si Vladimir Marcos, en esa gráfica, go- y ro- son códigos de estilo para las líneas. go- significa una línea verde (g de green) con marcadores en forma de círculo (o), y ro- es una línea roja (r de red) también con marcadores circulares.
Estos estilos hacen que sea fácil ver la diferencia entre la precisión y la pérdida del entrenamiento y de la validación en la gráfica.
Me cuentas, saludos
Como se cual es el tamaño de la imagen?
Hola Adrián,
Con python y utilizando cv2 podrías saberlo asi.
O también podrías verlo directamente dando clic derecho en el archivo y en propiedades.
Sin embargo ten presente que el tamaño de todas las imágenes debe ser el mismo, por esa razón si tienes una base de datos con imágenes de diferentes tamaños, debes hacer un resize a tu base de datos para obtener el mismo tamaño en todas las imágenes.
import cv2
img = cv2.imread('PATH_IMAGEN')
# cambiar el tamaño de la imagen
output = cv2.resize(img,(640,640)) # Ejemplo cambiando el tamaño de la imagen a 640x640
Saludos
Muchisimas gracias Profe
Hace falta algo de redes convolucionales, alquien sabe si en otro curso enseñan eso?
Hola Jose
Creo que aun no lo hemos creado, pero pasaré tu sugerencia al team.
Hay un curso específico de redes convolucionales ,buscalo
ejemplo si estoy trabajando en una clasificacion binaria donde haria dos elecciones es positivo o es negativo
Hola Ivan Josue
En este caso al ser un problema de clasificación binaria se recomienda sigmoidal, la ultima capa esta correcta, sin embargo tienes mal escrito sigmoid
Consulta respecto a esto, en los otros cursos cuando era clasificación binaria se usaba sigmoide pero una sola neurona. ¿Entonces qué es lo correcto?
Habiendo realizado los mismos pasos, me dio un excelente modelo, esto es por los datos (random) que se utilizó para entrenar? O cual puede ser su causa?
Hola Matias,
Si, recuerda que cada entrenamiento que hagas sera totalmente diferente al otro, debido a que los datos de entrada, la matriz de pesos, filtros, y otras variables que la red neuronal calcula son aleatorios.
Excelente pregunta.
Esta ocurriendo un Overfitting!!!
Claro, puedo ayudarte a analizar estas gráficas.
### Análisis de las Gráficas de Accuracy y Loss
1. **Gráfica de Accuracy (Izquierda):**
- **Entrenamiento (verde):** La precisión del modelo en el conjunto de entrenamiento aumenta rápidamente y alcanza un nivel muy alto, cercano al 100%.
- **Validación (rojo):** La precisión en el conjunto de validación alcanza un pico alrededor del 75-80%, pero luego parece estabilizarse o incluso mostrar una leve tendencia a la baja en las últimas épocas.
- **Posible sobreajuste (overfitting):** La gran diferencia entre la precisión de entrenamiento y la precisión de validación indica que el modelo podría estar sobreajustando. Está aprendiendo muy bien el conjunto de entrenamiento, pero no generaliza bien en el conjunto de validación.
2. **Gráfica de Loss (Derecha):**
- **Entrenamiento (verde):** La pérdida en el conjunto de entrenamiento disminuye rápidamente y alcanza valores cercanos a cero, lo cual es consistente con el alto valor de precisión en este conjunto.
- **Validación (rojo):** La pérdida en el conjunto de validación también disminuye inicialmente, pero luego empieza a aumentar ligeramente o a estabilizarse, lo que es otro indicio de sobreajuste.
### Conclusiones y Recomendaciones
- **Sobreajuste:** Este comportamiento es típico de un modelo que sobreajusta, especialmente si la diferencia entre el accuracy de entrenamiento y validación es alta y la pérdida en validación aumenta después de algunas épocas.
- **Posibles soluciones:**
- **Regularización:** Puedes intentar técnicas como Dropout, L2 regularization o Batch Normalization para reducir el sobreajuste.
- **Aumentar los datos:** Si es posible, intenta aumentar la cantidad de datos de entrenamiento, lo que podría ayudar a mejorar la generalización.
- **Early Stopping:** Implementa una técnica de parada temprana (early stopping) para detener el entrenamiento cuando la pérdida de validación comienza a aumentar.
Aquí tienes una guía paso a paso sobre cómo crear una red neuronal con TensorFlow y Keras para realizar clasificación de imágenes. Estos pasos incluyen definir las capas, compilar el modelo, entrenarlo, evaluarlo y hacer predicciones.
### 1. Importar las Bibliotecas Necesarias
Primero, importamos TensorFlow y Keras, y configuramos el entorno.
import tensorflow as tf
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Flatten, Conv2D, MaxPooling2D
from tensorflow.keras.datasets import mnist # Dataset de ejemplofrom tensorflow.keras.utils import to\_categorical
### 2. Preparar los Datos
Usaremos el dataset MNIST de dígitos escritos a mano como ejemplo. Esto incluye cargar y preprocesar los datos.
\# Cargar los datos
(X\_train, y\_train),(X\_test, y\_test)= mnist.load\_data()\# Normalizar los datos de imágenes (escalado entre 0 y 1)X\_train, X\_test = X\_train /255.0, X\_test /255.0
\# Redimensionar los datos para añadir una dimensión de canal
X\_train = X\_train.reshape(X\_train.shape\[0],28,28,1)X\_test = X\_test.reshape(X\_test.shape\[0],28,28,1)
\# Convertir las etiquetas en una codificación categórica
y\_train = to\_categorical(y\_train,10)y\_test = to\_categorical(y\_test,10)
### 3. Crear la Red Neuronal y Definir las Capas
Creamos un modelo secuencial con capas de convolución, max pooling y capas densas.
Ahora entrenamos el modelo usando el conjunto de datos de entrenamiento y validación.
history = model.fit(X\_train, y\_train, epochs=10, batch\_size=32, validation\_split=0.2)
### 6. Evaluar el Modelo
Evaluamos el modelo en el conjunto de prueba.
test\_loss, test\_accuracy = model.evaluate(X\_test, y\_test)print(f'Precisión en el conjunto de prueba: {test\_accuracy:.4f}')
### 7. Hacer Predicciones
Finalmente, hacemos predicciones sobre nuevas muestras.
predictions = model.predict(X\_test)
\# Convertir a etiquetas predichas
predicted\_classes = predictions.argmax(axis=1)
\# Ejemplo de predicción en una sola imagen
import numpy as np
image\_index =0# Cambia el índice para ver otra imagenplt.imshow(X\_test\[image\_index].reshape(28,28), cmap='gray')plt.title(f'Predicción: {predicted\_classes\[image\_index]}')plt.show()
### 8. Visualizar el Rendimiento (Opcional)
Puedes visualizar la precisión y pérdida del modelo en cada época.
import matplotlib.pyplot as plt
\# Precisión
plt.plot(history.history\['accuracy'], label='Entrenamiento')plt.plot(history.history\['val\_accuracy'], label='Validación')plt.title('Precisión del modelo')plt.xlabel('Épocas')plt.ylabel('Precisión')plt.legend()plt.show()
\# Pérdida
plt.plot(history.history\['loss'], label='Entrenamiento')plt.plot(history.history\['val\_loss'], label='Validación')plt.title('Pérdida del modelo')plt.xlabel('Épocas')plt.ylabel('Pérdida')plt.legend()plt.show()
Estos pasos cubren todo el flujo de trabajo básico para crear, entrenar, evaluar y hacer predicciones con una red neuronal en TensorFlow y Keras.
No entiendo porque arranca con el mainProject empezado, siendo que es un archivo que no habíamos creado aun.