Muy buenas, soy Luis y en esta ocasión les traigo otro nuevo post.
Índice
Utilice una red neuronal previamente entrenada para la extracción de características y las imágenes de clúster mediante K-means.
Objetivo
En este tutorial, lo guiaré a través del uso de una red neuronal previamente entrenada para extraer un vector de características de las imágenes y agrupar las imágenes en función de cuán similares sean los vectores de características.
El modelo
El modelo pre-entrenado que se utilizará en este tutorial es la red neural convolucional VGG16 (CNN), que se considera el estado del arte para las tareas de reconocimiento de imágenes. Vamos a utilizar este modelo sólo como extractor de características, lo que significa que eliminaremos la capa final (de predicción) para poder obtener un vector de características.
Los datos
Esta implementación usará el conjunto de datos de flores de Kaggle que puedes descargar aquí. El conjunto de datos contiene 210 imágenes de 10 especies diferentes de flores que serán descargadas como archivos png.
Importaciones
Antes de empezar, necesitamos importar los módulos necesarios para cargar/procesar las imágenes junto con los módulos para extraer y agrupar nuestros vectores de características.
- load_img nos permite cargar una imagen de un archivo como un objeto PIL.
- img_to_array nos permite convertir el objeto PIL en una matriz NumPy.
- preprocess_input está destinado a preparar su imagen en el formato que el modelo requiere. Debes cargar las imágenes con la función load_img de Keras para garantizar que las imágenes que cargues sean compatibles con la función preprocess_input.
- VGG16 es el modelo pre-entrenado que vamos a utilizar.
- KMeans el algoritmo de agrupación en clústeres que vamos a usar.
- PCA para reducir las dimensiones de nuestro vector de características.
Cargando los datos
Ahora que los datos se descargan en su ordenador, queremos que la pitón apunte al lugar donde se encuentran las imágenes. De esta manera, en lugar de cargar una ruta de archivo completa, podemos simplemente utilizar el nombre del archivo.
path = r"E:\Documents\Data\Datasets\Images\flower_images\flower_images" # change the working directory to the path where the images are located os.chdir(path) # this list holds all the image filename flowers = [] # creates a ScandirIterator aliased as files with os.scandir(path) as files: # loops through each file in the directory for file in files: if file.name.endswith('.png'): # adds only the image files to the flowers list flowers.append(file.name)
# view the first 10 flower entries print(flowers[:10])output: ['0001.png', '0002.png', '0003.png', '0004.png', '0005.png', '0006.png', '0007.png', '0008.png', '0009.png', '0010.png']
Ahora que tenemos todos los nombres de archivo cargados en la lista de flores, podemos empezar a preprocesar las imágenes.
Preprocesamiento de datos
Aquí es donde ponemos los métodos load_img() y preprocess_input() para usar. Al cargar las imágenes vamos a fijar el tamaño del objetivo en (224, 224) porque el modelo VGG espera que las imágenes que recibe sean matrices de 224×224 NumPy.
Actualmente, nuestra matriz sólo tiene 3 dimensiones (filas, columnas, canales) y el modelo funciona en lotes de muestras. Así que necesitamos expandir nuestra matriz para añadir la dimensión que le permitirá al modelo saber cuántas imágenes le estamos dando (num_de_muestras, filas, columnas, canales).
Number of dimensions: 4 Number of images (batch size): 1 Number of rows (0th axis): 224 Number of columns (1st axis): 224 Number of channels (rgb): 3
El último paso es pasar la matriz remodelada al método preprocess_input y nuestra imagen está lista para ser cargada en el modelo.
El modelo
Ahora podemos cargar el modelo VGG y eliminar la capa de salida manualmente. Esto significa que la nueva capa final es una capa completamente conectada con 4096 nodos de salida. Este vector de 4096 números es el vector de características que usaremos para agrupar las imágenes.
Ahora que se quitó la última capa, podemos pasar nuestra imagen a través del predecir método para obtener nuestro vector de características.
Aquí está todo el código en una sola función
Ahora podemos usar esto feature_extraction función para extraer las características de todas las imágenes y almacenar las características en un diccionario con el nombre de archivo como las claves.
Wall time: 56.2 s
Reducción de dimensionalidad (PCA)
Dado que nuestro vector de características tiene más de 4.000 dimensiones, su computadora se lo agradecerá si reduce el número de dimensiones de 4.000 a un número mucho menor. No podemos simplemente acortar la lista dividiéndola o usando algún subconjunto de ella porque perderemos información. Si tan solo hubiera una manera de reducir la dimensionalidad manteniendo la mayor cantidad de información posible.
Ingrese al ámbito del análisis de componentes principales.
No voy a perder el tiempo explicando qué es la PCA porque ya hay toneladas de artículos que lo explican, que vincularé aquí.
En pocas palabras, si está trabajando con datos y tiene muchas variables a considerar (en nuestro caso 4096), PCA le permite reducir el número de variables conservando la mayor cantidad de información posible del conjunto original.
El número de dimensiones a reducir depende de usted y estoy seguro de que hay un método para encontrar el mejor número de componentes para usar, pero para este caso, elegí 100 como un número arbitrario.
print(f"Components before PCA: f.shape[1]") print(f"Components after PCA: pca.n_components")Components before PCA: 4096 Components after PCA: 100
Ahora que tenemos un conjunto de funciones más pequeño, estamos listos para agrupar nuestras imágenes.
Definirá un número objetivo k, que se refiere al número de centroides que necesita en el conjunto de datos. Un centroide es la ubicación imaginaria o real que representa el centro del grupo.
Este algoritmo nos permitirá agrupar nuestros vectores de características en k grupos. Cada grupo debe contener imágenes que sean visualmente similares. En este caso, sabemos que hay 10 especies diferentes de flores, por lo que podemos tener k = 10.
kmeans.labels_
[6, 6, 8, 6, 6, 5, 4, 6, 5, 6, 4, 6, 6, 3, 3, 5, 6, 6, 4, 4, 8, 1,
3, 8, 4, 2, 8, 4, 2, 6, 9, 7, 4, 4, 0, 5, 4, 9, 8, 5, 9, 5, 3, 6,
5, 1, 3, 9, 6, 5, 0, 1, 3, 9, 6, 7, 4, 6, 4, 5, 8, 5, 3, 6, 5, 4,
6, 5, 2, 1, 4, 3, 9, 5, 4, 6, 2, 4, 5, 0, 5, 1, 2, 9, 5, 4, 8, 1,
7, 1, 3, 5, 4, 8, 5, 4, 6, 9, 5, 9, 5, 8, 1, 4, 9, 8, 5, 4, 5, 6,
4, 1, 8, 9, 4, 6, 5, 7, 5, 6, 4, 8, 1, 4, 5, 5, 8, 6, 5, 2, 4, 8,
5, 1, 1, 6, 6, 7, 8, 1, 9, 1, 6, 4, 8, 3, 6, 1, 0, 0, 8, 1, 3, 4,
9, 9, 0, 4, 0, 6, 4, 9, 0, 3, 5, 0, 3, 9, 9, 4, 9, 5, 0, 9, 5, 4,
5, 1, 8, 3, 6, 4, 5, 2, 6, 6, 9, 5, 0, 3, 1, 3, 5, 4, 5, 0, 9, 4,
2, 1, 0, 9, 4, 9, 1, 2, 6, 1, 6, 0]
Cada etiqueta en esta lista es un identificador de grupo para cada imagen en nuestro conjunto de datos. El orden de las etiquetas es paralelo a la lista de nombres de archivo de cada imagen. De esta forma podemos agrupar las imágenes en sus grupos.
# view the filenames in cluster 0 groups[0]output: ['0035.png', '0051.png', '0080.png', '0149.png', '0150.png', '0157.png', '0159.png', '0163.png', '0166.png', '0173.png', '0189.png', '0196.png', '0201.png', '0210.png']
Todo lo que nos queda por hacer es ver un clúster para ver qué tan bien le fue a nuestro modelo al inspeccionar los clústeres.
Clúster 0
Grupo 1
Grupo 2
Aquí podemos ver que a nuestro modelo le fue bastante bien agrupando las imágenes de flores. Incluso podemos ver que el grupo 2 y el grupo 0 tienen flores amarillas, pero el tipo de flores en cada grupo son especies diferentes.
Conclusión
Aquí está todo el proceso en un archivo.
Espero que todos hayan aprendido algo nuevo, dejen un comentario si tienen alguna pregunta o tuvieron un momento aha 🙂
Referencias
Añadir comentario