Google deep dream - Tutorial práctico
DeepDream es un experimento que visualiza los patrones aprendidos por una red neuronal. Al igual que cuando un niño mira nubes e intenta interpretar formas aleatorias, DeepDream sobreinterpreta y mejora los patrones que ve en una imagen.
Lo hace enviando una imagen a través de la red, luego calculando el gradiente de la imagen con respecto a las activaciones de una capa en particular. Por último, la imagen se modifica para aumentar estas activaciones, mejorando los patrones vistos por la red y dando como resultado una imagen de ensueño. Este proceso se denominó "Inceptionism" (una referencia a InceptionNet y la película Inception).
¿Cómo funciona el algoritmo del sueño profundo?
Cuando suministramos una imagen a una RNA entrenada, las neuronas se disparan y generan activaciones, el algoritmo sencillamente hace que algunas neuronas se disparen más. Es posible seleccionar qué neuronas en que capa estamos interesados en activar, y repetir este proceso hasta que la imagen de entrada contiene las características que una capa específica estaba buscando.
Pasos del algoritmo
Envíamos nuestra imagen a través de una red neuronal pre entrenada.
Se selecciona una capa a elección (las primeras capturan bordes, las capas más profundas detectan formas más completas)
Se calculan las activaciones (salidas) que salen de las capas de interés
Se calcula el gradiente de las activaciones con respecto a la imagen de entrada (ascenso del gradiente)
Se modifica la imagen para aumentar las activaciones y mejorar los patrones vistos por la red
Se repite el proceso
En el ejemplo desarrollado en el cuaderno, tendremos las siguientes secciones: carga y preprocesado de datos, definición del modelo preentrenado, definición de las capas que queremos activar, definición de la función que calcula el error y la función que lo maximiza, contrario al objetivo que tenemos comúnmente al entrenar una RN.
Cargamos el modelo base preentrenado
base_model = tf.keras.applications.InceptionV3(include_top = False, weights = 'imagenet')
Obtenemos y procesamos nuestra entrada
# get and process the data
img_1 = Image.open("/content/drive/MyDrive/COLAB NOTEBOOKS/eiffel.jpg")
img_2 = Image.open("/content/drive/MyDrive/COLAB NOTEBOOKS/mars.jpg")
image = Image.blend(img_1, img_2, 0.5)
image.save("/content/drive/MyDrive/COLAB NOTEBOOKS/img_0.jpg")
sample_image = tf.keras.preprocessing.image.load_img("/content/drive/MyDrive/COLAB NOTEBOOKS/img_0.jpg")
sample_image = tf.keras.preprocessing.image.img_to_array(sample_image)
sample_image = sample_image/255.0
sample_image = tf.expand_dims(sample_image, axis = 0)
Elegimos las capas de la RN preentrenada y creamos nuestro modelo
layer_names = ['mixed3', 'mixed5', 'mixed7']
layers = [base_model.get_layer(name).output for name in layer_names]
deepdream_model = tf.keras.Model(inputs = base_model.input, outputs = layers)
activations = deepdream_model(sample_image)
El siguiente bloque calcula la pérdida
def calculate_loss(image, model):
img_batch = tf.expand_dims(image, axis=0)
layer_activations = model(img_batch)
print('Activation values (layer output) \n', layer_activations)
losses = []
for act in layer_activations:
loss = tf.math.reduce_mean(act)
losses.append(loss)
print('Losses (from multiple activations layers) = ', losses)
print('Losses shape', np.shape(losses))
print('Sum of all losses', tf.reduce_sum(losses))
return tf.reduce_sum(losses) # gets the sum
loss = calculate_loss(tf.Variable(sample_image), deepdream_model)
Calculamos el gradiente ascendente:
# ascend gradient
@tf.function
def deepdream(model, image, step_size):
with tf.GradientTape() as tape:
tape.watch(image)
loss = calculate_loss(image, model)
gradients = tape.gradient(loss, image)
print('Gradients =\n', gradients)
print('Gradients shape =\n', np.shape(gradients))
gradients = tf.math.reduce_std(gradients)
# excite the layers
# we can do it adding directly the gradients (because they have the same shape)
image = image + gradients * step_size
image = tf.clip_by_value(image, -1, 1)
return loss, image
Corremos el modelo:
def run_deepdream(model, image, steps = 100, step_size = 0.01):
image = tf.keras.applications.inception_v3.preprocess_input(image)
deprocess = lambda image : tf.cast((255*(image+1.0)/2), tf.uint8)
for step in range(steps):
loss, image = deepdream(model, image, step_size)
if step % 100 == 0:
plt.figure(figsize=(12,12))
plt.imshow(deprocess(image))
plt.show()
print("Step {}, loss {}".format(step, loss))
#clear_output(wait=True)
plt.figure(figsize=(12,12))
plt.imshow(deprocess(image))
plt.show()
return deprocess(image)
Puede encontrar el código relacionado acá.