Clasificación de imágenes a gran escala con Keras - vgg16 ajuste fino -

⏱️3 min
Compartir:

1. Introducción

Recientemente comencé a aprender machine learning y a participar en Kaggle , la competencia para la clasificación de imágenes. Esta vez resumiré cómo implementar vgg16 con la biblioteca python keras 1.

2 Acerca de los datos

El conjunto de datos es el siguiente. Solo había experimentado un conjunto de datos como MNIST que a menudo se veían en los tutoriales de ML, así que sentí que era un conjunto de datos muy grande.

  • Clases: alrededor de 15,000
  • Tamaño de los datos de aprendizaje: alrededor de 1,2 millones de archivos de imagen. Más de 300GB
  • El tamaño de cada archivo de imagen: varía entre los archivos. p.ej. 1,600 \ * 1,200
  • Datos de prueba: alrededor de 120,000 archivos

3 Implementación

3.1 Aprender datos

Primero te mostraré el código completo.

python
1from keras.preprocessing.image import ImageDataGenerator
2from keras import optimizers
3from keras.applications.vgg16 import VGG16
4from keras.layers import Dense, Dropout, Flatten, Input, BatchNormalization
5from keras.models import Model, Sequential
6from keras.callbacks import ModelCheckpoint
7import numpy as np
8
9train_data_dir = "/train/"
10validation_data_dir = "/validation/"
11
12train_datagen = ImageDataGenerator(rescale=1. / 255)
13validation_datagen = ImageDataGenerator(rescale=1. / 255)
14
15img_width, img_height = 200, 150
16nb_train_samples = 915649
17nb_validation_samples = 302091
18epochs = 50
19batch_size = 64
20nb_category = 14951
21
22train_generator = train_datagen.flow_from_directory(
23 train_data_dir,
24 target_size=(img_width, img_height),
25 batch_size=batch_size,
26 class_mode="categorical")
27
28validation_generator = validation_datagen.flow_from_directory(
29 validation_data_dir,
30 target_size=(img_width, img_height),
31 batch_size=batch_size,
32 class_mode="categorical")
33
34# define input_tensor
35input_tensor = Input(shape=(img_width, img_height, 3))
36
37vgg16 = VGG16(include_top=False, weights='imagenet', input_tensor=input_tensor)
38
39top_model = Sequential()
40top_model.add(Flatten(input_shape=vgg16.output_shape[1:]))
41top_model.add(Dense(256, activation='relu', kernel_initializer='he_normal'))
42top_model.add(BatchNormalization())
43top_model.add(Dropout(0.5))
44top_model.add(Dense(nb_category, activation='softmax'))
45
46# Connect vgg16 and top_model
47model = Model(inputs=vgg16.input, outputs=top_model(vgg16.output))
48
49# Fix layers
50for layer in model.layers[:15]:
51 layer.trainable = False
52
53optimizer = optimizers.rmsprop(lr=5e-7, decay=5e-5)
54model.compile(loss='categorical_crossentropy',
55 optimizer=optimizer,
56 metrics=['accuracy'])
57
58checkpoint_cb = ModelCheckpoint("snapshot/{epoch:03d}-{val_acc:.5f}.hdf5", save_best_only=True)
59
60model.fit_generator(
61 train_generator,
62 steps_per_epoch=nb_train_samples // batch_size,
63 epochs=epochs,
64 validation_data=validation_generator,
65 validation_steps=nb_validation_samples // batch_size,
66 callbacks=[checkpoint_cb])
67
68# Save the model
69model.save("model.h5")
70
71model.summary()

3.1.1 Aprender con datos a gran escala

En la mayoría de los tutoriales, podemos ver que los datos se cargan de la siguiente manera.

python
1(X_train, y_train), (X_test, y_test) = mnist.load_data()

Sin embargo, no es posible cargar datos completos en la memoria cuando trata datos a gran escala como esta vez. En su lugar, puede usar la función flow_from_directory para cargar datos 2. Esta función procesa datos de imágenes mientras expande los datos en tiempo real.

Primero necesitas crear ImageDataGenerator .

python
1train_datagen = ImageDataGenerator(rescale=1. / 255)
2validation_datagen = ImageDataGenerator(rescale=1. / 255)

Esta clase realiza la generación por lotes de datos de imagen mientras realiza el preprocesamiento. Esta vez, simplemente reescalar. 1/255 se utiliza para normalizar el rango de valores RGB de 0-255 a 0-1.

A continuación, lea los datos.

python
1train_generator = train_datagen.flow_from_directory(
2 train_data_dir,
3 target_size=(img_width, img_height),
4 batch_size=batch_size,
5 class_mode="categorical")
6
7validation_generator = validation_datagen.flow_from_directory(
8 validation_data_dir,
9 target_size=(img_width, img_height),
10 batch_size=batch_size,
11 class_mode="categorical")

Como es una clasificación categórica, establezca class_mode como categorical . En este momento, debe tener cuidado con la estructura de la carpeta. Como se muestra a continuación, debe crear una subcarpeta para cada clase que desee clasificar.

javascript
1data/
2 train/
3 classA/
4 aaa.jpg
5 bbb.jpg
6 ...
7 classB/
8 ccc.jpg
9 ddd.jpg
10 ...
11
12 validation/
13 classA/
14 eee.jpg
15 fff.jpg
16 ...
17 classB/
18 ggg.jpg
19 hhh.jpg
20 ...

3.1.2 Usar el modelo vgg16

Aprenda a usar el modelo VGG16 que se puede usar con Keras .

python
1# define input_tensor
2input_tensor = Input(shape=(img_width, img_height, 3))
3
4vgg16 = VGG16(include_top=False, weights='imagenet', input_tensor=input_tensor)
5
6top_model = Sequential()
7top_model.add(Flatten(input_shape=vgg16.output_shape[1:]))
8top_model.add(Dense(256, activation='relu', kernel_initializer='he_normal'))
9top_model.add(BatchNormalization())
10top_model.add(Dropout(0.5))
11top_model.add(Dense(nb_category, activation='softmax'))
12
13# Connect vgg16 with top_model
14model = Model(inputs=vgg16.input, outputs=top_model(vgg16.output))
15
16# Fix layers
17for layer in model.layers[:15]:
18 layer.trainable = False
19
20optimizer = optimizers.rmsprop(lr=5e-7, decay=5e-5)
21model.compile(loss='categorical_crossentropy',
22 optimizer=optimizer,
23 metrics=['accuracy'])
24
25checkpoint_cb = ModelCheckpoint("snapshot/{epoch:03d}-{val_acc:.5f}.hdf5", save_best_only=True)
26
27model.fit_generator(
28 train_generator,
29 steps_per_epoch=nb_train_samples // batch_size,
30 epochs=epochs,
31 validation_data=validation_generator,
32 validation_steps=nb_validation_samples // batch_size,
33 callbacks=[checkpoint_cb])

Primero, use el modelo vgg16 predeterminado. En este momento, se especifica el tamaño del conjunto de datos de entrada.

python
1input_tensor = Input(shape=(img_width, img_height, 3))
2
3vgg16 = VGG16(include_top=False, weights='imagenet', input_tensor=input_tensor)

Luego, adjunte su propio modelo. Tenga en cuenta que include_top en el argumento anterior debe establecerse en False para fines de ajuste fino.

python
1top_model = Sequential()
2top_model.add(Flatten(input_shape=vgg16.output_shape[1:]))
3top_model.add(Dense(256, activation='relu', kernel_initializer='he_normal'))
4top_model.add(BatchNormalization())
5top_model.add(Dropout(0.5))
6top_model.add(Dense(nb_category, activation='softmax'))
7
8# Connect vgg16 with top_model
9model = Model(inputs=vgg16.input, outputs=top_model(vgg16.output))

Para ser honesto, no entiendo completamente la función relu especificada aquí. Por lo tanto, no creo que el contenido de este modelo sea muy útil.

A continuación, se fija el peso. Si esto no se especifica, los pesos se volverán a aprender desde el principio, pero esta vez se solucionarán.

python
1for layer in model.layers[:15]:
2 layer.trainable = False

Compila el modelo. En este momento, especifique optimizador. Esto especifica qué algoritmo usar al actualizar los parámetros.

python
1optimizer = optimizers.rmsprop(lr=5e-7, decay=5e-5)
2model.compile(loss='categorical_crossentropy',
3 optimizer=optimizer,
4 metrics=['accuracy'])

Finalmente aprendiendo. Si ModelCheckpoint se establece en devoluciones de llamada, se pueden guardar resultados intermedios. No es obligatorio.

python
1checkpoint_cb = ModelCheckpoint("snapshot/{epoch:03d}-{val_acc:.5f}.hdf5", save_best_only=True)
2
3model.fit_generator(
4 train_generator,
5 steps_per_epoch=nb_train_samples // batch_size,
6 epochs=epochs,
7 validation_data=validation_generator,
8 validation_steps=nb_validation_samples // batch_size,
9 callbacks=[checkpoint_cb])

3.2 Predecir

python
1from keras.preprocessing.image import ImageDataGenerator
2from keras import optimizers
3from keras.applications.vgg16 import VGG16
4from keras.layers import Dense, Dropout, Flatten, Input, BatchNormalization
5from keras.models import Model, Sequential, load_model
6import pandas as pd
7import numpy as np
8import os
9from pandas import DataFrame
10
11test_data_dir = "/test/"
12
13test_datagen = ImageDataGenerator(rescale=1. / 255)
14
15img_width, img_height = 200, 150
16nb_test_samples = 115474
17batch_size = 1
18nb_category = 14951
19
20test_generator = test_datagen.flow_from_directory(
21 test_data_dir,
22 target_size=(img_width, img_height),
23 batch_size=batch_size,
24 class_mode=None,
25 shuffle=False)
26
27model = load_model("model.h5")
28
29pred = model.predict_generator(
30 test_generator,
31 steps=nb_test_samples,
32 verbose=1)

No es muy diferente del código de aprendizaje. Del mismo modo, los datos se leen con flow_from_directory , pero el punto a tener en cuenta es que se requieren subcarpetas incluso para los datos de prueba (= clases desconocidas). Por ejemplo, en la siguiente configuración, no funcionará a menos que organice los datos en subcarpetas.

javascript
1data/
2 test/
3 sub/
4 aaa.jpg
5 bbb.jpg
6 ...

Como la clase es desconocida, establezca class_mode como None .

4 Resumen

  • Entendí cómo usar vgg16 con Keras.
  • Cargue datos a gran escala con flow_from_directory .
  • Tenga en cuenta que también necesita subcarpetas para la predicción.

5 referencia

Footnotes

  1. Keras Documentation

  2. Building powerful image classification models using very little data

Compartir:

Artículos relacionados

Aplicación de Android CI/CD con Flutter
Guides

Aplicación de Android CI/CD con Flutter

Aprenda a construir pipelines CI/CD para apps Android con Flutter. Basado en GitHub Actions, sin usar fastlane.

mark241