• Saltar a la navegación principal
  • Saltar al contenido principal
Logo Codificando Bits

Codificando Bits

  • Academia
    • Rutas
    • Cursos
    • Proyectos
    • Tutoriales
  • Acceder
  • Suscribirse

¿Cómo entrenar una Red Convolucional con imágenes de diferentes tamaños?

Las Redes Convolucionales son ampliamente utilizadas en Visión por Computador, ya que están diseñadas para procesar imágenes. Y esto permite desarrollar aplicaciones como la clasificación, la segmentación y la detección de objetos, entre otras.

Y un desafío común al entrenar este tipo de redes es cuando tenemos un set de datos propio pero donde las imágenes tienen distintos tamaños. Y esto es un problema porque la Red Convolucional requiere imágenes de entrada de un tamaño fijo.

Y entonces surge una pregunta y es ¿cómo podemos entrenar una Red Convolucional que acepta imágenes de tamaño fijo a la entrada si nuestras imágenes tienen tamaños variables?

Pues en este artículo veremos qué alternativas existen para ajustar las imágenes de un set de datos a un tamaño uniforme para de esta forma poder entrenar correctamente la red y lograr obtener además el mejor desempeño posible.

Arquitectura de una Red Convolucional

Muy bien, para entender el problema al que usualmente nos enfrentamos cuando tenemos imágenes de tamaño variable, necesitamos recordar algunos elementos básicos de una Red Convolucional.

En el curso Fundamentos de Deep Learning con Python, disponible acá en la Academia Online, vemos todos los detalles de cómo funcionan estas Redes Convolucionales, así que en este punto sólo repasaremos algunos elementos claves.

Una Red Convolucional es un tipo de Red Neuronal que ha sido diseñada específicamente para procesar imágenes.

Y toda Red Convolucional tiene una serie de capas, entre las cuales se encuentra la capa de entrada que es la encargada de recibir las imágenes a procesar, así como una capa de salida, encargada de generar las predicciones (por ejemplo, la categoría a la que pertenece la imagen).

Si nos enfocamos en la capa de entrada, al momento de programar la Red Convolucional en nuestros computadores (usando, por ejemplo, librerías como Keras) tendremos que definir de manera explícita el tamaño de la imagen de entrada:

modelo.add(layers.Conv2D(32, 
                        (3, 3), 
                        activation='relu', 
                        input_shape=(alto, ancho, 3)))

Por ejemplo, la porción de código anterior corresponde al código que se requeriría para crear una capa de entrada de una Red Convolucional usando la librería Keras. Y en la línea 4 vemos que el parámetro «input_shape» requiere que definamos de manera explícita el alto y el ancho de las imágenes de entrada.

Así que es importante tener claro que una Red Convolucional acepta imágenes con un alto y ancho específicos y este tamaño no se podrá modificar ni durante el entrenamiento del modelo ni al momento de generar predicciones.

Y el problema es que en la práctica, cuando estamos construyendo una Red Convolucional, hacemos uso de imágenes que tienen diferentes tamaños (altos y anchos) así que debemos implementar alguna etapa de pre-procesamiento de estas imágenes para garantizar que todas tengan exactamente las mismas dimensiones requeridas por la capa de entrada.

Veamos entonces cuáles técnicas de pre-procesamiento podemos implementar.

Alternativas de pre-procesamiento de las imágenes

En esencia podemos usar tres alternativas de pre-procesamiento para ajustar el tamaño de las imágenes: el «cropping» o recorte, el «padding» o rellenado con ceros y el redimensionamiento. Así que veamos en detalle cada una de estas técnicas así como sus ventajas y desventajas.

El «cropping» o recorte

La primera alternativa de pre-procesamiento se conoce como el recorte o «cropping» que consiste en eliminar los bordes de las imágenes más grandes dentro del set de datos para garantizar que tras este recorte tengan el mismo tamaño de la imagen más pequeña dentro del dataset.

Por ejemplo, en la parte de arriba de la siguiente figura vemos un set de cinco imágenes organizadas de mayor a menor (de izquierda a derecha):

Ejemplo del procedimiento de recorte ("cropping") de un set de imágenes. Arriba: imágenes originales, abajo: imágenes recortadas
Ejemplo del procedimiento de recorte («cropping») de un set de imágenes. Arriba: imágenes originales, abajo: imágenes recortadas

Así que la idea del recorte es eliminar los bordes de todas las demás imágenes, preservando únicamente la porción central y garantizando de esta forma que todas las imágenes resultantes tendrán el mismo tamaño. El resultado de este recorte se muestra en la parte de abajo de la figura anterior.

La desventaja de esta alternativa es que se perderá gran cantidad de información en las imágenes recortadas (pues se está preservando únicamente la porción central).

El «padding» o rellenado con ceros

La segunda alternativa es el «padding» o rellenado con ceros, que consiste en agregar ceros a los bordes de las imágenes más pequeñas dentro del set de datos para que tras rellenarlas tengan el mismo tamaño de la imagen más grande dentro del set de datos.

Así, en la primera fila de la figura de abajo vemos nuevamente las imágenes originales, organizadas de mayor a menor y con la imagen más grande ubicada del lado izquierdo:

Ejemplo del procedimiento de rellenado con ceros ("padding") de un set de imágenes. Arriba: imágenes originales, abajo: imágenes tras aplicar el "padding"
Ejemplo del procedimiento de rellenado con ceros («padding») de un set de imágenes. Arriba: imágenes originales, abajo: imágenes tras aplicar el «padding»

En la parte de abajo vemos que las imágenes han sido rellenadas con ceros pues contienen porciones de color negro en sus bordes.

En este caso no hay pérdida de información, pues el contenido de las imágenes originales se ha preservado. Sin embargo, al rellenar las imágenes con ceros estamos agregando datos que son irrelevantes y que pueden hacer que la Red Convolucional no genere buenas predicciones tras el entrenamiento.

El redimensionamiento o «reshaping»

Con esta tercera técnica de pre-procesamiento lo que hacemos es redimensionar las imágenes a un tamaño «promedio».

Es decir que no tomaremos como referencia ni la imagen más pequeña (como en el «cropping») ni la imagen más grande dentro del set de datos (como en el «padding») sino que en lugar de ello buscaremos un tamaño intermedio y ajustaremos todas las imágenes a dicho tamaño.

En la figura de abajo vemos un ejemplo de este redimensionamiento. En la parte de arriba vemos las imágenes originales y la flecha de color rojo señala la imagen cuyo tamaño se usará como referencia para el redimensionamiento:


Ejemplo del redimensionamiento de un set de imágenes. Arriba: imágenes originales (la imagen señalada con la flecha será usada como referencia para el redimensionamiento), abajo: imágenes tras aplicar el redimensionamiento

En la parte de abajo de la figura anterior vemos el resultado del redimensionamiento: todas las imágenes tendrán el mismo tamaño de la imagen usada como referencia.

La ventaja de este método, frente al «cropping» y al «padding», es que no habrá pérdida de información.

Sin embargo, las imágenes resultantes pueden presentar algo de distorsión con respecto a las imágenes originales. A pesar de esto, esta es la técnica que sugiero utilizar al momento de pre-procesar nuestras imágenes.

¿Cómo determinar el tamaño ideal para el redimensionamiento?

Como acabamos de ver, la técnica que usualmente funciona mejor es el redimensionamiento de las imágenes.

Sin embargo, en este punto surge una pregunta: ¿cuáles serán el alto y el ancho más adecuados para un problema y para una Red Convolucional en particular?

Y la respuesta es que no podemos saberlo con antelación. Es decir que, como ocurre siempre en el Deep Learning, no existe una regla o una fórmula matemática que nos permita saber con antelación, es decir antes de entrenar nuestra red, cuál será el tamaño más adecuado de las imágenes a usar.

Así que lo que debemos hacer es ver el alto y el ancho como un hiperparámetro de la red y la idea es encontrar el mejor valor posible de este hiperparámetro (alto y ancho) que genere las mejores predicciones.

Recordemos que un hiperparámetro es esencialmente una cantidad numérica cuyo valor tenemos que definir al momento de escribir el código para crear y entrenar nuestro modelo. Y la elección de este valor es clave en el comportamiento de nuestra red, pues puede afectar su desempeño.

Por ejemplo, el número de capas de una red convolucional es un hiperparámetro, el número de filtros en cada capa o el tamaño mismo de los filtros es un hiperparámetro y dependiendo de los valores que asignemos a estos hiperparámetros tendremos un mejor o un peor desempeño de la red.

Y cuando nos referimos al desempeño podemos estar hablando por ejemplo de la exactitud (si estamos implementando un clasificador de imágenes) o de qué tan precisa es la demarcación del objeto de interés (si estamos hablando de detección de objetos).

Así que si volvemos al caso de los tamaños de las imágenes podemos pensar que habrá ciertos tamaños (es decir combinaciones de altos y anchos) que harán que la Red Convolucional tenga un mejor o peor desempeño.

Entonces, lo que podemos hacer es probar diferentes combinaciones de altos y anchos y entrenar el modelo con cada una de estas combinaciones, evaluar su desempeño y escoger aquella combinación que arroje el mejor desempeño.

Por ejemplo, si usamos «n» diferentes combinaciones para entrenar «n» diferentes Redes Convolucionales para clasificar imágenes, podríamos obtener para cada modelo entrenado estos niveles de exactitud:

ModeloAlto, anchoDesempeño (exactitud)
1alto_1, ancho_183%
2alto_2, ancho_292%
………
nalto_n, ancho_n89%

Y tras este entrenamiento podemos ver que la combinación de «alto_2» y «ancho_2» para el segundo modelo es la que genera el mejor desempeño, así que estas serían las dimensiones que deberíamos usar al momento de ajustar el tamaño de las imágenes.

¿Y cómo determinar las posibles combinaciones de tamaños?

Bien, en este punto ya tenemos claro que debemos tratar tanto el ancho como el alto de las imágenes como hiperparámetros de nuestra red y la idea es entrenar varias redes convolucionales con diferentes altos y anchos para encontrar la combinación que genere mejores predicciones.

Pero entonces la pregunta es: ¿cómo podemos determinar esos posibles altos y anchos candidatos?

Y la respuesta a esta pregunta estará precisamente en nuestro set de datos. Así que la idea es analizar las dimensiones que tienen las imágenes en nuestro set de datos para así determinar estos tamaños candidatos.

Por ejemplo, podemos obtener un histograma que nos muestre la forma como la relación alto/ancho está distribuida en nuestro set de datos. Algo similar a esto:

Ejemplo de un histograma que muestra la relación "alto/ancho" para cada imagen en un set de datos. Eje horizontal: valor de la relación "alto/ancho"; eje vertical: porcentaje de imágenes con las diferentes relaciones "alto/ancho"
Ejemplo de un histograma que muestra la relación «alto/ancho» para cada imagen en un set de datos. Eje horizontal: valor de la relación «alto/ancho»; eje vertical: porcentaje de imágenes con las diferentes relaciones «alto/ancho»

En la figura anterior podemos ver un ejemplo de un histograma para un set de imágenes en particular. Las relaciones «alto/ancho» (eje horizontal) iguales a 1 nos indican que tendremos imágenes cuadradas (el alto y el ancho tienen el mismo valor), mientras que un valor de «alto/ancho» menor que 1 indica que tendremos imágenes más anchas que altas y un valor mayor a 1 corresponde a imágenes más altas que anchas.

En el ejemplo anterior podemos ver que un poco más del 70% de las imágenes tiene relaciones «alto/ancho» que oscilan entre 1.0 y 1.2. Es decir que más del 70% de las imágenes son o cuadradas o son ligeramente más altas que anchas.

Y el análisis anterior puede ser complementado por ejemplo obteniendo un segundo histograma que nos muestre el producto del ancho por el alto, es decir el número total de pixeles de cada imagen:


Ejemplo de un histograma que muestra el producto del ancho por el alto (es decir el número de pixeles) para cada imagen en un set de datos. Eje horizontal: valor del producto ancho por alto; eje vertical: porcentaje de imágenes con diferentes números de pixeles

Ejemplo de un histograma que muestra el producto del ancho por el alto (es decir el número de pixeles) para cada imagen en un set de datos. Eje horizontal: valor del producto ancho por alto; eje vertical: porcentaje de imágenes con diferentes números de pixeles

Con este segundo histograma podemos ver que un poco más del 70% de las imágenes (correspondientes a la barra de mayor altura en el histograma) tienen un número de pixeles de aproximadamente 0.125×10^6 que equivale 125.000 pixeles. Si asumimos imágenes cuadradas esto equivale a imágenes de aproximadamente 350×350 pixeles.

Así que si combinamos este resultado con el obtenido en el primer histograma (donde teníamos relaciones alto/ancho entre 1.0 y 1.2) podríamos por ejemplo proponer tres posibles combinaciones de alto y ancho: 450 x 350 pixeles, 350 x 350 pixeles y 300 x 250 pixeles.

Y habiendo definido estas tres posibles combinaciones podríamos entonces entrenar tres diferentes modelos (uno con cada combinación), evaluar su desempeño y escoger aquella combinación que genere las mejores predicciones.

También es importante tener en cuenta que debemos evitar redimensionar las imágenes a tamaños excesivamente grandes, generalmente superiores a los 500 pixeles. Esto debido a que entre más grandes sean las imágenes que usemos para entrenar nuestros modelos, más prolongado va a ser el tiempo de entrenamiento (y esto no necesariamente garantizará un mejor desempeño). Además, si queremos usar, por ejemplo, modelos pre-entrenados usando transferencia de aprendizaje generalmente dichos modelos usan imágenes de entrada con tamaños menores a estos 500 pixeles.

Conclusión

Muy bien, acabamos de entender cómo abordar el problema de determinar el tamaño que deben tener nuestras imágenes cuando nuestro set de datos contiene imágenes de tamaño variable.

La idea es tratar este tamaño (alto y ancho) como un hiperparámetro y lo que debemos hacer es entrenar varias redes convolucionales usando diferentes combinaciones de altos y anchos y escoger aquella que genere las mejores predicciones.

Y para determinar los posibles tamaños candidatos lo que sugiero es analizar las imágenes en nuestro set de datos, extrayendo por ejemplo las relaciones alto/ancho más comunes o el número total de pixeles (es decir alto x ancho) más común y a partir de esto definir tres o cuatro combinaciones de tamaños y entrenar el número de redes correspondiente para de esta forma seleccionar el tamaño más adecuado.

© Codificando Bits, LLC | Blog | Contacto | Servicios | Acerca de | Políticas

¿Has olvidado la contraseña?
¿Has perdido tu contraseña? Por favor, introduce tu nombre de usuario o dirección de correo electrónico. Recibirás por correo electrónico un enlace para crear una nueva contraseña.
body::-webkit-scrollbar { width: 7px; } body::-webkit-scrollbar-track { border-radius: 10px; background: #f0f0f0; } body::-webkit-scrollbar-thumb { border-radius: 50px; background: #dfdbdb }