Глубоко и интересно | 22 DeepDream

искусственный интеллект TensorFlow GitHub
Глубоко и интересно | 22 DeepDream

Введение

Познакомить с принципом DeepDream и реализовать его с помощью TensorFlow.

Эффект

Давайте сначала посмотрим на эффект DeepDream, изначально это была такая картинка

DeepDream处理之前的天空

После обработки DeepDream может стать так

DeepDream处理之后的天空

Немного странное и мечтательное, а также немного неизвестное духовное загрязнение

принцип

Большую часть времени мы обучаем и настраиваем параметры сети на основе заданных данных и меток.

Однако иногда мы исправим параметры сети и отрегулируйте входные данные в соответствии с определенной функцией потери. Например, в передаче стиля изображения мы регулируем синтезированное изображение в соответствии с функцией потери содержимого и функцией потери стилей.

Для обычных моделей классификации изображений введите изображение, и каждый тензор в сети выдаст соответствующее значение ответа.Чем больше значение, тем больше тензору «нравится» изображение.

Например, если вы вводите изображение собаки, тензор, используемый для идентификации и классификации собак в сети, выдаст большее значение ответа.

Установите цель оптимизации, чтобы максимизировать значение отклика тензора для настройки входного изображения, что является принципом DeepDream.

Например, чтобы удовлетворить тензор, который любит собак, мы корректируем и увеличиваем некоторые подсказки, такие как собаки на исходной картинке, чтобы значение отклика этого тензора было больше.

выполнить

загрузить библиотеку

# -*- coding: utf-8 -*-

import tensorflow as tf
import numpy as np
import cv2
from imageio import imread, imsave, mimsave
import matplotlib.pyplot as plt
%matplotlib inline
from scipy.ndimage.filters import gaussian_filter

Загрузите модель классификации изображений, которая используется здесьinception5h

layer_names = ['conv2d0', 'conv2d1', 'conv2d2', 
               'mixed3a', 'mixed3b', 'mixed4a', 'mixed4b', 'mixed4c', 'mixed4d', 'mixed4e',
               'mixed5a', 'mixed5b']

graph = tf.Graph()
with graph.as_default():
    with tf.gfile.FastGFile('inception5h.pb', 'rb') as f:
        graph_def = tf.GraphDef()
        graph_def.ParseFromString(f.read())
        tf.import_graph_def(graph_def, name='')
    X = graph.get_tensor_by_name('input:0')
    layers = [graph.get_tensor_by_name(name + ':0') for name in layer_names]
    
    all_layers_names = [tensor.name for tensor in tf.get_default_graph().as_graph_def().node]
    print(all_layers_names)

sess = tf.Session(graph=graph)

Определите функцию для получения тензора градиента и функцию для вычисления градиента исходного изображения в блоках.

def get_gradient(tensor):
    with graph.as_default():
        return tf.gradients(tf.reduce_mean(tf.square(tensor)), X)[0]

def get_tile_size(num_pixels, tile_size=400):
    num_tiles = max(1, int(round(num_pixels / tile_size)))
    return int(np.ceil(num_pixels / num_tiles))
    
def tiled_gradient(gradient, image, tile_size=400):
    grad = np.zeros_like(image)
    H, W, _ = image.shape
    
    h = get_tile_size(H, tile_size)
    h_4 = h // 4
    w = get_tile_size(W, tile_size)
    w_4 = w // 4
    
    h_start = np.random.randint(-3 * h_4, -h_4)
    while h_start < H:
        h_end = h_start + h
        h_start_lim = max(h_start, 0)
        h_end_lim = min(h_end, H)
        
        w_start = np.random.randint(-3 * w_4, -w_4)
        while w_start < W:
            w_end = w_start + w
            w_start_lim = max(w_start, 0)
            w_end_lim = min(w_end, W)
            
            g = sess.run(gradient, feed_dict={X: [image[h_start_lim: h_end_lim, w_start_lim: w_end_lim, :]]})[0]
            g /= (np.std(g) + 1e-8)
            
            grad[h_start_lim: h_end_lim, w_start_lim: w_end_lim, :] = g
            
            w_start = w_end
        
        h_start = h_end
    
    return grad

Настройте входное изображение в соответствии с градиентом, то есть DeepDream

def dream(layer_tensor, image, iteration=10, step=3.0, tile_size=400):
    img = image.copy()
    gradient = get_gradient(layer_tensor)
    
    for i in range(iteration):
        grad = tiled_gradient(gradient, img)
        
        sigma = (i * 4.0) / iteration + 0.5
        grad = gaussian_filter(grad, 0.5 * sigma) + gaussian_filter(grad, sigma) + gaussian_filter(grad, 2 * sigma)
        
        scaled_step = step / (np.std(grad) + 1e-8)
        img += grad * scaled_step
        img = np.clip(img, 0, 255)
        
    return img

Масштабируйте исходное изображение, выполняйте обработку DeepDream в нескольких масштабах и складывайте их

def recursive_dream(layer_tensor, image, repeat=3, scale=0.7, blend=0.2, iteration=10, step=3.0, tile_size=400):
    if repeat > 0:
        sigma = 0.5
        img_blur = gaussian_filter(image, (sigma, sigma, 0.0))
        
        h0 = img_blur.shape[0]
        w0 = img_blur.shape[1]
        h1 = int(scale * h0)
        w1 = int(scale * w0)
        img_downscaled = cv2.resize(img_blur, (w1, h1))
        
        img_dream = recursive_dream(layer_tensor, img_downscaled, repeat - 1, scale, blend, iteration, step, tile_size)
        img_upscaled = cv2.resize(img_dream, (w0, h0))
        
        image = blend * image + (1.0 - blend) * img_upscaled
        image = np.clip(image, 0, 255)
    
    return dream(layer_tensor, image, iteration, step, tile_size)

читать картинку

image = imread('mountain.jpg')
image = image.astype(np.float32)

Исходное изображение обрабатывается с ответными значениями тензора 12 в качестве цели оптимизации.

for i in range(len(layers)):
    print(layer_names[i])
    result = recursive_dream(layers[i], image)
    plt.figure(figsize=(10, 15))
    plt.imshow(result / 255.)
    plt.show()
    imsave('imgs/%s.jpg' % layer_names[i], result)

DeepDream результат conv2d2

conv2d2的DeepDream结果

Результаты DeepDream для mix3a

mixed3a的DeepDream结果

Результаты DeepDream для mix4c

mixed4c的DeepDream结果

Результаты DeepDream для Mixed5a

mixed5a的DeepDream结果

По мере увеличения количества слоев, на которых расположен тензор, графика, оптимизированная DeepDream, усложняется.

Помимо использования всего тензора в качестве цели, вы также можете выбрать только значение отклика фильтра для оптимизации.

Например, если вы выберете фильтр Mixed4c, вы увидите, что графики различных настроек фильтра отличаются.

for i in range(10):
    print('Filter %d of mixed4c' % i)
    result = recursive_dream(layers[7][:, :, :, i], image)
    plt.figure(figsize=(10, 15))
    plt.imshow(result / 255.)
    plt.show()
    imsave('imgs/mixed4c_filter_%d.jpg' % i, result)

Соответствующий результат filter0 для Mixed4c

mixed4c的filter0对应结果

Соответствующий результат filter8 дляmixed4c

mixed4c的filter8对应结果

Конечно, вы также можете повторно запускать DeepDream на изображении, и оптимизированная графика будет становиться все более и более очевидной.

img = image.copy()
imgs = []
for i in range(20):
    print('Iteration %d of mixed4c' % i)
    img = recursive_dream(layers[7], img)
    plt.figure(figsize=(10, 15))
    plt.imshow(img / 255.)
    plt.show()
    imgs.append(img)
mimsave('imgs/mixed4c多轮迭代结果.gif', imgs, fps=5)

Результат немного призрачный, возможно, mix4c предпочитает собак...

mixed4c多轮迭代结果

Ссылаться на

видеоурок

Глубоко и интересно (1)