deep learning - online - Google Deep Dream-Usa clases para "controlar los sueños"
deep dream google (0)
Fondo
He estado jugando con Deep Dream
y Inceptionism
, utilizando el marco de Caffe
para visualizar las capas de GoogLeNet
, una arquitectura construida para el proyecto Imagenet
, una gran base de datos visual diseñada para usar en el reconocimiento visual de objetos.
Imagenet
se puede encontrar aquí: Imagenet 1000 Clases.
Para explorar la arquitectura y generar ''sueños'', estoy usando tres cuadernos:
https://github.com/kylemcdonald/deepdream/blob/master/dream.ipynb
https://github.com/auduno/deepdraw/blob/master/deepdraw.ipynb
La idea básica aquí es extraer algunas características de cada canal en una capa específica del modelo o de una imagen de "guía".
Luego ingresamos una imagen que deseamos modificar en el modelo y extraemos las entidades en la misma capa especificada (para cada octava), mejorando las mejores características coincidentes, es decir, el producto de punto más grande de los dos vectores de características.
Hasta ahora he logrado modificar las imágenes de entrada y controlar los sueños utilizando los siguientes métodos:
- (a) aplicar capas como objetivos
''end''
para la optimización de la imagen de entrada. (ver visualización de características )- (b) usar una segunda imagen para guiar el objetivo de optimización en la imagen de entrada.
- (c) visualizar las clases del modelo
Googlenet
generadas a partir del ruido .
Sin embargo, el efecto que quiero lograr se encuentra entre estas técnicas, de las cuales no he encontrado ninguna documentación, papel o código.
Resultado deseado
Para que una sola clase o unidad que pertenezca a una capa
''end''
(a) guíe el objetivo de optimización (b) y visualice esta clase (c) en la imagen de entrada:
Un ejemplo donde class = ''face''
y input_image = ''clouds.jpg''
:
tenga en cuenta: la imagen anterior se generó utilizando un modelo para el reconocimiento facial, que no se entrenó en el conjunto de datos Imagenet
. Sólo para fines de demostración.
Código de trabajo
Enfoque (a)
from cStringIO import StringIO
import numpy as np
import scipy.ndimage as nd
import PIL.Image
from IPython.display import clear_output, Image, display
from google.protobuf import text_format
import matplotlib as plt
import caffe
model_name = ''GoogLeNet''
model_path = ''models/dream/bvlc_googlenet/'' # substitute your path here
net_fn = model_path + ''deploy.prototxt''
param_fn = model_path + ''bvlc_googlenet.caffemodel''
model = caffe.io.caffe_pb2.NetParameter()
text_format.Merge(open(net_fn).read(), model)
model.force_backward = True
open(''models/dream/bvlc_googlenet/tmp.prototxt'', ''w'').write(str(model))
net = caffe.Classifier(''models/dream/bvlc_googlenet/tmp.prototxt'', param_fn,
mean = np.float32([104.0, 116.0, 122.0]), # ImageNet mean, training set dependent
channel_swap = (2,1,0)) # the reference model has channels in BGR order instead of RGB
def showarray(a, fmt=''jpeg''):
a = np.uint8(np.clip(a, 0, 255))
f = StringIO()
PIL.Image.fromarray(a).save(f, fmt)
display(Image(data=f.getvalue()))
# a couple of utility functions for converting to and from Caffe''s input image layout
def preprocess(net, img):
return np.float32(np.rollaxis(img, 2)[::-1]) - net.transformer.mean[''data'']
def deprocess(net, img):
return np.dstack((img + net.transformer.mean[''data''])[::-1])
def objective_L2(dst):
dst.diff[:] = dst.data
def make_step(net, step_size=1.5, end=''inception_4c/output'',
jitter=32, clip=True, objective=objective_L2):
''''''Basic gradient ascent step.''''''
src = net.blobs[''data''] # input image is stored in Net''s ''data'' blob
dst = net.blobs[end]
ox, oy = np.random.randint(-jitter, jitter+1, 2)
src.data[0] = np.roll(np.roll(src.data[0], ox, -1), oy, -2) # apply jitter shift
net.forward(end=end)
objective(dst) # specify the optimization objective
net.backward(start=end)
g = src.diff[0]
# apply normalized ascent step to the input image
src.data[:] += step_size/np.abs(g).mean() * g
src.data[0] = np.roll(np.roll(src.data[0], -ox, -1), -oy, -2) # unshift image
if clip:
bias = net.transformer.mean[''data'']
src.data[:] = np.clip(src.data, -bias, 255-bias)
def deepdream(net, base_img, iter_n=20, octave_n=4, octave_scale=1.4,
end=''inception_4c/output'', clip=True, **step_params):
# prepare base images for all octaves
octaves = [preprocess(net, base_img)]
for i in xrange(octave_n-1):
octaves.append(nd.zoom(octaves[-1], (1, 1.0/octave_scale,1.0/octave_scale), order=1))
src = net.blobs[''data'']
detail = np.zeros_like(octaves[-1]) # allocate image for network-produced details
for octave, octave_base in enumerate(octaves[::-1]):
h, w = octave_base.shape[-2:]
if octave > 0:
# upscale details from the previous octave
h1, w1 = detail.shape[-2:]
detail = nd.zoom(detail, (1, 1.0*h/h1,1.0*w/w1), order=1)
src.reshape(1,3,h,w) # resize the network''s input image size
src.data[0] = octave_base+detail
for i in xrange(iter_n):
make_step(net, end=end, clip=clip, **step_params)
# visualization
vis = deprocess(net, src.data[0])
if not clip: # adjust image contrast if clipping is disabled
vis = vis*(255.0/np.percentile(vis, 99.98))
showarray(vis)
print octave, i, end, vis.shape
clear_output(wait=True)
# extract details produced on the current octave
detail = src.data[0]-octave_base
# returning the resulting image
return deprocess(net, src.data[0])
Ejecuto el código de arriba con:
end = ''inception_4c/output''
img = np.float32(PIL.Image.open(''clouds.jpg''))
_=deepdream(net, img)
Enfoque (b)
"""
Use one single image to guide
the optimization process.
This affects the style of generated images
without using a different training set.
"""
def dream_control_by_image(optimization_objective, end):
# this image will shape input img
guide = np.float32(PIL.Image.open(optimization_objective))
showarray(guide)
h, w = guide.shape[:2]
src, dst = net.blobs[''data''], net.blobs[end]
src.reshape(1,3,h,w)
src.data[0] = preprocess(net, guide)
net.forward(end=end)
guide_features = dst.data[0].copy()
def objective_guide(dst):
x = dst.data[0].copy()
y = guide_features
ch = x.shape[0]
x = x.reshape(ch,-1)
y = y.reshape(ch,-1)
A = x.T.dot(y) # compute the matrix of dot-products with guide features
dst.diff[0].reshape(ch,-1)[:] = y[:,A.argmax(1)] # select ones that match best
_=deepdream(net, img, end=end, objective=objective_guide)
y corro el código de arriba con:
end = ''inception_4c/output''
# image to be modified
img = np.float32(PIL.Image.open(''img/clouds.jpg''))
guide_image = ''img/guide.jpg''
dream_control_by_image(guide_image, end)
Enfoque fallido
Y así es como traté de acceder a clases individuales, codificando en caliente la matriz de clases y enfocándome en una (hasta ahora sin resultado):
def objective_class(dst, class=50):
# according to imagenet classes
#50: ''American alligator, Alligator mississipiensis'',
one_hot = np.zeros_like(dst.data)
one_hot.flat[class] = 1.
dst.diff[:] = one_hot.flat[class]
¿Podría complacer a alguien que me guíe en la dirección correcta aquí? Podria ser muy apreciado.