Nota: Este artículo es una traducción del original que aparece en HACKERNOON: Deep Learning for Noobs [Part 2]
Muchas gracias al autor Debarko De por permitir su publicación en español.
Muchas gracias al autor Debarko De por permitir su publicación en español.
Aprendizaje profundo para
principiantes (Parte 2)
¿Cómo podemos configurar nuestra propia red neuronal
convolucional? En esta exposición vamos a tratar de responder a esta pregunta.
Trabajaremos sobre el problema de segmentación de imágenes que discutimos en la
primera parte de
esta serie.
Hay muchas bibliotecas disponibles para crear una red
neuronal convolucional. Elegimos Keras y Tensorflow. La primera pregunta que viene a la mente es:
¿Por qué estos dos en concreto? ¿Por qué no sólo
Tensorflow?
En lo que sería la biblioteca general de aprendizaje
automático hay muchas bibliotecas. Tensorflow, Theano, PyTorch, Caffe y Torch
son algunas de los más importantes. Desde aquí quiero expresar el profundo
reconocimiento a PyTorch gracias a Soumith Chintala y a su equipo, que han creado una biblioteca
impresionante. Esperemos que se puedan hacer cargo del mundo (** sonrisa
maliciosa **).
Todas ellas son bibliotecas de bajo nivel. Lo que
implica tener que acelerar los procesos mediante GPU o CPU y optimizar cálculos
matriciales. Por lo tanto, construir redes que utilicen estas bibliotecas
podría convertirse en un importante reto. Keras es una biblioteca de alto
nivel. Ayuda a crear capas neuronales y
simplifica las complejidades de las operaciones de cálculo. Keras trabaja con
Theano o Tensorflow como respaldo. He elegido Tensorflow como respaldo porque
tiene un mejor apoyo de la comunidad.
KEras & TEnsorflow (KETE) es la combinación
perfecta.
Instalación
Vamos a decidir los componentes que hay que instalar. Y
lo vamos a ir haciendo según avanzamos. Los sistemas tradicionales se
eternizarían entrenando conjuntos de datos. Así que vamos a conseguir un
servidor AWS. Si disponemos de un equipo para videojuegos podemos programarlo
en local. Utilizaremos el sistema g2.2xLarge de AWS. Tiene 26 núcleos de GPU y
cuesta 0,65 dólares / hora. ¿Por qué lo elegimos? Nos decidimos por él porque
es el sistema de GPU más barato disponible en la nube, y funcionará mejor que
la mayor parte del hardware que tengamos en casa. Lo siguiente es decidir el
sistema operativo que vamos a emplear. Definitivamente tiene sentido utilizar
Ubuntu 16.04 LTS pero ¡un momento! Vamos a utilizar una AMI pre-horneado que
tiene un montón de herramientas incorporadas. De esta manera podemos dejar
acabada la mayor parte de la configuración. Busquemos Deep Learning AMI de AWS.
Hay otras buenas AMIs en aprendizaje automático que se pueden encontrar en la
red. Necesitamos que Python 2.7 y Tensorflow estén instalados al menos en la
AMI.
Instancia GPU y aprendizaje profundo AMI en AWS
Después de seleccionar el
tipo de instancia (máquina virtual de Amazon) y la AMI hay que crear una clave.
Puede utilizar cualquier clave que ya tenga preparada. Pero para este caso
crearemos una. Vamos a utilizar una clave con el siguiente nombre: deepkey.pem.
Descargue la clave y guárdela en un lugar seguro. Inicie la instancia. Para
crearla se necesitan entre 5 y 10 minutos. Mientras tanto, hay que cambiar el
permiso de la clave a 400. De lo contrario ssh no le permitirá iniciar sesión.
Chmod 400 ~ / deepkey.pem
A continuación, hay que ir a la lista de instancias de
EC2. Desde allí, seleccionar la instancia que se ha creado. Hay que copiar la
DNS pública de la instancia de AWS. Se parecerá a esto:
ec2-52-24-183-62.us-west-2.compute.amazonaws.com
# A continuación entramos en el sistema
Ssh ec2-user@ec2-52-24-183-62.us-west-2.compute.amazonaws.com -i ~ / deepkey.pem
Ssh ec2-user@ec2-52-24-183-62.us-west-2.compute.amazonaws.com -i ~ / deepkey.pem
# La AMI podría estar desafasada por lo que siempre es mejor
ponerla al día
Sudo yum update
Sudo yum update
#
Instalamos pip para obtener Keras
sudo yum install python-pip
sudo yum install python-pip
#
Actualizamos el pip master instalado
sudo /usr/local/bin/pip install — upgrade pip
sudo /usr/local/bin/pip install — upgrade pip
#
Instalamos Keras
sudo /usr/local/bin/pip install keras
sudo /usr/local/bin/pip install keras
Por defecto, la configuración básica Keras se instala
con Theano. Vamos a usar Tensorflow. Así que vamos a cambiarlo. Abrir ~ /
.keras / keras.conf y actualizarlo como se muestra a continuación. El archivo
se debe ver como se muestra en la sección siguiente.
{
“image_dim_ordering”: “tf”,
“epsilon”: 1e-07,
“floatx”: “float32”,
“backend”: “tensorflow”
}
“image_dim_ordering”: “tf”,
“epsilon”: 1e-07,
“floatx”: “float32”,
“backend”: “tensorflow”
}
Espero que todos los pasos se hayan seguido sin cometer
errores. Vamos ahora a probar nuestra instalación. Abrimos python y luego
importamos keras para probarlo. La salida debe tener un aspecto como el que se
muestra a continuación.
Prueba de instalación Keras
Así que ahora tenemos Python, Tensorflow y Keras
instalados. La AMI también proporciona Theano y otros recursos pre instalados,
pero no los vamos a utilizar. No es necesario desinstalarlos ya que no
interfieren en el funcionamiento. Terminada la instalación, vayamos con el
código.
No hay que perder el tiempo en la instalación, sino que
hay que aprovecharlo en aprender y en
realizar la implementación.
Vamos a entrenar una red que podamos usar para
clasificar imágenes de perros y gatos de Kaggle. Antes de esto comenzaremos a
escribir un modelo sencillo. Esto ayudará a entender cómo funciona Keras.
Comenzaré con el código. Si lo observamos, hay comentarios antes de cada línea
de código. Estos comentarios explican en cierta medida lo que sucede en esa
línea particular de código. Para ejecutar el código, se puede utilizar
cualquier base de datos conteniendo imágenes de perros y gatos, o podemos
descargar los datos de la muestra de Kaggle. Para poder descargar los datos de
la muestra es necesario registrarse en Kaggle. Aquí está el enlace de Kaggle.
from keras.preprocessing.image import ImageDataGenerator
from keras.models import Sequential
from keras.layers import Convolution2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
# tamaño esperado de la imagen
img_width, img_height = 150, 150
from keras.models import Sequential
from keras.layers import Convolution2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense
# tamaño esperado de la imagen
img_width, img_height = 150, 150
# carpeta que contiene las imágenes sobre
# las que se entrenará la red. La carpeta de entrenamiento
# tiene dos subcarpetas, perros y gatos.
train_data_dir = 'data/train'
# las que se entrenará la red. La carpeta de entrenamiento
# tiene dos subcarpetas, perros y gatos.
train_data_dir = 'data/train'
# carpeta que contiene las muestras de validación
# la estructura de la carpeta es la misma que la de la carpeta de entrenamiento
validation_data_dir = 'data/validation'
# la estructura de la carpeta es la misma que la de la carpeta de entrenamiento
validation_data_dir = 'data/validation'
# número de imágenes que se consideran para el entrenamiento
train_samples = 2000
train_samples = 2000
# número de imágenes se utilizan en la validación
validation_samples = 800
validation_samples = 800
# número de veces que se ejecutará la red # sobre el conjunto de
entrenamiento antes
# de empezar con la validación
epoch = 50
# de empezar con la validación
epoch = 50
# ** Inicio del modelo **
model = Sequential()
model.add(Convolution2D(32, 3, 3, input_shape=(3, img_width, img_height)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Convolution2D(32, 3, 3))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Convolution2D(64, 3, 3))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(1))
model.add(Activation('sigmoid'))
# ** Fin del modelo **
model = Sequential()
model.add(Convolution2D(32, 3, 3, input_shape=(3, img_width, img_height)))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Convolution2D(32, 3, 3))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Convolution2D(64, 3, 3))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Flatten())
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(1))
model.add(Activation('sigmoid'))
# ** Fin del modelo **
model.compile(loss='binary_crossentropy',
optimizer='rmsprop',
metrics=['accuracy'])
# esta es la mejora de la configuración que utilizaremos para el entrenamiento
# en el que generamos un gran número de imágenes transformadas de manera que el
# modelo puede tratar con una gran variedad de escenarios del mundo real
train_datagen = ImageDataGenerator(
rescale=1./255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
# esta es la mejora de la configuración que utilizaremospara la prueba:
# sólo para reajuste
test_datagen = ImageDataGenerator(rescale=1./255)
optimizer='rmsprop',
metrics=['accuracy'])
# esta es la mejora de la configuración que utilizaremos para el entrenamiento
# en el que generamos un gran número de imágenes transformadas de manera que el
# modelo puede tratar con una gran variedad de escenarios del mundo real
train_datagen = ImageDataGenerator(
rescale=1./255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
# esta es la mejora de la configuración que utilizaremospara la prueba:
# sólo para reajuste
test_datagen = ImageDataGenerator(rescale=1./255)
# esta sección toma imágenes de la carpeta
# y las pasa al ImageGenerator que crea entonces
# un gran número de versiones transformadas
train_generator = train_datagen.flow_from_directory(
train_data_dir,
target_size=(img_width, img_height),
batch_size=32,
class_mode='binary')
validation_generator = test_datagen.flow_from_directory(
validation_data_dir,
target_size=(img_width, img_height),
batch_size=32,
class_mode='binary')
# y las pasa al ImageGenerator que crea entonces
# un gran número de versiones transformadas
train_generator = train_datagen.flow_from_directory(
train_data_dir,
target_size=(img_width, img_height),
batch_size=32,
class_mode='binary')
validation_generator = test_datagen.flow_from_directory(
validation_data_dir,
target_size=(img_width, img_height),
batch_size=32,
class_mode='binary')
# aquí es donde se produce el proceso real
# y llevará algún tiempo ejecutar este paso.
model.fit_generator(
train_generator,
samples_per_epoch=train_samples,
nb_epoch=epoch,
validation_data=validation_generator,
nb_val_samples=validation_samples)
model.save_weights('trial.h5')
# y llevará algún tiempo ejecutar este paso.
model.fit_generator(
train_generator,
samples_per_epoch=train_samples,
nb_epoch=epoch,
validation_data=validation_generator,
nb_val_samples=validation_samples)
model.save_weights('trial.h5')
El código es autoexplicativo. Se puede reemplazar la
sección entre 'Inicio del modelo' y 'Final del modelo' para usar otros modelos.
Tendremos nuestro propio código clasificador, y yo serviré de guía en el
código.
Primero importamos algunas dependencias de Keras. A
continuación, definimos las dimensiones de la imagen que pasará a la red.
Después de eso informamos el código donde están los conjuntos de imágenes: el
conjunto de datos de entrenamiento y el conjunto de datos de validación.
Después se construye el modelo desde el principio hasta el final. No voy a
entrar en profundidad en el modelo, ya que es una implementación VGGNet
estándar. Los detalles sobre la arquitectura de red se pueden encontrar en el
siguiente documento arXiv:
Very Deep Convolutional Networks for Large-Scale
Image Recognition
K. Simonyan, A. Zisserman
arXiv:1409.1556
K. Simonyan, A. Zisserman
arXiv:1409.1556
A continuación, el código genera transformaciones en los
datos. Aquí se puede acortar, estirar, inclinar el conjunto de datos para que
la red no entre en sobre entrenamiento. Creamos generadores para que el código
pueda leer imágenes de las carpetas especificadas. Después se inicia el
procesamiento. El sistema realiza el entrenamiento y la validación el número
veces que se mencionan en 'epoch'. Finalmente almacenamos estos pesos para usarlos en el futuro y evitar que la red
tenga que entrenarse de nuevo. Si tiene
dudas, por favor, decídase y
formule las preguntas que considere. Intentaré contestarlas según mi
leal saber y entender.
El modelo anterior es sencillo y sólo existe por una
explicación más sencilla aún. La clasificación de gatos y perros podría no
tener tanto éxito debido a la cantidad de datos que tenemos. Así que tenemos
que acudir al aprendizaje de transferencia. En el aprendizaje de transferencia
trabajamos en modelos que entrenamos para resolver cuestiones similares.
Tomamos los pesos de entrenamiento y los reutilizamos para resolver cuestiones
completamente diferentes. Entrenamos modelos que pre-entrenamos sobre imágenes
para clasificar diferentes cosas. ¿Por qué funciona esto? Es porque el modelo
que vamos a utilizar fue entrenado para hacer la clasificación de imágenes. Las
capas más profundas siempre serán capaces de clasificar de forma genérica, y
trabajarán en el nivel de detección de bordes y curvas. De ahí el término
transferencia de aprendizaje, ya que se transfiere el aprendizaje del
planteamiento de un problema al de otro problema distinto. Esto podría
funcionar bien en nuestro caso. Pero podemos hacer que funcione mejor. A continuación
entrenamos las capas superiores. Estas capas realmente se preocupan por los
elementos reales que se clasifican. Las entrenamos con nuestro conjunto de
datos de entrenamiento. Podemos llamar a este conjunto de datos dominio
específico. Esto le permite a la red comprender que es exactamente lo que
queremos clasificar. Así que el código es el siguiente:
import os
import h5py
import numpy as np
from keras.preprocessing.image import ImageDataGenerator
from keras import optimizers
from keras.models import Sequential
from keras.layers import Convolution2D, MaxPooling2D, ZeroPadding2D
from keras.layers import Activation, Dropout, Flatten, Dense
# ruta a los archivos de pesos del modelo.
weights_path = 'vgg16_weights.h5'
top_model_weights_path = 'fc_model.h5'
# dimensiones de las imágenes.
img_width, img_height = 150, 150
train_data_dir = 'data/train'
validation_data_dir = 'data/validation'
nb_train_samples = 2000
nb_validation_samples = 800
nb_epoch = 50
# creación de la red VGG16
model = Sequential()
model.add(ZeroPadding2D((1, 1), input_shape=(3, img_width, img_height)))
model.add(Convolution2D(64, 3, 3, activation='relu', name='conv1_1'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(64, 3, 3, activation='relu', name='conv1_2'))
model.add(MaxPooling2D((2, 2), strides=(2, 2)))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(128, 3, 3, activation='relu', name='conv2_1'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(128, 3, 3, activation='relu', name='conv2_2'))
model.add(MaxPooling2D((2, 2), strides=(2, 2)))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(256, 3, 3, activation='relu', name='conv3_1'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(256, 3, 3, activation='relu', name='conv3_2'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(256, 3, 3, activation='relu', name='conv3_3'))
model.add(MaxPooling2D((2, 2), strides=(2, 2)))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(512, 3, 3, activation='relu', name='conv4_1'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(512, 3, 3, activation='relu', name='conv4_2'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(512, 3, 3, activation='relu', name='conv4_3'))
model.add(MaxPooling2D((2, 2), strides=(2, 2)))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(512, 3, 3, activation='relu', name='conv5_1'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(512, 3, 3, activation='relu', name='conv5_2'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(512, 3, 3, activation='relu', name='conv5_3'))
model.add(MaxPooling2D((2, 2), strides=(2, 2)))
# cargar los pesos de las redes VGG16 networks
# (entrenadas sobre ImageNet, ganaron la competición ILSVRC en 2014)
# nota: cuando hay una correspondencia completa entre la definición del modelo
# y el archivo de pesos, se puede llamar a model.load_weights(filename)
imponer os.path.exists(weights_path), 'Los pesos del modelo no se encuentran (ver la variable "weights_path" en el script).'
f = h5py.File(weights_path)
for k in range(f.attrs['nb_layers']):
if k >= len(model.layers):
# no miramos las últimas capas (completamente conectadas) del archivo
break
g = f['layer_{}'.format(k)]
weights = [g['param_{}'.format(p)] for p in range(g.attrs['nb_params'])]
model.layers[k].set_weights(weights)
f.close()
print('Model loaded.')
# creación de un modelo clasificador para situarlo encima del modelo convolucional top_model = Sequential()
top_model.add(Flatten(input_shape=model.output_shape[1:]))
top_model.add(Dense(256, activation='relu'))
top_model.add(Dropout(0.5))
top_model.add(Dense(1, activation='sigmoid'))
# hay que notar que es necesario empezar con un clasificador
# completamente entrenado, incluyendo el clasificador situado arriba,
# para realizar con éxito un ajuste fino
top_model.load_weights(top_model_weights_path)
# añadir el modelo en la parte superior de la base convolucional
model.add(top_model)
# establecer las primeras 25 capas (hasta el último bloque de convolución)
# a las no entrenables (los pesos no se actualizarán)
for layer in model.layers[:25]:
layer.trainable = False
# compilar el modelo con un SDG/ momento optimizador
# y a una tasa de aprendizaje muy baja.
model.compile(loss='binary_crossentropy',
optimizer=optimizers.SGD(lr=1e-4, momentum=0.9),
metrics=['accuracy'])
# preparación de los datos de mejora de la configuración
train_datagen = ImageDataGenerator(
rescale=1./255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
test_datagen = ImageDataGenerator(rescale=1./255)
train_generator = train_datagen.flow_from_directory(
train_data_dir,
target_size=(img_height, img_width),
batch_size=32,
class_mode='binary')
validation_generator = test_datagen.flow_from_directory(
validation_data_dir,
target_size=(img_height, img_width),
batch_size=32,
class_mode='binary')
# ajuste fino del modelo
model.fit_generator(
train_generator,
samples_per_epoch=nb_train_samples,
nb_epoch=nb_epoch,
validation_data=validation_generator,
nb_val_samples=nb_validation_samples)
import h5py
import numpy as np
from keras.preprocessing.image import ImageDataGenerator
from keras import optimizers
from keras.models import Sequential
from keras.layers import Convolution2D, MaxPooling2D, ZeroPadding2D
from keras.layers import Activation, Dropout, Flatten, Dense
# ruta a los archivos de pesos del modelo.
weights_path = 'vgg16_weights.h5'
top_model_weights_path = 'fc_model.h5'
# dimensiones de las imágenes.
img_width, img_height = 150, 150
train_data_dir = 'data/train'
validation_data_dir = 'data/validation'
nb_train_samples = 2000
nb_validation_samples = 800
nb_epoch = 50
# creación de la red VGG16
model = Sequential()
model.add(ZeroPadding2D((1, 1), input_shape=(3, img_width, img_height)))
model.add(Convolution2D(64, 3, 3, activation='relu', name='conv1_1'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(64, 3, 3, activation='relu', name='conv1_2'))
model.add(MaxPooling2D((2, 2), strides=(2, 2)))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(128, 3, 3, activation='relu', name='conv2_1'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(128, 3, 3, activation='relu', name='conv2_2'))
model.add(MaxPooling2D((2, 2), strides=(2, 2)))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(256, 3, 3, activation='relu', name='conv3_1'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(256, 3, 3, activation='relu', name='conv3_2'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(256, 3, 3, activation='relu', name='conv3_3'))
model.add(MaxPooling2D((2, 2), strides=(2, 2)))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(512, 3, 3, activation='relu', name='conv4_1'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(512, 3, 3, activation='relu', name='conv4_2'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(512, 3, 3, activation='relu', name='conv4_3'))
model.add(MaxPooling2D((2, 2), strides=(2, 2)))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(512, 3, 3, activation='relu', name='conv5_1'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(512, 3, 3, activation='relu', name='conv5_2'))
model.add(ZeroPadding2D((1, 1)))
model.add(Convolution2D(512, 3, 3, activation='relu', name='conv5_3'))
model.add(MaxPooling2D((2, 2), strides=(2, 2)))
# cargar los pesos de las redes VGG16 networks
# (entrenadas sobre ImageNet, ganaron la competición ILSVRC en 2014)
# nota: cuando hay una correspondencia completa entre la definición del modelo
# y el archivo de pesos, se puede llamar a model.load_weights(filename)
imponer os.path.exists(weights_path), 'Los pesos del modelo no se encuentran (ver la variable "weights_path" en el script).'
f = h5py.File(weights_path)
for k in range(f.attrs['nb_layers']):
if k >= len(model.layers):
# no miramos las últimas capas (completamente conectadas) del archivo
break
g = f['layer_{}'.format(k)]
weights = [g['param_{}'.format(p)] for p in range(g.attrs['nb_params'])]
model.layers[k].set_weights(weights)
f.close()
print('Model loaded.')
# creación de un modelo clasificador para situarlo encima del modelo convolucional top_model = Sequential()
top_model.add(Flatten(input_shape=model.output_shape[1:]))
top_model.add(Dense(256, activation='relu'))
top_model.add(Dropout(0.5))
top_model.add(Dense(1, activation='sigmoid'))
# hay que notar que es necesario empezar con un clasificador
# completamente entrenado, incluyendo el clasificador situado arriba,
# para realizar con éxito un ajuste fino
top_model.load_weights(top_model_weights_path)
# añadir el modelo en la parte superior de la base convolucional
model.add(top_model)
# establecer las primeras 25 capas (hasta el último bloque de convolución)
# a las no entrenables (los pesos no se actualizarán)
for layer in model.layers[:25]:
layer.trainable = False
# compilar el modelo con un SDG/ momento optimizador
# y a una tasa de aprendizaje muy baja.
model.compile(loss='binary_crossentropy',
optimizer=optimizers.SGD(lr=1e-4, momentum=0.9),
metrics=['accuracy'])
# preparación de los datos de mejora de la configuración
train_datagen = ImageDataGenerator(
rescale=1./255,
shear_range=0.2,
zoom_range=0.2,
horizontal_flip=True)
test_datagen = ImageDataGenerator(rescale=1./255)
train_generator = train_datagen.flow_from_directory(
train_data_dir,
target_size=(img_height, img_width),
batch_size=32,
class_mode='binary')
validation_generator = test_datagen.flow_from_directory(
validation_data_dir,
target_size=(img_height, img_width),
batch_size=32,
class_mode='binary')
# ajuste fino del modelo
model.fit_generator(
train_generator,
samples_per_epoch=nb_train_samples,
nb_epoch=nb_epoch,
validation_data=validation_generator,
nb_val_samples=nb_validation_samples)
Los pesos para VGG16 se pueden conseguir en mi Github. También se puede conseguir el archivo de pesos del
fc_model ejecutando este programa sobre el conjunto de datos dataset. Se puede utilizar el mismo
conjunto de pesos del enlace compartido VGG16. Se puede ajustar el número
de epoch para
conseguir un mejor aprendizaje, pero tener cuidado porque esto podría llevar a
la sobrealimentación. Yo he utilizado esta técnica en una gran cantidad de
casos prácticos en mi trabajo. Un caso práctico es distinguir entre prescripciones y no
prescripciones. Utilizamos exactamente el mismo modelo entrenado en los datos
de ImageNet de gatos y perros para clasificar las recetas. Espero que lo puedan
usar en casos prácticos en el mundo real. Comuníquenos cualquier caso
interesante que haya resuelto utilizando este método.
Puede seguirme en twitter y también puede registrarse en una pequeña lista
de correo mailing list. Si le ha gustado
este artículo, pulse el botón ❤ para recomendarlo. Esto ayudará a otros
usuarios de Medium a encontrarlo.