Aprendizaje profundo con Keras - Guía rápida

Deep Learning se ha convertido en una palabra de moda en los últimos días en el campo de la Inteligencia Artificial (IA). Durante muchos años, utilizamos el aprendizaje automático (ML) para impartir inteligencia a las máquinas. En los últimos días, el aprendizaje profundo se ha vuelto más popular debido a su supremacía en las predicciones en comparación con las técnicas tradicionales de ML.

El aprendizaje profundo esencialmente significa entrenar una red neuronal artificial (ANN) con una gran cantidad de datos. En el aprendizaje profundo, la red aprende por sí misma y, por lo tanto, requiere datos enormes para aprender. Si bien el aprendizaje automático tradicional es esencialmente un conjunto de algoritmos que analizan datos y aprenden de ellos. Luego utilizaron este aprendizaje para tomar decisiones inteligentes.

Ahora, llegando a Keras, es una API de redes neuronales de alto nivel que se ejecuta sobre TensorFlow, una plataforma de aprendizaje automático de código abierto de extremo a extremo. Con Keras, puede definir fácilmente arquitecturas ANN complejas para experimentar con sus macrodatos. Keras también es compatible con GPU, que se vuelve esencial para procesar una gran cantidad de datos y desarrollar modelos de aprendizaje automático.

En este tutorial, aprenderá el uso de Keras en la construcción de redes neuronales profundas. Veremos los ejemplos prácticos para la enseñanza. El problema en cuestión es reconocer dígitos escritos a mano utilizando una red neuronal entrenada con aprendizaje profundo.

Solo para entusiasmarlo más con el aprendizaje profundo, a continuación se muestra una captura de pantalla de las tendencias de Google sobre el aprendizaje profundo aquí:

Como puede ver en el diagrama, el interés en el aprendizaje profundo está creciendo constantemente durante los últimos años. Hay muchas áreas, como la visión por computadora, el procesamiento del lenguaje natural, el reconocimiento de voz, la bioinformática, el diseño de fármacos, etc., donde el aprendizaje profundo se ha aplicado con éxito. Este tutorial lo ayudará a comenzar rápidamente con el aprendizaje profundo.

¡Así que sigue leyendo!

Como se dijo en la introducción, el aprendizaje profundo es un proceso de entrenamiento de una red neuronal artificial con una gran cantidad de datos. Una vez entrenada, la red podrá darnos las predicciones sobre datos invisibles. Antes de continuar explicando qué es el aprendizaje profundo, repasemos rápidamente algunos términos utilizados en el entrenamiento de una red neuronal.

Redes neuronales

La idea de una red neuronal artificial se derivó de las redes neuronales de nuestro cerebro. Una red neuronal típica consta de tres capas: entrada, salida y capa oculta, como se muestra en la siguiente imagen.

Esto también se llama shallowred neuronal, ya que contiene solo una capa oculta. Agrega más capas ocultas en la arquitectura anterior para crear una arquitectura más compleja.

Redes profundas

El siguiente diagrama muestra una red profunda que consta de cuatro capas ocultas, una capa de entrada y una capa de salida.

A medida que se agrega la cantidad de capas ocultas a la red, su entrenamiento se vuelve más complejo en términos de recursos requeridos y el tiempo que lleva entrenar completamente la red.

Capacitación en red

Después de definir la arquitectura de la red, la entrena para realizar ciertos tipos de predicciones. Entrenar una red es un proceso para encontrar los pesos adecuados para cada enlace de la red. Durante el entrenamiento, los datos fluyen de las capas de entrada a salida a través de varias capas ocultas. Como los datos siempre se mueven en una dirección desde la entrada a la salida, llamamos a esta red como Red de avance y llamamos a la propagación de datos como Propagación hacia adelante.

Función de activación

En cada capa, calculamos la suma ponderada de entradas y la alimentamos a una función de activación. La función de activación aporta no linealidad a la red. Es simplemente una función matemática que discretiza la salida. Algunas de las funciones de activación más utilizadas son sigmoide, hiperbólica, tangente (tanh), ReLU y Softmax.

Retropropagación

La retropropagación es un algoritmo de aprendizaje supervisado. En Backpropagation, los errores se propagan hacia atrás desde la capa de salida a la de entrada. Dada una función de error, calculamos el gradiente de la función de error con respecto a los pesos asignados en cada conexión. El cálculo del gradiente avanza hacia atrás a través de la red. El gradiente de la capa final de pesos se calcula primero y el gradiente de la primera capa de pesos se calcula en último lugar.

En cada capa, los cálculos parciales del gradiente se reutilizan en el cálculo del gradiente para la capa anterior. Esto se llama Gradient Descent.

En este tutorial basado en proyectos, definirá una red neuronal profunda de retroalimentación y la entrenará con técnicas de retropropagación y descenso de gradientes. Afortunadamente, Keras nos proporciona todas las API de alto nivel para definir la arquitectura de red y entrenarla mediante el descenso de gradientes. A continuación, aprenderá cómo hacer esto en Keras.

Sistema de reconocimiento de dígitos escritos a mano

En este mini proyecto, aplicará las técnicas descritas anteriormente. Creará una red neuronal de aprendizaje profundo que se entrenará para reconocer dígitos escritos a mano. En cualquier proyecto de aprendizaje automático, el primer desafío es recopilar los datos. Especialmente, para las redes de aprendizaje profundo, necesita datos enormes. Afortunadamente, para el problema que estamos tratando de resolver, alguien ya ha creado un conjunto de datos para el entrenamiento. Esto se llama mnist, que está disponible como parte de las bibliotecas de Keras. El conjunto de datos consta de varias imágenes de 28x28 píxeles de dígitos escritos a mano. Entrenarás tu modelo en la mayor parte de este conjunto de datos y el resto de los datos se usarán para validar tu modelo entrenado.

Descripción del Proyecto

los mnistEl conjunto de datos consta de 70000 imágenes de dígitos escritos a mano. Aquí se reproducen algunas imágenes de muestra para su referencia

Cada imagen tiene un tamaño de 28 x 28 píxeles, lo que hace un total de 768 píxeles de varios niveles de escala de grises. La mayoría de los píxeles tienden hacia el tono negro, mientras que solo unos pocos están hacia el blanco. Pondremos la distribución de estos píxeles en una matriz o un vector. Por ejemplo, la distribución de píxeles para una imagen típica de dígitos 4 y 5 se muestra en la siguiente figura.

Cada imagen tiene un tamaño de 28 x 28 píxeles, lo que hace un total de 768 píxeles de varios niveles de escala de grises. La mayoría de los píxeles tienden hacia el tono negro, mientras que solo unos pocos están hacia el blanco. Pondremos la distribución de estos píxeles en una matriz o un vector. Por ejemplo, la distribución de píxeles para una imagen típica de dígitos 4 y 5 se muestra en la siguiente figura.

Claramente, se puede ver que la distribución de los píxeles (especialmente los que tienden al tono blanco) difieren, esto distingue los dígitos que representan. Alimentaremos esta distribución de 784 píxeles a nuestra red como entrada. La salida de la red constará de 10 categorías que representan un dígito entre 0 y 9.

Nuestra red constará de 4 capas: una capa de entrada, una capa de salida y dos capas ocultas. Cada capa oculta contendrá 512 nodos. Cada capa está completamente conectada a la siguiente. Cuando entrenemos la red, calcularemos los pesos para cada conexión. Entrenamos la red aplicando retropropagación y descenso de gradiente que discutimos anteriormente.

Con estos antecedentes, comencemos ahora a crear el proyecto.

Configuración del proyecto

Usaremos Jupyter mediante Anacondanavegador para nuestro proyecto. Como nuestro proyecto usa TensorFlow y Keras, deberá instalarlos en la configuración de Anaconda. Para instalar Tensorflow, ejecute el siguiente comando en la ventana de su consola:

>conda install -c anaconda tensorflow

Para instalar Keras, use el siguiente comando:

>conda install -c anaconda keras

Ahora está listo para iniciar Jupyter.

Iniciando Jupyter

Cuando inicie el navegador Anaconda, verá la siguiente pantalla de inicio.

Hacer clic ‘Jupyter’para empezar. La pantalla mostrará los proyectos existentes, si los hay, en su disco.

Iniciar un nuevo proyecto

Inicie un nuevo proyecto de Python 3 en Anaconda seleccionando la siguiente opción de menú:

File | New Notebook | Python 3

La captura de pantalla de la selección del menú se muestra para su referencia rápida:

Aparecerá un nuevo proyecto en blanco en su pantalla como se muestra a continuación:

Cambie el nombre del proyecto a DeepLearningDigitRecognition haciendo clic y editando en el nombre predeterminado “UntitledXX”.

Primero importamos las diversas bibliotecas requeridas por el código en nuestro proyecto.

Manejo y trazado de matrices

Como es típico, usamos numpy para el manejo de matrices y matplotlibpara trazar. Estas bibliotecas se importan en nuestro proyecto utilizando lo siguienteimport declaraciones

import numpy as np
import matplotlib
import matplotlib.pyplot as plot

Suprimir advertencias

Dado que tanto Tensorflow como Keras siguen revisando, si no sincroniza sus versiones apropiadas en el proyecto, en el tiempo de ejecución verá muchos errores de advertencia. Como distraen su atención del aprendizaje, suprimiremos todas las advertencias en este proyecto. Esto se hace con las siguientes líneas de código:

# silent all warnings
import os
os.environ['TF_CPP_MIN_LOG_LEVEL']='3'
import warnings
warnings.filterwarnings('ignore')
from tensorflow.python.util import deprecation
deprecation._PRINT_DEPRECATION_WARNINGS = False

Keras

Usamos bibliotecas de Keras para importar conjuntos de datos. Usaremos elmnistconjunto de datos para dígitos escritos a mano. Importamos el paquete requerido usando la siguiente declaración

from keras.datasets import mnist

Definiremos nuestra red neuronal de aprendizaje profundo utilizando paquetes de Keras. Importamos elSequential, Dense, Dropout y Activationpaquetes para definir la arquitectura de la red. Usamosload_modelpaquete para guardar y recuperar nuestro modelo. También usamosnp_utilspara algunas utilidades que necesitamos en nuestro proyecto. Estas importaciones se realizan con las siguientes declaraciones de programa:

from keras.models import Sequential, load_model
from keras.layers.core import Dense, Dropout, Activation
from keras.utils import np_utils

Cuando ejecute este código, verá un mensaje en la consola que dice que Keras usa TensorFlow en el backend. La captura de pantalla en esta etapa se muestra aquí:

Ahora, como tenemos todas las importaciones que requiere nuestro proyecto, procederemos a definir la arquitectura de nuestra red de Deep Learning.

Nuestro modelo de red neuronal constará de una pila lineal de capas. Para definir tal modelo, llamamos alSequential función -

model = Sequential()

Capa de entrada

Definimos la capa de entrada, que es la primera capa en nuestra red usando la siguiente declaración de programa:

model.add(Dense(512, input_shape=(784,)))

Esto crea una capa con 512 nodos (neuronas) con 784 nodos de entrada. Esto se muestra en la siguiente figura:

Tenga en cuenta que todos los nodos de entrada están completamente conectados a la Capa 1, es decir, cada nodo de entrada está conectado a los 512 nodos de la Capa 1.

A continuación, necesitamos agregar la función de activación para la salida de la Capa 1. Usaremos ReLU como nuestra activación. La función de activación se agrega usando la siguiente declaración de programa:

model.add(Activation('relu'))

A continuación, agregamos la deserción del 20% utilizando la siguiente declaración. La deserción es una técnica utilizada para evitar que el modelo se sobreajuste.

model.add(Dropout(0.2))

En este punto, nuestra capa de entrada está completamente definida. A continuación, agregaremos una capa oculta.

Capa oculta

Nuestra capa oculta constará de 512 nodos. La entrada a la capa oculta proviene de nuestra capa de entrada previamente definida. Todos los nodos están completamente conectados como en el caso anterior. La salida de la capa oculta irá a la siguiente capa en la red, que será nuestra capa final y de salida. Usaremos la misma activación de ReLU que para la capa anterior y un abandono del 20%. El código para agregar esta capa se proporciona aquí:

model.add(Dense(512))
model.add(Activation('relu'))
model.add(Dropout(0.2))

La red en esta etapa se puede visualizar de la siguiente manera:

A continuación, agregaremos la capa final a nuestra red, que es la capa de salida. Tenga en cuenta que puede agregar cualquier cantidad de capas ocultas usando un código similar al que ha usado aquí. Agregar más capas haría que la red fuera compleja para el entrenamiento; sin embargo, ofrece una clara ventaja de mejores resultados en muchos casos, aunque no en todos.

Capa de salida

La capa de salida consta de solo 10 nodos, ya que queremos clasificar las imágenes dadas en 10 dígitos distintos. Agregamos esta capa, usando la siguiente declaración:

model.add(Dense(10))

Como queremos clasificar la salida en 10 unidades distintas, usamos la activación softmax. En el caso de ReLU, la salida es binaria. Agregamos la activación usando la siguiente declaración:

model.add(Activation('softmax'))

En este punto, nuestra red se puede visualizar como se muestra en el siguiente diagrama:

En este punto, nuestro modelo de red está completamente definido en el software. Ejecute la celda de código y si no hay errores, recibirá un mensaje de confirmación en la pantalla como se muestra en la captura de pantalla a continuación:

A continuación, necesitamos compilar el modelo.

La compilación se realiza mediante una única llamada de método llamada compile.

model.compile(loss='categorical_crossentropy', metrics=['accuracy'], optimizer='adam')

los compileEl método requiere varios parámetros. El parámetro de pérdida se especifica para tener tipo'categorical_crossentropy'. El parámetro de métricas se establece en'accuracy' y finalmente usamos el adamoptimizador para entrenar la red. La salida en esta etapa se muestra a continuación:

Ahora, estamos listos para alimentar los datos a nuestra red.

Cargando datos

Como se dijo anteriormente, usaremos el mnistconjunto de datos proporcionado por Keras. Cuando cargamos los datos en nuestro sistema, los dividiremos en los datos de entrenamiento y de prueba. Los datos se cargan llamando alload_data método de la siguiente manera -

(X_train, y_train), (X_test, y_test) = mnist.load_data()

La salida en esta etapa se parece a la siguiente:

Ahora, aprenderemos la estructura del conjunto de datos cargado.

Los datos que se nos proporcionan son las imágenes gráficas de tamaño 28 x 28 píxeles, cada una de las cuales contiene un solo dígito entre 0 y 9. Mostraremos las diez primeras imágenes en la consola. El código para hacerlo se proporciona a continuación:

# printing first 10 images
for i in range(10):

plot.subplot(3,5,i+1)
plot.tight_layout()
plot.imshow(X_train[i], cmap='gray', interpolation='none')
plot.title("Digit: {}".format(y_train[i]))
plot.xticks([])
plot.yticks([])

En un ciclo iterativo de 10 recuentos, creamos una subtrama en cada iteración y mostramos una imagen de X_trainvector en él. Titulamos cada imagen del correspondientey_trainvector. Tenga en cuenta que ely_train El vector contiene los valores reales de la imagen correspondiente en X_trainvector. Eliminamos las marcas de los ejes xey llamando a los dos métodosxticks y ytickscon argumento nulo. Cuando ejecute el código, verá el siguiente resultado:

A continuación, prepararemos los datos para introducirlos en nuestra red.

Antes de que alimentemos los datos a nuestra red, deben convertirse al formato requerido por la red. A esto se le llama preparar datos para la red. Por lo general, consiste en convertir una entrada multidimensional en un vector unidimensional y normalizar los puntos de datos.

Vector de entrada de remodelación

Las imágenes de nuestro conjunto de datos constan de 28 x 28 píxeles. Esto debe convertirse en un vector unidimensional de tamaño 28 * 28 = 784 para alimentarlo en nuestra red. Lo hacemos llamando alreshape método en el vector.

X_train = X_train.reshape(60000, 784)
X_test = X_test.reshape(10000, 784)

Ahora, nuestro vector de entrenamiento constará de 60000 puntos de datos, cada uno de los cuales constará de un vector de una sola dimensión de tamaño 784. De manera similar, nuestro vector de prueba constará de 10000 puntos de datos de un vector de una sola dimensión de tamaño 784.

Normalizar datos

Los datos que contiene el vector de entrada tienen actualmente un valor discreto entre 0 y 255, los niveles de escala de grises. Normalizar estos valores de píxeles entre 0 y 1 ayuda a acelerar el entrenamiento. Como vamos a utilizar el descenso de gradiente estocástico, la normalización de los datos también ayudará a reducir la posibilidad de quedarse atascado en los óptimos locales.

Para normalizar los datos, los representamos como tipo flotante y los dividimos por 255 como se muestra en el siguiente fragmento de código:

X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train /= 255
X_test /= 255

Veamos ahora cómo se ven los datos normalizados.

Examinar datos normalizados

Para ver los datos normalizados, llamaremos a la función de histograma como se muestra aquí:

plot.hist(X_train[0])
plot.title("Digit: {}".format(y_train[0]))

Aquí, trazamos el histograma del primer elemento del X_trainvector. También imprimimos el dígito representado por este punto de datos. El resultado de ejecutar el código anterior se muestra aquí:

Notará una gran densidad de puntos que tienen un valor cercano a cero. Estos son los puntos negros de la imagen, que obviamente son la mayor parte de la imagen. El resto de los puntos de la escala de grises, que están cerca del color blanco, representan el dígito. Puede consultar la distribución de píxeles para otro dígito. El siguiente código imprime el histograma de un dígito en el índice 2 en el conjunto de datos de entrenamiento.

plot.hist(X_train[2])
plot.title("Digit: {}".format(y_train[2])

El resultado de ejecutar el código anterior se muestra a continuación:

Al comparar las dos cifras anteriores, notará que la distribución de los píxeles blancos en dos imágenes difiere, lo que indica una representación de un dígito diferente: "5" y "4" en las dos imágenes anteriores.

A continuación, examinaremos la distribución de datos en nuestro conjunto de datos de entrenamiento completo.

Examinar la distribución de datos

Antes de entrenar nuestro modelo de aprendizaje automático en nuestro conjunto de datos, debemos conocer la distribución de dígitos únicos en nuestro conjunto de datos. Nuestras imágenes representan 10 dígitos distintos que van del 0 al 9. Nos gustaría saber el número de dígitos 0, 1, etc., en nuestro conjunto de datos. Podemos obtener esta información utilizando elunique método de Numpy.

Utilice el siguiente comando para imprimir el número de valores únicos y el número de ocurrencias de cada uno

print(np.unique(y_train, return_counts=True))

Cuando ejecute el comando anterior, verá el siguiente resultado:

(array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9], dtype=uint8), array([5923, 6742, 5958, 6131, 5842, 5421, 5918, 6265, 5851, 5949]))

Muestra que hay 10 valores distintos, del 0 al 9. Hay 5923 ocurrencias del dígito 0, 6742 ocurrencias del dígito 1, y así sucesivamente. La captura de pantalla de la salida se muestra aquí:

Como paso final en la preparación de datos, necesitamos codificar nuestros datos.

Codificación de datos

Tenemos diez categorías en nuestro conjunto de datos. Por lo tanto, codificaremos nuestra salida en estas diez categorías mediante la codificación one-hot. Usamos el método to_categorial de las utilidades de Numpy para realizar la codificación. Después de codificar los datos de salida, cada punto de datos se convertiría en un vector unidimensional de tamaño 10. Por ejemplo, el dígito 5 ahora se representará como [0,0,0,0,0,1,0,0,0 , 0].

Codifique los datos utilizando el siguiente fragmento de código:

n_classes = 10
Y_train = np_utils.to_categorical(y_train, n_classes)

Puede comprobar el resultado de la codificación imprimiendo los primeros 5 elementos del vector Y_train categorizado.

Utilice el siguiente código para imprimir los primeros 5 vectores:

for i in range(5):
   print (Y_train[i])

Verá la siguiente salida:

[0. 0. 0. 0. 0. 1. 0. 0. 0. 0.]
[1. 0. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 1. 0. 0. 0. 0. 0.]
[0. 1. 0. 0. 0. 0. 0. 0. 0. 0.]
[0. 0. 0. 0. 0. 0. 0. 0. 0. 1.]

El primer elemento representa el dígito 5, el segundo representa el dígito 0 y así sucesivamente.

Finalmente, también tendrá que categorizar los datos de prueba, lo cual se hace usando la siguiente declaración:

Y_test = np_utils.to_categorical(y_test, n_classes)

En esta etapa, sus datos están completamente preparados para ingresar a la red.

A continuación, viene la parte más importante y es entrenar nuestro modelo de red.

El entrenamiento del modelo se realiza en una única llamada de método llamada ajuste que toma pocos parámetros como se ve en el código a continuación:

history = model.fit(X_train, Y_train,
   batch_size=128, epochs=20,
   verbose=2,
   validation_data=(X_test, Y_test)))

Los dos primeros parámetros del método de ajuste especifican las características y la salida del conjunto de datos de entrenamiento.

los epochsestá establecido en 20; asumimos que el entrenamiento convergerá en un máximo de 20 épocas: las iteraciones. El modelo entrenado se valida en los datos de prueba como se especifica en el último parámetro.

La salida parcial de ejecutar el comando anterior se muestra aquí:

Train on 60000 samples, validate on 10000 samples
Epoch 1/20
- 9s - loss: 0.2488 - acc: 0.9252 - val_loss: 0.1059 - val_acc: 0.9665
Epoch 2/20
- 9s - loss: 0.1004 - acc: 0.9688 - val_loss: 0.0850 - val_acc: 0.9715
Epoch 3/20
- 9s - loss: 0.0723 - acc: 0.9773 - val_loss: 0.0717 - val_acc: 0.9765
Epoch 4/20
- 9s - loss: 0.0532 - acc: 0.9826 - val_loss: 0.0665 - val_acc: 0.9795
Epoch 5/20
- 9s - loss: 0.0457 - acc: 0.9856 - val_loss: 0.0695 - val_acc: 0.9792

La captura de pantalla de la salida se muestra a continuación para su referencia rápida:

Ahora, a medida que el modelo se entrena con nuestros datos de entrenamiento, evaluaremos su rendimiento.

Para evaluar el desempeño del modelo, llamamos evaluate método de la siguiente manera -

loss_and_metrics = model.evaluate(X_test, Y_test, verbose=2)

Para evaluar el desempeño del modelo, llamamos evaluate método de la siguiente manera -

loss_and_metrics = model.evaluate(X_test, Y_test, verbose=2)

Imprimiremos la pérdida y la precisión utilizando las siguientes dos declaraciones:

print("Test Loss", loss_and_metrics[0])
print("Test Accuracy", loss_and_metrics[1])

Cuando ejecute las declaraciones anteriores, verá el siguiente resultado:

Test Loss 0.08041584826191042
Test Accuracy 0.9837

Esto muestra una precisión de prueba del 98%, que debería ser aceptable para nosotros. Lo que significa para nosotros que en el 2% de los casos, los dígitos escritos a mano no se clasificarían correctamente. También trazaremos métricas de precisión y pérdida para ver cómo funciona el modelo en los datos de prueba.

Trazado de métricas de precisión

Usamos el grabado historydurante nuestro entrenamiento para obtener un gráfico de métricas de precisión. El siguiente código trazará la precisión en cada época. Recogemos la precisión de los datos de entrenamiento ("acc") y la precisión de los datos de validación ("val_acc") para el trazado.

plot.subplot(2,1,1)
plot.plot(history.history['acc'])
plot.plot(history.history['val_acc'])
plot.title('model accuracy')
plot.ylabel('accuracy')
plot.xlabel('epoch')
plot.legend(['train', 'test'], loc='lower right')

La gráfica de salida se muestra a continuación:

Como puede ver en el diagrama, la precisión aumenta rápidamente en las dos primeras épocas, lo que indica que la red está aprendiendo rápido. Posteriormente, la curva se aplana, lo que indica que no se requieren demasiadas épocas para entrenar más el modelo. Por lo general, si la precisión de los datos de entrenamiento ("acc") sigue mejorando mientras que la precisión de los datos de validación ("val_acc") empeora, se está produciendo un sobreajuste. Indica que el modelo está empezando a memorizar los datos.

También trazaremos las métricas de pérdida para verificar el desempeño de nuestro modelo.

Trazado de métricas de pérdida

Nuevamente, graficamos la pérdida en los datos de entrenamiento ("pérdida") y de prueba ("val_loss"). Esto se hace usando el siguiente código:

plot.subplot(2,1,2)
plot.plot(history.history['loss'])
plot.plot(history.history['val_loss'])
plot.title('model loss')
plot.ylabel('loss')
plot.xlabel('epoch')
plot.legend(['train', 'test'], loc='upper right')

La salida de este código se muestra a continuación:

Como puede ver en el diagrama, la pérdida en el conjunto de entrenamiento disminuye rápidamente durante las dos primeras épocas. Para el conjunto de prueba, la pérdida no disminuye al mismo ritmo que el conjunto de entrenamiento, pero permanece casi plana durante múltiples épocas. Esto significa que nuestro modelo se está generalizando bien para datos invisibles.

Ahora, usaremos nuestro modelo entrenado para predecir los dígitos en nuestros datos de prueba.

Predecir los dígitos en un dato invisible es muy fácil. Simplemente necesita llamar alpredict_classes método del model pasándolo a un vector que consta de puntos de datos desconocidos.

predictions = model.predict_classes(X_test)

La llamada al método devuelve las predicciones en un vector que puede probarse para ceros y unos contra los valores reales. Esto se hace usando las siguientes dos declaraciones:

correct_predictions = np.nonzero(predictions == y_test)[0]
incorrect_predictions = np.nonzero(predictions != y_test)[0]

Finalmente, imprimiremos el recuento de predicciones correctas e incorrectas utilizando las siguientes dos declaraciones de programa:

print(len(correct_predictions)," classified correctly")
print(len(incorrect_predictions)," classified incorrectly")

Cuando ejecute el código, obtendrá el siguiente resultado:

9837 classified correctly
163 classified incorrectly

Ahora, como ha entrenado satisfactoriamente el modelo, lo guardaremos para uso futuro.

Guardaremos el modelo entrenado en nuestra unidad local en la carpeta de modelos en nuestro directorio de trabajo actual. Para guardar el modelo, ejecute el siguiente código:

directory = "./models/"
name = 'handwrittendigitrecognition.h5'
path = os.path.join(save_dir, name)
model.save(path)
print('Saved trained model at %s ' % path)

La salida después de ejecutar el código se muestra a continuación:

Ahora, como ha guardado un modelo entrenado, puede usarlo más adelante para procesar sus datos desconocidos.

Para predecir los datos no vistos, primero debe cargar el modelo entrenado en la memoria. Esto se hace usando el siguiente comando:

model = load_model ('./models/handwrittendigitrecognition.h5')

Tenga en cuenta que simplemente estamos cargando el archivo .h5 en la memoria. Esto configura toda la red neuronal en la memoria junto con los pesos asignados a cada capa.

Ahora, para hacer sus predicciones sobre datos no vistos, cargue los datos, que sean uno o más elementos, en la memoria. Procese previamente los datos para cumplir con los requisitos de entrada de nuestro modelo como lo hizo en sus datos de entrenamiento y prueba anteriores. Después del preprocesamiento, envíelo a su red. El modelo generará su predicción.

Keras proporciona una API de alto nivel para crear una red neuronal profunda. En este tutorial, aprendió a crear una red neuronal profunda que fue entrenada para encontrar los dígitos en texto escrito a mano. Se creó una red de múltiples capas para este propósito. Keras le permite definir una función de activación de su elección en cada capa. Utilizando el descenso de gradiente, la red se entrenó con los datos de entrenamiento. La precisión de la red entrenada para predecir los datos invisibles se probó en los datos de prueba. Aprendió a trazar las métricas de precisión y error. Una vez que la red está completamente capacitada, guardó el modelo de red para uso futuro.