Reconocimiento de imágenes en Python con TensorFlow y Keras

R

Introducción

Una de las utilizaciones más comunes de TensorFlow y Keras es el reconocimiento / clasificación de imágenes. Si quieres aprender a usar Keras para clasificar o reconocer imágenes, este artículo te enseñará cómo.

Definiciones

Si no tiene claros los conceptos básicos detrás del reconocimiento de imágenes, será difícil comprender completamente el resto de este artículo. Entonces, antes de continuar, tomemos un momento para definir algunos términos.

TensorFlow/Keras

Crédito: commons.wikimedia.org

TensorFlow es una biblioteca de código abierto creada para Python por el equipo de Google Brain. TensorFlow compila muchos algoritmos y modelos diferentes juntos, lo que permite al usuario implementar redes neuronales profundas para su uso en tareas como el reconocimiento / clasificación de imágenes y el procesamiento del lenguaje natural. TensorFlow es un marco poderoso que funciona mediante la implementación de una serie de nodes de procesamiento, cada node representa una operación matemática, y la serie completa de nodes se denomina “gráfico”.

En términos de Keras , es una API de alto nivel (interfaz de programación de aplicaciones) que puede usar las funciones de TensorFlow debajo (así como otras bibliotecas ML como Theano). Keras fue diseñado con la facilidad de uso y la modularidad como principios rectores. En términos prácticos, Keras hace que la implementación de las muchas funciones poderosas pero a menudo complejas de TensorFlow sea lo más simple posible, y está configurado para funcionar con Python sin modificaciones o configuraciones importantes.

Reconocimiento de imágenes (clasificación)

El reconocimiento de imágenes se refiere a la tarea de ingresar una imagen en una red neuronal y hacer que genere algún tipo de etiqueta para esa imagen. La etiqueta que genera la red corresponderá a una clase predefinida. Puede haber varias clases con las que se puede etiquetar la imagen, o solo una. Si hay una sola clase, a menudo se aplica el término “reconocimiento”, mientras que una tarea de reconocimiento de varias clases se suele denominar “clasificación”.

Un subconjunto de la clasificación de imágenes es la detección de objetos, donde se identifican instancias específicas de objetos como pertenecientes a una determinada clase, como animales, automóviles o personas.

Extracción de características

Para llevar a cabo el reconocimiento / clasificación de imágenes, la red neuronal debe realizar la extracción de características . Las características son los elementos de los datos que le interesan y que serán alimentados a través de la red. En el caso específico del reconocimiento de imágenes, las características son los grupos de píxeles, como bordes y puntos, de un objeto que la red analizará en busca de patrones.

El reconocimiento de características (o extracción de características) es el proceso de extraer las características relevantes de una imagen de entrada para que estas características puedan analizarse. Muchas imágenes contienen anotaciones o metadatos sobre la imagen que ayudan a la red a encontrar las características relevantes.

Cómo las redes neuronales aprenden a reconocer imágenes

Tener una intuición de cómo una red neuronal reconoce imágenes le ayudará cuando esté implementando un modelo de red neuronal, así que exploremos brevemente el proceso de reconocimiento de imágenes en las siguientes secciones.

Extracción de funciones con filtros

Crédito: commons.wikimedia.org

La primera capa de una red neuronal incluye todos los píxeles de una imagen. Una vez que todos los datos se han introducido en la red, se aplican diferentes filtros a la imagen, que forma representaciones de diferentes partes de la imagen. Esta es la extracción de características y crea “mapas de características”.

Este proceso de extraer características de una imagen se logra con una “capa convolucional”, y la convolución consiste simplemente en formar una representación de parte de una imagen. Es a partir de este concepto de convolución que obtenemos el término Red neuronal convolucional (CNN), el tipo de red neuronal más comúnmente utilizada en la clasificación / reconocimiento de imágenes.

Si desea visualizar cómo funciona la creación de mapas de características, piense en encender una linterna sobre una imagen en una habitación oscura. A medida que desliza el rayo sobre la imagen, aprende sobre las características de la imagen. Un filtro es lo que usa la red para formar una representación de la imagen, y en esta metáfora, la luz de la linterna es el filtro.

El ancho del haz de tu linterna controla la cantidad de imagen que examinas a la vez, y las redes neuronales tienen un parámetro similar, el tamaño del filtro. El tamaño del filtro afecta la cantidad de imagen y la cantidad de píxeles que se examinan a la vez. Un tamaño de filtro común utilizado en las CNN es 3, y esto cubre tanto el alto como el ancho, por lo que el filtro examina un área de píxeles de 3 x 3.

Crédito: commons.wikimedia.org

Si bien el tamaño del filtro cubre la altura y el ancho del filtro, también se debe especificar la profundidad del filtro.

¿Cómo tiene profundidad una imagen 2D?

Las imágenes digitales se representan como alto, ancho y algún valor RGB que define los colores del píxel, por lo que la “profundidad” que se está rastreando es el número de canales de color que tiene la imagen. Las imágenes en escala de grises (sin color) solo tienen 1 canal de color, mientras que las imágenes en color tienen 3 canales de profundidad.

Todo esto significa que para un filtro de tamaño 3 aplicado a una imagen a todo color, las dimensiones de ese filtro serán 3 x 3 x 3. Por cada píxel cubierto por ese filtro, la red multiplica los valores del filtro con los valores en los propios píxeles para obtener una representación numérica de ese píxel. Este proceso se realiza luego para que toda la imagen logre una representación completa. El filtro se mueve por el resto de la imagen de acuerdo con un parámetro llamado “zancada”, que define cuántos píxeles se moverá el filtro después de calcular el valor en su posición actual. Un tamaño de zancada convencional para una CNN es 2.

El resultado final de todo este cálculo es un mapa de características. Este proceso generalmente se realiza con más de un filtro, lo que ayuda a preservar la complejidad de la imagen.

Funciones de activación

Una vez que se ha creado el mapa de características de la imagen, los valores que representan la imagen se pasan a través de una función de activación o capa de activación. La función de activación toma valores que representan la imagen, que están en forma lineal (es decir, solo una lista de números) gracias a la capa convolucional, y aumenta su no linealidad ya que las imágenes en sí mismas no son lineales.

La función de activación típica que se usa para lograr esto es una Unidad Lineal Rectificada (ReLU), aunque hay algunas otras funciones de activación que se usan ocasionalmente (puede leer sobre ellas aquí ).

Capas de agrupación

Una vez que se activan los datos, se envían a través de una capa de agrupación . La agrupación “reduce la resolución” de una imagen, lo que significa que toma la información que representa la imagen y la comprime, haciéndola más pequeña. El proceso de agrupación hace que la red sea más flexible y más hábil para reconocer objetos / imágenes en función de las características relevantes.

Cuando miramos una imagen, normalmente no nos preocupamos por toda la información del fondo de la imagen, solo por las características que nos interesan, como las personas o los animales.

De manera similar, una capa de agrupación en una CNN abstraerá las partes innecesarias de la imagen, manteniendo solo las partes de la imagen que cree que son relevantes, controladas por el tamaño especificado de la capa de agrupación.

Debido a que tiene que tomar decisiones sobre las partes más relevantes de la imagen, la esperanza es que la red aprenda solo las partes de la imagen que realmente representan el objeto en cuestión. Esto ayuda a prevenir el sobreajuste , donde la red aprende aspectos del caso de entrenamiento demasiado bien y no puede generalizar a nuevos datos.

Crédito: commons.wikimedia.org

Hay varias formas de agrupar valores, pero la agrupación máxima es la más utilizada. La agrupación máxima obtiene el valor máximo de los píxeles dentro de un solo filtro (dentro de un solo punto en la imagen). Esto reduce 3/4 de la información, suponiendo que se estén utilizando filtros de 2 x 2.

Los valores máximos de los píxeles se utilizan para tener en cuenta las posibles distorsiones de la imagen, y los parámetros / tamaño de la imagen se reducen para controlar el sobreajuste. Hay otros tipos de agrupación, como la agrupación promedio o la agrupación de suma, pero no se utilizan con tanta frecuencia porque la agrupación máxima tiende a producir una mejor precisión.

Aplastamiento

Las capas finales de nuestra CNN, las capas densamente conectadas, requieren que los datos estén en forma de vector para ser procesados. Por esta razón, los datos deben “aplanarse”. Los valores se comprimen en un vector largo o una columna de números ordenados secuencialmente.

Capa completamente conectada

Las capas finales de la CNN son capas densamente conectadas o una red neuronal artificial (ANN). La función principal de la ANN es analizar las características de entrada y combinarlas en diferentes atributos que ayudarán en la clasificación. Estas capas están formando esencialmente colecciones de neuronas que representan diferentes partes del objeto en cuestión, y una colección de neuronas puede representar las orejas flácidas de un perro o el enrojecimiento de una manzana. Cuando se activen suficientes de estas neuronas en respuesta a una imagen de entrada, la imagen se clasificará como un objeto.

Crédito: commons.wikimedia.org

El error, o la diferencia entre los valores calculados y el valor esperado en el conjunto de entrenamiento, es calculado por la ANN. Luego, la red sufre una retropropagación , donde se calcula la influencia de una neurona determinada en una neurona en la siguiente capa y se ajusta su influencia. Esto se hace para optimizar el rendimiento del modelo. Este proceso se repite una y otra vez. Así es como la red se entrena con datos y aprende asociaciones entre características de entrada y clases de salida.

Las neuronas en las capas intermedias completamente conectadas generarán valores binarios relacionados con las posibles clases. Si tiene cuatro clases diferentes (digamos un perro, un automóvil, una casa y una persona), la neurona tendrá un valor “1” para la clase que cree que representa la imagen y un valor “0” para las otras clases. .

La capa final completamente conectada recibirá la salida de la capa anterior y entregará una probabilidad para cada una de las clases, sumando una. Si hay un valor de 0,75 en la categoría “perro”, representa un 75% de certeza de que la imagen es un perro.

El clasificador de imágenes ahora ha sido entrenado y las imágenes se pueden pasar a la CNN, que ahora generará una suposición sobre el contenido de esa imagen.

El flujo de trabajo de Machine Learning

Antes de pasar a un ejemplo de entrenamiento de un clasificador de imágenes, tomemos un momento para comprender el flujo de trabajo o la canalización del Machine Learning. El proceso para entrenar un modelo de red neuronal es bastante estándar y se puede dividir en cuatro fases diferentes.

Preparación de datos

Primero, deberá recopilar sus datos y ponerlos en una forma en la que la red pueda entrenar. Esto implica recopilar imágenes y etiquetarlas. Incluso si ha descargado un conjunto de datos que otra persona ha preparado, es probable que deba realizar un procesamiento previo o una preparación antes de poder usarlo para la capacitación. La preparación de datos es un arte en sí mismo, que implica lidiar con cosas como valores perdidos, datos corruptos, datos en el formato incorrecto, etiquetas incorrectas, etc.

En este artículo, utilizaremos un conjunto de datos preprocesados.

Creando el modelo

La creación del modelo de red neuronal implica tomar decisiones sobre varios parámetros e hiperparámetros. Debe tomar decisiones sobre la cantidad de capas que usará en su modelo, cuáles serán los tamaños de entrada y salida de las capas, qué tipo de funciones de activación usará, si usará o no la deserción, etc.

Aprender qué parámetros e hiperparámetros usar vendrá con el tiempo (y mucho estudio), pero desde el principio hay algunas heurísticas que puede usar para comenzar a ejecutar y cubriremos algunas de ellas durante el ejemplo de implementación.

Entrenando el modelo

Una vez que haya creado su modelo, simplemente cree una instancia del modelo y ajústela con sus datos de entrenamiento. La mayor consideración al entrenar un modelo es la cantidad de tiempo que tarda en entrenarse. Puede especificar la duración del entrenamiento para una red especificando el número de épocas para entrenar. Cuanto más entrenes a un modelo, más mejorará su rendimiento, pero si pasa demasiadas épocas de entrenamiento corre el riesgo de sobreajuste.

Elegir el número de épocas para las que entrenar es algo que comprenderá, y es habitual guardar los pesos de una red entre sesiones de entrenamiento para que no tenga que empezar de nuevo una vez que haya progresado un poco en el entrenamiento de la red.

Evaluación del modelo

Hay varios pasos para evaluar el modelo. El primer paso para evaluar el modelo es comparar el rendimiento del modelo con un conjunto de datos de validación , un conjunto de datos en el que el modelo no ha sido entrenado. Comparará el rendimiento del modelo con este conjunto de validación y analizará su rendimiento a través de diferentes métricas.

Existen varias métricas para determinar el rendimiento de un modelo de red neuronal, pero la métrica más común es la “precisión”, la cantidad de imágenes clasificadas correctamente dividida por la cantidad total de imágenes en su conjunto de datos.

Una vez que haya visto la precisión del rendimiento del modelo en un conjunto de datos de validación, normalmente volverá y entrenará la red nuevamente utilizando parámetros ligeramente modificados, porque es poco probable que esté satisfecho con el rendimiento de su red la primera vez que entrena. Seguirá ajustando los parámetros de su red, reentrenándola y midiendo su rendimiento hasta que esté satisfecho con la precisión de la red.

Finalmente, probará el rendimiento de la red en un conjunto de pruebas. Este conjunto de pruebas es otro conjunto de datos que su modelo nunca ha visto antes.

Quizás te estés preguntando:

¿Por qué molestarse con el equipo de prueba? Si se está haciendo una idea de la precisión de su modelo, ¿no es ese el propósito del conjunto de validación?

Es una buena idea mantener un lote de datos que la red nunca ha visto para probar porque todos los ajustes de los parámetros que hace, combinados con la repetición de la prueba en el conjunto de validación, podrían significar que su red ha aprendido algunas idiosincrasias del conjunto de validación que no se generalizará a datos fuera de la muestra.

Por lo tanto, el propósito del conjunto de pruebas es verificar problemas como el sobreajuste y estar más seguro de que su modelo es realmente apto para funcionar en el mundo real.

Reconocimiento de imágenes con una CNN

Hemos cubierto mucho hasta ahora, y si toda esta información ha sido un poco abrumadora, ver estos conceptos reunidos en un clasificador de muestra entrenado en un conjunto de datos debería hacer que estos conceptos sean más concretos. Así que veamos un ejemplo completo de reconocimiento de imágenes con Keras, desde la carga de los datos hasta la evaluación.

Crédito: www.cs.toronto.edu

Para empezar, necesitaremos un conjunto de datos para entrenar. En este ejemplo, usaremos el famoso conjunto de datos CIFAR-10 . CIFAR-10 es un gran conjunto de datos de imágenes que contiene más de 60.000 imágenes que representan 10 clases diferentes de objetos como gatos, aviones y automóviles.

Las imágenes son RGB a todo color, pero son bastante pequeñas, solo 32 x 32. Una gran cosa sobre el conjunto de datos CIFAR-10 es que viene empaquetado con Keras, por lo que es muy fácil cargar el conjunto de datos y las imágenes necesitan muy poco preprocesamiento.

Lo primero que debemos hacer es importar las bibliotecas necesarias. Mostraré cómo se usan estas importaciones a medida que avanzamos, pero por ahora sepan que usaremos Numpy y varios módulos asociados con Keras:

import numpy
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten, BatchNormalization, Activation
from keras.layers.convolutional import Conv2D, MaxPooling2D
from keras.constraints import maxnorm
from keras.utils import np_utils

Vamos a utilizar una semilla aleatoria aquí para que usted pueda replicar los resultados logrados en este artículo, por lo que necesitamos numpy:

# Set random seed for purposes of reproducibility
seed = 21

Preparando los datos

Necesitamos una importación más: el conjunto de datos.

from keras.datasets import cifar10

Ahora carguemos el conjunto de datos. Podemos hacerlo simplemente especificando en qué variables queremos cargar los datos y luego usando la load_data()función:

# loading in the data
     
(X_train, y_train), (X_test, y_test) = cifar10.load_data()

En la mayoría de los casos, necesitará realizar un procesamiento previo de sus datos para que estén listos para su uso, pero como estamos usando un conjunto de datos preempaquetados, es necesario realizar muy poco procesamiento previo. Una cosa que queremos hacer es normalizar los datos de entrada.

Si los valores de los datos de entrada están en un rango demasiado amplio, puede afectar negativamente al rendimiento de la red. En este caso, los valores de entrada son los píxeles de la imagen, que tienen un valor entre 0 y 255.

Entonces, para normalizar los datos, simplemente podemos dividir los valores de la imagen por 255. Para hacer esto, primero necesitamos hacer que los datos sean de tipo flotante, ya que actualmente son números enteros. Podemos hacer esto usando el astype()comando Numpy y luego declarando qué tipo de datos queremos:

# normalize the inputs from 0-255 to between 0 and 1 by dividing by 255
    
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train = X_train / 255.0
X_test = X_test / 255.0

Otra cosa que tendremos que hacer para que los datos estén listos para la red es codificar los valores en un solo uso. No entraré en los detalles de la codificación one-hot aquí, pero por ahora sepa que las imágenes no pueden ser utilizadas por la red como están, primero deben codificarse y la codificación one-hot se usa mejor al hacer clasificación binaria.

Realmente estamos haciendo una clasificación binaria aquí porque una imagen pertenece a una clase o no, no puede caer en algún punto intermedio. El comando Numpy to_categorical()se usa para codificar en caliente. Es por eso que importamos la np_utilsfunción de Keras, ya que contiene to_categorical().

También necesitamos especificar la cantidad de clases que hay en el conjunto de datos, de modo que sepamos cuántas neuronas comprimir la capa final:

# one hot encode outputs
y_train = np_utils.to_categorical(y_train)
y_test = np_utils.to_categorical(y_test)
class_num = y_test.shape[1]

Diseñando el modelo

Llegamos a la etapa en la que diseñamos el modelo de CNN. Lo primero que debemos hacer es definir el formato que nos gustaría usar para el modelo, Keras tiene varios formatos o planos diferentes sobre los que construir modelos, pero Sequentiales el más utilizado, y por eso lo hemos importado de Keras.

Crea el modelo

model = Sequential()

La primera capa de nuestro modelo es una capa convolucional. Tomará las entradas y ejecutará filtros convolucionales en ellas.

Al implementar estos en Keras, tenemos que especificar el número de canales / filtros que queremos (que son los 32 a continuación), el tamaño del filtro que queremos (3 x 3 en este caso), la forma de entrada (al crear la primera capa ) y la activación y el relleno que necesitamos.

Como se mencionó, relues la activación más común y padding='same'solo significa que no estamos cambiando el tamaño de la imagen en absoluto:

model.add(Conv2D(32, (3, 3), input_shape=X_train.shape[1:], padding='same'))
model.add(Activation('relu'))

Nota : También puede encadenar las activaciones y agrupaciones, así:

model.add(Conv2D(32, (3, 3), input_shape=(3, 32, 32), activation='relu', padding='same'))

Ahora haremos una capa de deserción para evitar el sobreajuste, que funciona eliminando aleatoriamente algunas de las conexiones entre las capas (0.2 significa que elimina el 20% de las conexiones existentes):

model.add(Dropout(0.2))

Es posible que también queramos hacer una normalización por lotes aquí. La normalización por lotes normaliza las entradas que se dirigen a la siguiente capa, asegurando que la red siempre cree activaciones con la misma distribución que deseamos:

model.add(BatchNormalization())

Ahora viene otra capa convolucional, pero el tamaño del filtro aumenta para que la red pueda aprender representaciones más complejas:

model.add(Conv2D(64, (3, 3), padding='same'))
model.add(Activation('relu'))

Aquí está la capa de agrupación, como se discutió anteriormente, esto ayuda a que el clasificador de imágenes sea más robusto para que pueda aprender patrones relevantes. También está la deserción y la normalización por lotes:

model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.2))
model.add(BatchNormalization())

Ese es el flujo básico para la primera mitad de una implementación de CNN: convolucional, activación, abandono, agrupación. Ahora puede ver por qué hemos importado Dropout, BatchNormalization, Activation, Conv2d, y MaxPooling2d.

Puede variar el número exacto de capas convolucionales que tiene a su gusto, aunque cada una agrega más gastos de cálculo. Tenga en cuenta que a medida que agrega capas convolucionales, generalmente aumenta su número de filtros para que el modelo pueda aprender representaciones más complejas. Si los números elegidos para estas capas parecen algo arbitrarios, solo sepa que, en general, aumenta los filtros a medida que avanza y se recomienda convertirlos en potencias de 2, lo que puede otorgar un ligero beneficio al entrenar en una GPU.

Es importante no tener demasiadas capas de agrupación, ya que cada agrupación descarta algunos datos. La agrupación con demasiada frecuencia hará que las capas densamente conectadas no tengan casi nada de lo que aprender cuando los datos lleguen a ellas.

El número exacto de capas de agrupación que debe usar variará según la tarea que esté realizando, y es algo que obtendrá una sensación con el tiempo. Dado que las imágenes aquí ya son tan pequeñas, no agruparemos más de dos veces.

Ahora puede repetir estas capas para darle a su red más representaciones para trabajar:

model.add(Conv2D(64, (3, 3), padding='same'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.2))
model.add(BatchNormalization())
    
model.add(Conv2D(128, (3, 3), padding='same'))
model.add(Activation('relu'))
model.add(Dropout(0.2))
model.add(BatchNormalization())

Una vez que hayamos terminado con las capas convolucionales, necesitamos Flattenlos datos, por lo que importamos la función anterior. También agregaremos una capa de abandono nuevamente:

model.add(Flatten())
model.add(Dropout(0.2))

Ahora hacemos uso de la Denseimportación y creamos la primera capa densamente conectada. Necesitamos especificar el número de neuronas en la capa densa. Tenga en cuenta que el número de neuronas en las capas sucesivas disminuye, acercándose finalmente al mismo número de neuronas que clases hay en el conjunto de datos (en este caso, 10). La restricción del kernel puede regularizar los datos a medida que aprenden, otra cosa que ayuda a prevenir el sobreajuste. Es por eso que importamos maxnormantes.

model.add(Dense(256, kernel_constraint=maxnorm(3)))
model.add(Activation('relu'))
model.add(Dropout(0.2))
model.add(BatchNormalization())
    
model.add(Dense(128, kernel_constraint=maxnorm(3)))
model.add(Activation('relu'))
model.add(Dropout(0.2))
model.add(BatchNormalization())

En esta última capa, pasamos el número de clases por el número de neuronas. Cada neurona representa una clase, y la salida de esta capa será un vector de 10 neuronas con cada neurona almacenando alguna probabilidad de que la imagen en cuestión pertenezca a la clase que representa.

Finalmente, la softmaxfunción de activación selecciona la neurona con mayor probabilidad como salida, votando que la imagen pertenece a esa clase:

model.add(Dense(class_num))
model.add(Activation('softmax'))

Ahora que hemos diseñado el modelo que queremos usar, solo tenemos que compilarlo. Especifiquemos el número de épocas para las que queremos entrenar, así como el optimizador que queremos usar.

El optimizador es lo que ajustará los pesos en su red para acercarse al punto de menor pérdida. El Adamalgoritmo es uno de los optimizadores más utilizados porque ofrece un gran rendimiento en la mayoría de los problemas:

epochs = 25
optimizer="adam"

Ahora compilemos el modelo con nuestros parámetros elegidos. También especifiquemos una métrica para usar.

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

Podemos imprimir el resumen del modelo para ver cómo se ve todo el modelo.

print(model.summary())

Imprimir el resumen nos dará bastante información:

Results:
                
Layer (type) Output Shape Param #
=================================================================
conv2d_1 (Conv2D) (None, 32, 32, 32) 896
_________________________________________________________________
activation_1 (Activation) (None, 32, 32, 32) 0
_________________________________________________________________
dropout_1 (Dropout) (None, 32, 32, 32) 0
_________________________________________________________________
batch_normalization_1 (Batch (None, 32, 32, 32) 128
_________________________________________________________________
conv2d_2 (Conv2D) (None, 32, 32, 64) 18496
_________________________________________________________________
activation_2 (Activation) (None, 32, 32, 64) 0
_________________________________________________________________
max_pooling2d_1 (MaxPooling2 (None, 16, 16, 64) 0
_________________________________________________________________
dropout_2 (Dropout) (None, 16, 16, 64) 0
_________________________________________________________________
batch_normalization_2 (Batch (None, 16, 16, 64) 256
_________________________________________________________________
conv2d_3 (Conv2D) (None, 16, 16, 64) 36928
_________________________________________________________________
activation_3 (Activation) (None, 16, 16, 64) 0
_________________________________________________________________
max_pooling2d_2 (MaxPooling2 (None, 8, 8, 64) 0
_________________________________________________________________
dropout_3 (Dropout) (None, 8, 8, 64) 0
_________________________________________________________________
batch_normalization_3 (Batch (None, 8, 8, 64) 256
_________________________________________________________________
conv2d_4 (Conv2D) (None, 8, 8, 128) 73856
_________________________________________________________________
activation_4 (Activation) (None, 8, 8, 128) 0
_________________________________________________________________
dropout_4 (Dropout) (None, 8, 8, 128) 0
_________________________________________________________________
batch_normalization_4 (Batch (None, 8, 8, 128) 512
_________________________________________________________________
flatten_1 (Flatten) (None, 8192) 0
_________________________________________________________________
dropout_5 (Dropout) (None, 8192) 0
_________________________________________________________________
dense_1 (Dense) (None, 256) 2097408
_________________________________________________________________
activation_5 (Activation) (None, 256) 0
_________________________________________________________________
dropout_6 (Dropout) (None, 256) 0
_________________________________________________________________
batch_normalization_5 (Batch (None, 256) 1024
_________________________________________________________________
dense_2 (Dense) (None, 128) 32896
_________________________________________________________________
activation_6 (Activation) (None, 128) 0
_________________________________________________________________
dropout_7 (Dropout) (None, 128) 0
_________________________________________________________________
batch_normalization_6 (Batch (None, 128) 512
_________________________________________________________________
dense_3 (Dense) (None, 10) 1290
_________________________________________________________________
activation_7 (Activation) (None, 10) 0
=================================================================
Total params: 2,264,458
Trainable params: 2,263,114
Non-trainable params: 1,344

Ahora llegamos a entrenar el modelo. Para hacer esto, todo lo que tenemos que hacer es llamar a la fit()función en el modelo y pasar los parámetros elegidos.

Aquí es donde utilizo la semilla que elegí, para propósitos de reproducibilidad.

numpy.random.seed(seed)
model.fit(X_train, y_train, validation_data=(X_test, y_test), epochs=epochs, batch_size=64)

Estaremos entrenando con 50000 muestras y validando con 10000 muestras.

Ejecutar este fragmento de código producirá:

Epoch 1/25

64/50000 [..............................] - ETA: 16:57 - loss: 3.1479 - acc: 0.0938
128/50000 [..............................] - ETA: 10:12 - loss: 3.0212 - acc: 0.0938
192/50000 [..............................] - ETA: 7:57 - loss: 2.9781 - acc: 0.1250
256/50000 [..............................] - ETA: 6:48 - loss: 2.8830 - acc: 0.1484
320/50000 [..............................] - ETA: 6:07 - loss: 2.8878 - acc: 0.1469
384/50000 [..............................] - ETA: 5:40 - loss: 2.8732 - acc: 0.1458
448/50000 [..............................] - ETA: 5:20 - loss: 2.8842 - acc: 0.1406

...
...
...

49664/50000 [============================>.] - ETA: 1s - loss: 1.5160 - acc: 0.4611
49728/50000 [============================>.] - ETA: 1s - loss: 1.5157 - acc: 0.4612
49792/50000 [============================>.] - ETA: 1s - loss: 1.5153 - acc: 0.4614
49856/50000 [============================>.] - ETA: 0s - loss: 1.5147 - acc: 0.4615
49920/50000 [============================>.] - ETA: 0s - loss: 1.5144 - acc: 0.4617
49984/50000 [============================>.] - ETA: 0s - loss: 1.5141 - acc: 0.4617
50000/50000 [==============================] - 262s 5ms/step - loss: 1.5140 - acc: 0.4618 - val_loss: 1.0715 - val_acc: 0.6195

End of Epoch 1

Tenga en cuenta que en la mayoría de los casos, querrá tener un conjunto de validación que sea diferente del conjunto de prueba, por lo que deberá especificar un porcentaje de los datos de entrenamiento para usar como el conjunto de validación. En este caso, simplemente pasaremos los datos de la prueba para asegurarnos de que los datos de la prueba estén reservados y no entrenados. Solo tendremos datos de prueba en este ejemplo, para simplificar las cosas.

Ahora podemos evaluar el modelo y ver cómo funcionó. Solo llama model.evaluate():

# Model evaluation
scores = model.evaluate(X_test, y_test, verbose=0)
print("Accuracy: %.2f%%" % (scores[1]*100))

Y nos saluda el resultado:

Accuracy: 83.01%

¡Y eso es! Ahora tenemos una CNN capacitada en reconocimiento de imágenes. No está mal para la primera ejecución, pero probablemente querrá jugar con la estructura y los parámetros del modelo para ver si no puede obtener un mejor rendimiento.

Conclusión

Ahora que ha implementado su primera red de reconocimiento de imágenes en Keras, sería una buena idea jugar con el modelo y ver cómo el cambio de parámetros afecta su rendimiento.

Esto le dará algo de intuición sobre las mejores opciones para diferentes parámetros del modelo. También debe leer sobre las diferentes opciones de parámetros e hiperparámetros mientras lo hace. Una vez que se sienta cómodo con estos, puede intentar implementar su propio clasificador de imágenes en un conjunto de datos diferente.

Si desea jugar con el código o simplemente estudiarlo un poco más, ¡el proyecto está cargado en GitHub !

 

About the author

Ramiro de la Vega

Bienvenido a Pharos.sh

Soy Ramiro de la Vega, Estadounidense con raíces Españolas. Empecé a programar hace casi 20 años cuando era muy jovencito.

Espero que en mi web encuentres la inspiración y ayuda que necesitas para adentrarte en el fantástico mundo de la programación y conseguir tus objetivos por difíciles que sean.

Add comment

Sobre mi

Últimos Post

Etiquetas

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con tus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, aceptas el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Más información
Privacidad