Alberto Beiz

Mis pruebas y experimentos.

Contacta sin miedo:

Hola mundo con Keras y Fashion MNIST

Mi primera prueba de Deep Learning con Keras va a ser construir un clasificador de imágenes. Voy a seguir el excelente tutorial de Jordi Torres, aunque voy a cambiar el dataset.

No voy a entrar en profundidad en ninguno de los conceptos que se presentan, los iré investigando poquito a poquito en futuros posts. El objetivo es tener algo funcionando lo antes posible para divertirnos, emocionarnos y tener un punto de partida desde donde empezar a trastear.

En el tutorial original se utiliza el archiconocido dataset MNIST, una base de datos de 70.000 imágenes (28x28 píxeles) de dígitos escritos a mano.

El problema es que es un dataset muy estudiado y utilizado, y un poco “simple”. Asi que Vamos a probar a usar Fashion MNIST, el mismo concepto pero con imágenes de prendas de ropa, un poco más complejas. Puedes aprender más sobre el dataset en su repositorio oficial.

Pues ¡al turrón!

# Importamos los paquetes necesarios
import keras
from keras.datasets import fashion_mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout
from keras.optimizers import adam

# Las imágenes se procesarán de 128 en 128
batch_size = 128
# Fashion MNIST se divide en 10 clases
num_classes = 10
# Vamos a realizar 20 pasadas por todo el dataset
epochs = 20
# Las imágenes son de 28x28 píxeles
shape = 28*28

# Cargamos los sets de entrenamiento y de validación
(x_train, y_train), (x_test, y_test) = fashion_mnist.load_data()
# Comprobamos que las imágenes son matrices de 28 filas y 28 columnas
x_train[0].shape
(28, 28)
# Y que una fila contiene 28 números enteros de 0 a 255, de negro a blanco
x_train[0][14]
array([  0,   0,   1,   4,   6,   7,   2,   0,   0,   0,   0,   0, 237,
       226, 217, 223, 222, 219, 222, 221, 216, 223, 229, 215, 218, 255,
        77,   0], dtype=uint8)
# Para nuestra red neuronal necesitamos que los valores estén en una
# lista de 28*28 = 784 elementos, no en una matriz
x_train = x_train.reshape(60000, shape)
x_test = x_test.reshape(10000, shape)

# Que sean valores con decimales 
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')

# Y que estén normalizados entre 0 y 1
x_train /= 255
x_test /= 255
# Comprobamos que cada imágen es ahora una lista de
# 784 números entre 0 y 1
print(x_train[0].shape)
print(x_test[0][460:470])
(784,)
[0.40392157 0.4509804  0.5058824  0.5254902  0.56078434 0.6039216
 0.64705884 0.6666667  0.6039216  0.5921569 ]
# El resultado es un número del 0 al 9
# dependiendo de si es un pantalón, zapato, etc...
y_train[134]
4
# Nosotros lo necesitamos en un formato especial llamado
# one hot encoding. Una lista con un 1 en la posición que corresponde,
# en nuestro caso en la 5ª posición
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)

print(y_train[134])
[0. 0. 0. 0. 1. 0. 0. 0. 0. 0.]
# Creamos la red neuronal
model = Sequential()

# Añadimos una capa con nuestras 784 entradas
# y 512 neuronas
model.add(Dense(512, activation='relu', input_shape=(shape,)))
# Desechamos parte de los resultados,
# mejora el proceso de aprendizaje
model.add(Dropout(0.2))
# Capa de salida para las 10 clases
model.add(Dense(10, activation='softmax'))

model.summary()
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_1 (Dense)              (None, 512)               401920    
_________________________________________________________________
dropout_1 (Dropout)          (None, 512)               0         
_________________________________________________________________
dense_2 (Dense)              (None, 10)                5130      
=================================================================
Total params: 407,050
Trainable params: 407,050
Non-trainable params: 0
_________________________________________________________________
# Compilamos el modelo
model.compile(loss='categorical_crossentropy',
              optimizer='adam',
              metrics=['accuracy'])
# Lo entrenamos
history = model.fit(x_train, y_train,
                    batch_size=batch_size,
                    epochs=epochs,
                    verbose = 0,
                    validation_data=(x_test, y_test))
# Comprobamos la precisión final sobre el set de entrenamiento
score = model.evaluate(x_train, y_train)
print('Test loss:', score[0])
print('Test accuracy:', score[1])
60000/60000 [==============================] - 18s 298us/step
Test loss: 0.16728065162400405
Test accuracy: 0.9367
# Comprobamos la precisión final sobre el set de validación
score = model.evaluate(x_test, y_test)
print('Test loss:', score[0])
print('Test accuracy:', score[1])
10000/10000 [==============================] - 3s 290us/step
Test loss: 0.3131952121436596
Test accuracy: 0.8982

Conclusión

He pasado por alto infinitos detalles pero lo esencial es que en muy pocas líneas de código hemos conseguido construir un sistema de Deep Learning que permite clasificar imágenes de 10 clases distintas con una precisión del 90%.

También vemos que prácticamente la mitad del ejercicio ha sido preparar los datos para poder trabajar con ellos, y eso que los datos ya estaban recopilados.

Fuentes