Explorando la extracción de funciones con CNN |  de Rodrigo Silva |  noviembre de 2023

Las redes neuronales convolucionales son los componentes básicos actuales para las tareas de clasificación de imágenes mediante el aprendizaje automático. Sin embargo, otra tarea muy útil que realizan antes de la clasificación es extraer características relevantes de una imagen. La extracción de características es la forma en que las CNN reconocen patrones clave de una imagen para clasificarla. Este artículo mostrará un ejemplo de cómo realizar extracciones de funciones utilizando TensorFlow y la API funcional de Keras. Pero primero, para formalizar estos conceptos de CNN, primero debemos hablar sobre el espacio de píxeles.

Espacio de píxeles

El espacio de píxeles es exactamente lo que sugiere el nombre: es el espacio donde la imagen se convierte en una matriz de valores, donde cada valor corresponde a un píxel individual. Por lo tanto, la imagen original que vemos, cuando se introduce en la CNN, se convierte en una matriz de números. En imágenes en escala de grises, estos números suelen oscilar entre 0 (negro) y 255 (blanco), y los valores intermedios son tonos de gris. En este artículo, todas las imágenes han sido normalizadas, es decir, cada píxel se ha dividido entre 255 por lo que su valor está en el intervalo [0, 1].

CNN y espacio de píxeles

Lo que hace una CNN con la imagen en representación de píxeles es aplicar filtros y procesarla para extraer los píxeles relevantes para tomar la “decisión” final, que es poner esa imagen dentro de una clase. Por ejemplo, en la imagen en la parte superior de la página, CNN prestó mucha atención a la boca, la lengua, los ojos (y los contornos fuertes en general) del león, y estas características se extraen aún más a medida que profundizamos en la red neuronal. . Por tanto, basta decir que cuanto más especializada sea una CNN en términos de clasificación, más profesional será a la hora de reconocer las características clave de una imagen.

La meta

Dicho esto, el objetivo es simple: ver el nivel de especialización de una CNN en lo que respecta a la extracción de características.

El método

Para hacer esto, entrené dos CNN con la misma arquitectura, pero con diferentes tamaños de entrenamiento: una con imágenes de 50K (esta es la punto de referenciael inteligente), y el otro con imágenes de 10K (este es el ficticio uno). Después de eso, corté las capas de la CNN para comprobar lo que ve el algoritmo y el sentido que le da a la imagen que se le introduce.

Conjunto de datos

El conjunto de datos utilizado para este proyecto fue el ampliamente utilizado cifar10 conjunto de datos de imágenes [1], un conjunto de datos de dominio público, que es una base de imágenes de 60 000 dividida en 10 clases, de las cuales 10 000 imágenes se utilizan como conjunto de validación reservada. Las imágenes tienen un tamaño de 32×32 píxeles y son de color RGB, lo que significa 3 canales de color.

Para evitar la fuga de datos, guardé una imagen para usarla como imagen de prueba en el reconocimiento de características, por lo tanto, esta imagen no se usó en ninguna de las capacitaciones. Les presento a nuestra cobaya: la rana.

La rana.

La implementación se muestra en el siguiente fragmento de código. Para cortar correctamente las capas de CNN es necesario utilizar la API funcional de Keras en TensorFlow en lugar de la API secuencial. Funciona como una cascada, donde se llama a la siguiente capa sobre la última.

import tensorflow as tf
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Input, Conv2D, MaxPool2D, Dense, Dropout, Flatten
from tensorflow.keras.callbacks import ModelCheckpoint, EarlyStopping

def get_new_model(input_shape):
'''
This function returns a compiled CNN with specifications given above.
'''

#Defining the architecture of the CNN
input_layer = Input(shape=input_shape, name='input')
h = Conv2D(filters=16, kernel_size=(3,3),
activation='relu', padding='same', name='conv2d_1')(input_layer)
h = Conv2D(filters=16, kernel_size=(3,3),
activation='relu', padding='same', name='conv2d_2')(h)

h = MaxPool2D(pool_size=(2,2), name='pool_1')(h)

h = Conv2D(filters=16, kernel_size=(3,3),
activation='relu', padding='same', name='conv2d_3')(h)
h = Conv2D(filters=16, kernel_size=(3,3),
activation='relu', padding='same', name='conv2d_4')(h)

h = MaxPool2D(pool_size=(2,2), name='pool_2')(h)

h = Conv2D(filters=16, kernel_size=(3,3),
activation='relu', padding='same', name='conv2d_5')(h)
h = Conv2D(filters=16, kernel_size=(3,3),
activation='relu', padding='same', name='conv2d_6')(h)

h = Dense(64, activation='relu', name='dense_1')(h)
h = Dropout(0.5, name='dropout_1')(h)
h = Flatten(name='flatten_1')(h)
output_layer = Dense(10, activation='softmax', name='dense_2')(h)

#To generate the model, we pass the input layer and the output layer
model = Model(inputs=input_layer, outputs=output_layer, name='model_CNN')

#Next we apply the compile method
model.compile(optimizer='adam',
loss='categorical_crossentropy',
metrics=['accuracy'])

return model

Las especificaciones de la arquitectura se muestran a continuación en la Fig. 1.

Fig. 1: Resumen de la CNN utilizada. Imagen del autor.

El optimizador utilizado es Adam, la función de pérdida fue de entropía cruzada categórica y la métrica utilizada para la evaluación fue simplemente la precisión, ya que el conjunto de datos está perfectamente equilibrado.

Ahora podemos cortar algunas capas estratégicas de las dos CNN para comprobar el nivel de procesamiento de las imágenes. La implementación del código se muestra a continuación:

benchmark_layers = model_benchmark.layers
benchmark_input = model_benchmark.input

layer_outputs_benchmark = [layer.output for layer in benchmark_layers]
features_benchmark = Model(inputs=benchmark_input, outputs=layer_outputs_benchmark)

Lo que sucede aquí es lo siguiente: la primera línea accede a cada capa del modelo y la segunda línea devuelve la capa de entrada de toda la CNN. Luego en la tercera línea hacemos una lista mostrando las salidas de cada capa, y finalmente, creamos un nuevo modelo, cuyas salidas son las salidas de las capas. De esta manera podemos ver lo que sucede entre capas.

Se escribió un código muy similar para acceder a las capas de nuestro modelo ficticio, por lo que lo omitiremos aquí. Ahora procedamos a mirar las imágenes de nuestra rana, procesadas dentro de diferentes capas de nuestras CNN.

Primera capa convolucional

Ficticio

La Fig. 2 muestra las imágenes de los 16 filtros de la capa convolucional (conv2d_1). Podemos ver que las imágenes no están superprocesadas y hay mucha redundancia. Se podría argumentar que esta es sólo la primera capa convolucional, lo que explica el hecho de que el procesamiento no es tan pesado, y esa es una observación justa. Para abordar esto, veremos la primera capa del punto de referencia.

Fig. 2: Primera capa convolucional del clasificador ficticio. Imagen del autor.

Punto de referencia

El clasificador de referencia muestra una imagen mucho más procesada, hasta el punto de que la mayoría de estas imágenes ya no son reconocibles. Recuerde: esta es solo la primera capa convolucional.

Fig. 3: Primera capa convolucional del clasificador de referencia. Imagen del autor.

Última capa convolucional

Ficticio

Como era de esperar, la imagen ya no es reconocible, ya que hemos pasado por 6 capas convolucionales en este punto y 2 capas de agrupación, lo que explica las dimensiones inferiores de las imágenes. Veamos cómo se ve la última capa del punto de referencia.

Fig. 4: Última capa convolucional del clasificador ficticio. Imagen del autor.

Punto de referencia

Esto se procesa aún más, hasta el punto en que la mayoría de los píxeles son negros, lo que muestra que se seleccionaron las características importantes y el resto de la imagen básicamente se desecha.

Fig. 5: Última capa convolucional del clasificador de referencia. Imagen del autor.

Podemos ver que los grados de procesamiento son muy diferentes para el mismo segmento de la red. El análisis cualitativo indica que el modelo de referencia es más agresivo a la hora de extraer información útil de los datos de entrada. Esto es particularmente evidente en la primera comparación de capas convolucionales: la salida de la imagen de la rana está mucho menos distorsionada y mucho más reconocible en el modelo ficticio que en el modelo de referencia.

Esto sugiere que el punto de referencia es más eficiente a la hora de descartar elementos de la imagen que no son útiles a la hora de predecir la clase, mientras que el clasificador ficticio, sin saber cómo proceder, considera más características. Podemos ver en la Fig. 6 que el punto de referencia (en azul) descarta más píxeles de color que el modelo ficticio (en rojo), que muestra una cola más larga en su distribución de colores.

Fig. 6: Distribución de probabilidad de los píxeles de la última capa. Podemos ver que los píxeles del benchmark (en azul) están más comprimidos hacia cero, mientras que los píxeles del modo ficticio (en rojo) muestran una cola más larga.

Si echamos un vistazo a la distribución de píxeles de nuestra imagen de rana original, tenemos la Fig. 7, que muestra una distribución mucho más simétrica, centrada más o menos alrededor de 0,4.

Fig. 7: Distribución de colores de nuestra imagen de rana original. Imagen del autor.

Desde el punto de vista de la teoría de la información, las diferencias en las distribuciones de probabilidad de la imagen original y las imágenes resultantes después de las capas convolucionales representan una ganancia de información masiva.

Mirando la Fig. 6 y comparándola con la Fig. 7, tenemos mucha más seguridad de qué píxeles vamos a encontrar en la primera que en la segunda. Por tanto, hay una ganancia de información. Esta es una exploración muy breve y cualitativa de la Teoría de la Información y abre una puerta a un área vasta. Para obtener más información sobre Información (juego de palabras), consulte esto correo.

Y finalmente, una forma de observar la incertidumbre en la respuesta de los clasificadores es observar la distribución de probabilidad entre las clases. Esta es la salida de la función sofmax, al final de nuestra CNN. La figura 8 (izquierda) muestra que el punto de referencia es mucho más seguro para la clase, con una distribución máxima en la clase rana; mientras que la Fig. 8 (derecha) muestra un clasificador ficticio confuso, con la mayor probabilidad en la clase incorrecta.