Kaggle: Perros vs Gatos, Clasificación de Imágenes usando Redes Convolucionales
1. 1
Resumen—En este trabajo se abordó el problema “Dogs vs.
Cats” propuesto en Kaggle usando una arquitectura de Redes
Convolucionales de 15 capas para predecir la categoría
predominante en imágenes que contienen perros o gatos. En la
implementación se utilizó el Lenguaje de Programación Julia y el
paquete para Aprendizaje Profundo Mocha.jl. La mejor tasa de
acierto obtenida fue de 86.73% sobre una base de datos de
prueba de 12,500 imágenes sin clasificar evaluadas por el Juez de
Kaggle.
Index Terms— Deep Learning, Kaggle, Julia, Mocha.jl,
ConvNet, AWS
I. INTRODUCCIÓN
econocer elementos dentro de imágenes resulta sencillo
para los seres humanos, sin embargo, la alta dificultad
para realizar esta tarea de forma automatizada [1] ha dado
origen a múltiples investigaciones e incluso competiciones
como “Dogs vs. Cats” en Kaggle, que buscan minimizar tanto
errores como tiempos de entrenamiento y clasificación.
Por muchos años, las Redes Convolucionales han sido
aplicadas a este tipo de problemas pues una de sus principales
ventajas es que el modelo se entrena de principio a fin, desde
los pixeles hasta las categorías finales, eliminando por ende la
necesidad de diseñar manualmente los extractores de
características que se sean adecuados para cada problema [2].
Algunos autores como Sermanet [2] toman como base la
arquitectura de clasificación ILSVRC12 de Krizhevsky et al.
[3] para realizar implementaciones en lenguajes como C,
Python o MathLab, sin embargo la complejidad de estas
implementaciones es alta y aún más si se desean aprovechar la
capacidad de procesamiento de la GPU.
En este reporte se ha utilizado el Lenguaje de Programación
Julia y el paquete Mocha.jl para aprendizaje profundo, para
implementar una arquitectura de clasificación basada en Redes
Convolucionales de 15 capas. El conjunto de datos de
entrenamiento consta de 25,000 imágenes con categorías de
Perros y Gatos, mientras que el conjunto de datos de prueba
consta de 12,500 imágenes sin categoría.
A continuación se describe el proceso de normalización de
datos, implementación de la arquitectura de clasificación de 15
capas, entrenamiento y, finalmente, se presentan los resultados
comparativos en base a tiempo y precisión.
El proceso realizado se describe en el siguiente gráfico, que
discrimina cinco fases que involucró la investigación, desde la
configuración del entorno hasta la clasificación:
Figura 1: Proceso de la investigación.
Entorno: La configuración del entorno fue la primera
tarea realizada. Dados los requerimientos de procesamiento,
la infraestructura utilizada fueron principalmente instancias
EC2 de Amazon del tipo g2.8xlarge equipadas con 2 GPUs,
30 CPUs y 60 Gigabytes de Memoría principal.
Normalización: Debido a que las imágenes de
entrenamiento y prueba eran de tamaños que oscilaban
desde 45 x 45 pixeles hasta 500 x 500 pixeles, se utilizaron
dos técnicas básicas de normalización: reducción de tamaño
y conversión a escala de grises.
Implementación: La implementación se realizó en dos
etapas: 1) normalización y conversión de los datos al
formato de almacenamiento HDF5 y 2) construcción de la
arquitectura de clasificación.
Entrenamiento: Durante el entrenamiento, de unas 5
horas aproximadamente, se utilizaron algunas técnicas de
monitoreo y guardado temporal del modelo con el fin de
reducir la posibilidad de sobreajuste y no perder el progreso
logrado.
Entorno
• AWS EC2 Instance
• IJulia, CUDA
Normalización
• Rezise
• Filters
Implementación
• HDF5
• IJulia
Entrenamiento
• GPU
• CPU
Clasificacion
• Kaggle Submission
Kaggle: Perros vs Gatos, Clasificación de
Imágenes usando Redes Convolucionales
Emilio García – emilio.garcia@pucp.pe
Pontificia Universidad Católica del Perú, Lima - Perú
R
2. 2
Clasificación: El proceso de clasificación tomó
aproximadamente 20 minutos para 12,500 imágenes. Con
una tasa de acierto de 79.9%. Con este resultado, la
presentación post-deadline en Kaggle situó al clasificador
en el lugar 90 de 215.
II. DESCRIPCIÓN Y NORMALIZACIÓN DE LOS
DATOS
La base de datos en Kaggle para el problema “Dogs vs.
Cats” contiene 25,000 imágenes a color de dimensiones
variables para el entrenamiento, además otras 12,500 con
características similares para ser usadas como datos de prueba.
Debido a que ambos conjuntos de datos, de entrenamiento y
pruebas, contenían imágenes de dimensiones variables, fue
necesario ejecutar un proceso de normalización para obtener
imágenes de 250 x 250 pixeles:
OriginalNormalizado
Figura 2: Imágenes originales y normalizadas del conjunto de datos de
entrenamiento.
Las nuevas imágenes con tamaños estándar y en escala de
grises, fueron almacenadas en formato HDF5 para su posterior
uso.
Hierarchical Data Format - HDF: HDF es un formato
de archivo portable extensamente usado, desarrollado en
el Centro Nacional para Aplicaciones de
Supercomputación (NCSA), para el almacenar, recuperar,
analizar, visualizar y convertir datos [6].
En este estudio fue utilizada la versión 5 del formato HDF
(HDF5) para almacenar los arrays multimensionales que
representaban las imágenes de los conjuntos de
entrenamiento y prueba del problema “Cats vs. Dogs” en
Kaggle.
El lenguaje de programación Julia, a través del paquete
HDF5, tiene soporte para lectura y escritura de archivos
HDF5. En la imagen siguiente, se muestra un snippet
usado para la creación del archivo para entrenamiento:
h5open(“train.hdf5”, "w") do h5
dset_data = d_create(h5, "data", datatype(Float32),
dataspace(cHeight, cWidth, 1, 25000))
dset_label = d_create(h5, "label", datatype(Float32),
dataspace(1, 25000))
for j = 1: 25000
sClass = files[j][1:3]
img = imread(string(imgDir,files[j]))
img = data(img)
fimg = spzeros(cHeight,cWidth)
for m = 1: cHeight*cWidth
fimg[m] = convert(Float32,img[m])
end
imgmatrix = vcat(fimg...)
class = sClass=="cat"?0/1:1/1
dset_data[:,:,1,idx[j]] = imgmatrix
dset_label[1,idx[j]] = class
if j % 500 == 0
println("Exporting... $j")
end
end
end
Figura 3: Snippet de la rutina de conversión de las imágenes de
entrenamiento al formato HDF5.
III. IMPLEMENTACIÓN DE LA ARQUITECTURA
PARA CLASIFICACIÓN
La arquitectura utilizada se basa en el modelo propuesto
en [3] de 15 capas, cuya implementación se realizó en su
totalidad usando el Lenguaje de Programación Julia.
Mocha.jl: De acuerdo a [7], Mocha es un Framework
de Aprendizaje Profundo para Julia inspirado en
Caffe, un framework de propósito similar para C++.
Mocha puede ser usado para entrenar Redes
Neuronales Convolucionales con pre-entrenamiento
opcional vía auo-encoders [7].
Algunas de las ventajas tomadas en cuenta al momento
de escoger Mocha.jl como framework para la
implementación de la arquitectura de clasificación fueron
las extensiones nativas para CUDA, cuBLASS y cuDNN
que permiten aprovechar la eficiencia de procesamiento de
la GPU para el entrenamiento del modelo.
La imagen a continuación muestra de manera gráfica la
arquitectura de clasificación. Nótese que la primera capa
(arriba a la izquierda) es la capa que contiene los datos de
entrada y la última (arriba a la derecha) es la que finalmente
se encargará de indicar la probabilidad de que el elemento
evaluado pertenezca a la clase 1: Perro o a la clase 0: Gato:
3. 3
Figura 4: Vista Gráfica de la arquitectura de clasificación utilizada.
La arquitectura en la Figura 4 muestra las 15 capas del
modelo, que en Julia se implementaron con el siguiente
snippet:
layers = [
AsyncHDF5DataLayer(name="train-data", source="train.txt", batch_size=20,
shuffle=false)
ConvolutionLayer(name="conv1", tops=[:conv1], bottoms=[:data],
kernel=(11,11), stride=(4,4), n_filter=96, neuron=Neurons.ReLU())
PoolingLayer(name="pool1", tops=[:pool1], bottoms=[:conv1],
kernel=(3,3), stride=(2,2), pooling=Pooling.Max())
LRNLayer(name="norm1", tops=[:norm1], bottoms=[:pool1],
kernel=5, scale=0.0001, power=0.75)
ConvolutionLayer(name="conv2", tops=[:conv2], bottoms=[:norm1],
kernel=(5,5), pad=(2,2), n_filter=256, n_group=2,
neuron=Neurons.ReLU())
PoolingLayer(name="pool2", tops=[:pool2], bottoms=[:conv2],
kernel=(3,3), stride=(2,2), pooling=Pooling.Max())
LRNLayer(name="norm2", tops=[:norm2], bottoms=[:pool2],
kernel=5, scale=0.0001, power=0.75)
ConvolutionLayer(name="conv3", tops=[:conv3], bottoms=[:norm2],
kernel=(3,3), pad=(1,1), n_filter=384, neuron=Neurons.ReLU())
ConvolutionLayer(name="conv4", tops=[:conv4], bottoms=[:conv3],
kernel=(3,3), pad=(1,1), n_filter=384, n_group=2,
neuron=Neurons.ReLU())
ConvolutionLayer(name="conv5", tops=[:conv5], bottoms=[:conv4],
kernel=(3,3), pad=(1,1), n_filter=256, n_group=2,
neuron=Neurons.ReLU())
PoolingLayer(name="pool5", tops=[:pool5], bottoms=[:conv5],
kernel=(3,3), stride=(2,2), pooling=Pooling.Max())
InnerProductLayer(name="fc6", tops=[:fc6], bottoms=[:pool5],
output_dim=4096, neuron=Neurons.ReLU())
InnerProductLayer(name="fc7", tops=[:fc7], bottoms=[:fc6],
output_dim=4096, neuron=Neurons.ReLU())
InnerProductLayer(name="fc8", tops=[:fc8], bottoms=[:fc7],
output_dim=2)
SoftmaxLossLayer(name="loss", bottoms=[:fc8,:label])
]
Figura 5: Implementación en Julia de la arquitectura de clasificación
mostrada en la Figura 4.
IV. EXPERIMENTACIÓN
A continuación se muestran los datos en tiempo de
procesamiento de cada una de las tareas realizadas en este
trabajo:
Tarea Descripción
Tiempo
(min)
1 Normalización de las Imágenes a 250 x 250 px y
escala de grises
3
2 Generación del dataset en formato HDF5 13
3 Entrenamiento del Modelo (x 10,000 iteraciones) 107
4 Clasificación ( x12,500 imágenes, 1 a la vez) 137
Tabla 1: Tiempos de procesamiento por tarea.
Durante el proceso de entrenamiento, se midieron las tasas
de acierto en un subconjunto de 1,000 imágenes extraídas del
conjunto de imágenes de entrenamiento. Estas 1,000 imágenes
no fueron incluidas en las iteraciones. A continuación se
muestran los porcentajes de acierto promedio por cada 1,000
iteraciones:
Iteración N°
Tasa de Acierto
(Promedio)
0 48.8*
1,000 70.2
2,000 80.9
3,000 83.5
4,000 86.2
5,000 86.8
6,000 86.5
7,000 86.7
8,000 87.1
9,000 87.4
10,000 86.9
Tabla 2: Tasa de Acierto por número de iteraciones.
*Tasa inicial por defecto
Debido a la tasa de acierto empieza a crecer con mejor
escala a partir de la iteración 7,000 llegando luego incluso a
decrecer, el entrenamiento se da por concluido en la
iteración 10,000.
Figura 6: Implementación en Julia de la arquitectura de clasificación
mostrada en la Figura 4.
4. 4
V. RESULTADOS OBTENIDOS
Presentamos a continuación el resultado de los
experimentos sobre 12,500 imágenes de prueba, evaluadas en
el sitio web para el problema “Dogs vs. Cats” de Kaggle:
El porcentaje de acierto alcanzado fue de 86.73% para un
total de 12,500 imágenes de prueba. El tiempo de clasificación
individual es de 1.3 segundos:
% Acierto
Tiempo de
Clasificación
por Imagen
Total de
Imágenes
Clasificadas
86.73% 1.3s 12,500
Tabla 3: Resumen de los Resultados Obtenidos
A continuación se muestra el resultado de la evaluación
automática sobre el resultado enviado al sitio para el problema
“Dogs vs. Cats” en Kaggle:
Figura 7: Resultado de la evaluación por el Juez de Kaggle sobre la
clasificación realizada.
VI. CONCLUSIONES Y RECOMENDACIONES
Gracias al empleo de Redes Convolucionales, el proceso de
entrenamiento no requiere de una etapa previa de extracción
de características, ya que el modelo se entrena de principio a
fin, desde la capa de datos a nivel de pixeles hasta la capa de
predicción en dónde la salida posible solo es, en este caso, un
vector de posibilidades 1x2.
Es importante notar que el tiempo de entrenamiento para las
25,000 imágenes fue de poco más de una hora y media, por lo
que recomendamos altamente el uso de la GPU para este tipo
de computación. Es posible que sin el procesamiento en la
GPU el tiempo de entrenamiento hubiera sido de entre 1 y 2
días.
Se requiere mejorar el proceso de normalización de las
imágenes en la capa de entrada con técnicas como las
mencionadas en [8] y realizar ajustes al modelo a fin de
alcanzar mejores tasas de acierto.
REFERENCIAS
[1] J. Elson, J. Douceur, J. Howell and J. Saul. Asirra: a CAPTCHA that
exploits interest-aligned manual image categorization. In Proc. of ACM
CCS 2007, pp. 366–374.
[2] L. Deng, D. Yu (2014). "Deep Learning: Methods and Applications".
Foundations and Trends in Signal Processing 7: 3–4.
[3] A. Krizhevsky, I. Sutskever, and G. Hinton. Imagenet classification with
deep convolutional neural networks.
[4] HDF5 en HDF Group: https://www.hdfgroup.org/HDF5
[5] Manual de usuario de HDF5:
https://www.hdfgroup.org/HDF5/doc/UG/HDF5_Users_Guide.pdf
[6] C. M. Chilan, M. Yang, A. Cheng and L. Arber: Parallel I/O
Performance Study With Hdf5, A Scientific Data Package: In: TeraGrid
2006: Advancing Scientific Discovery, June 12-15 (2006)
[7] Mocha.jl en GitHub: https://github.com/pluskid/Mocha.jl
[8] S. C. Pei and S. N. Lin: Image normalization for pattern recognition. In:
Image and Vision Computing Vol. 13 Num. 10, December 1995