DeepDream是一种艺术性的图像修改技术,它用到了卷积神经网络学到的表示,DeepDream由Google于2015年发布。这个算法与卷积神经网络过滤器可视化技术几乎相同,都是反向运行一个卷积神经网络:对卷积神经网络的输入做梯度上升,以便将卷积神经网络靠顶部的某一层的某个过滤器激活最大化。但有以下几个简单的区别:

  • 使用DeepDream,我们尝试将所有层的激活最大化,而不是将某一层的激活最大化,因此需要同时将大量特征的可视化混合在一起
  • 不是从空白的、略微带有噪声的输入开始,而是从现有的图像开始,因此所产生的效果能够抓住已经存在的视觉模式,并以某种艺术性的方式将图像扭曲
  • 输入图像是在不同的尺度上【叫作八度(octave)】进行处理的,这可以提高可视化的质量

我们将从一个在ImageNet上预训练的卷积神经网络(Keras内置的Inception V3模型)开始

#加载预训练的Inception V3模型
from keras.applications import inception_v3
from keras import backend as K #我们不需要训练模型,所以这个命令会禁用
K.set_learning_phase(0) #构建不包括全连接层的Inception V3网络。使用预训练的ImageNet权重来加载模型
model = inception_v3.InceptionV3(weights = 'imagenet',include_top=False) 

接下来要计算损失loss,即在梯度上升过程中需要最大化的量。在第五章的过滤器可视化中,我们试图将某一层的某个过滤器的值最大化。这里,我们要将多个层的所有过滤器的激活同时最大化。具体来说,就是对一组靠近顶部的层激活的L2范数进行加权求和,然后将其最大化。选择哪些层(以及它们对最终损失的贡献)对生成的可视化结果具有很大影响,所以我们希望让这些参数变得易于配置。更靠近底部的层生成的是几何图案,而更靠近顶部的层生成的则是从中能够看出某些ImageNet类别(比如鸟或狗)的图案。我们将随意选择4层的配置,但以后一定要探索多个不同的配置

# 设置DeepDream配置
layer_contributions={
'mixed2':0.2,
'mixed3':3.,
'mixed4':2,
'mixed5':1.5,
}
#这个字典将层的名称映射为一个系数,这个系数定量表示该层激活对你要最大化的损失的贡献大小。
# 注意,层的名称硬编码在内置的inception V3应用中

  

#定义需要最大化的损失

#创建一个字典,将层的名称映射为层的实例
layer_dict = dict([(layer.name,layer) for layer in model.layers] ) #在定义损失时将层的贡献添加到这个标量变量中
loss = K.variable(0.) for layer_name in layer_contributions:
coeff = layer_contributions[layer_name] #该层激活对损失的贡献大小
activation = layer_dict[layer_name].output #获取层的输出 scaling = K.prod(K.cast(K.shape(activation),'float32')) #将该层特征的L2范数添加到loss中,为了避免出现边界伪影,损失中仅包含非边界的像素
loss += coeff * K.sum(K.square(activation[:,2:-2,2:-2,:1])) / scaling

  


layer_dict ={'input_4':
 <keras.engine.input_layer.InputLayer at 0x281714cc240>,
'conv2d_283':
<keras.layers.convolutional.Conv2D at 0x28171545240>,
...}
activation.shape: (?, ?, ?, 288)(?, ?, ?, 768)

(?, ?, ?, 768)(?, ?, ?, 768) 
loss: Tensor("add_19:0", shape=(), 
dtype=float32)


 

  

#梯度上升过程

#这个张量用于保存生成的图像,即梦境图像
dream = model.input #计算损失相对于梦境图像的梯度
grads = K.gradients(loss,dream)[0] #将梯度标准化(重要技巧)
grads /= K.maximum(K.mean(K.abs(grads)),1e-7) #给定一张输出图像,设置一个keras函数来获取损失值和梯度值
outputs = [loss,grads]
fetch_loss_and_grads = K.function([dream],outputs) def eval_loss_and_grads(x):
outs = fetch_loss_and_grads([x])
loss_value = outs[0]
grad_values = outs[1]
return loss_value,grad_values #这个函数运行itertions次梯度上升
def gradient_ascent(x,iterations,step,max_loss=None):
for i in range(iterations):
loss_value,grad_values = eval_loss_and_grads(x)
if max_loss is not None and loss_value > max_loss:
break
print('...Loss value at',i,':',loss_value)
x += step * grad_values
return x

  

最后就是实际的DeepDream算法

首先,我们来定义一个列表,里面包含的是处理图像的尺度(也叫八度)。每个连续的尺度都是前一个的1.4倍(放大40%),即首先处理小图像,然后逐渐增大图像尺寸。对于每个连续的尺度,从最小到最大,我们都需要在当前尺度运行梯度上升,以便将之前定义的损失最大化。每次运行完梯度上升之后,将得到的图像放大40%。

在每次连续的放大之后(图像会变得模糊或像素化),为避免丢失大量图像细节,我们可以使用一个简单的技巧:每次放大之后,将丢失的细节重新注入到图像中。这种方法是可行的,因为我们知道原始图像放大到这个尺寸应该是什么样子。

给定一个较小的图像尺寸S和一个较大的图像尺寸L,你可以计算将原始图像大小调整为L与将原始图像大小调整为S之间的区别,这个区别可以定量描述从S到L的细节损失。

#辅助函数
import scipy
from keras.preprocessing import image def resize_img(img,size):
img = np.copy(img)
factors=(1,
float(size[0])/img.shape[1],
float(size[1])/img.shape[2],
1)
return scipy.ndimage.zoom(img,factors,order=1) def save_img(img,fname):
pil_img = deprocess_image(np.copy(img))
scipy.misc.imsave(fname,pil_img) def preprocess_image(image_path):
img = image.load_img(image_path)#打开图片
img = image.img_to_array(img)#把图片转成array形式
img = np.expand_dims(img,axis=0)#改变图像大小
img = inception_v3.preprocess_input(img)#将图像格式转换为Inception V3模型能够处理的张量
return img def deprocess_image(x): #通用函数,将一个张量转换为有效图像
if K.image_data_format() == 'channels_first':
x = x.reshape((3,x.shape[2],x.shape[3]))
x = x.transpose((1,2,0))
else:
x = x.reshape((x.shape[1],x.shape[2],3)) #对inception_v3.preprocess_input所做的预处理进行反向操作
x /= 2.
x += 0.5
x *= 255.
x = np.clip(x,0,255).astype('uint8')
return x

  

#在多个连续尺度上运行梯度上升
import numpy as np step = 0.01 #步长
num_octave = 3 #运行梯度上升的尺度个数
octave_scale = 1.4 #两个尺度之间的大小比例
iterations = 20 #在每个尺度上运行梯度上升的步数 max_loss = 10. #如果损失增大到大于10,我们要中断梯度上升的过程,以避免得到丑陋的伪影
base_image_path = 'IU.jpeg' #将这个变量修改为你要使用的图像的路径 img = preprocess_image(base_image_path)#将基础图像加载成一个numpy数组 original_shape = img.shape[1:3] #img.shape = (1, 776, 1200, 3)
successive_shapes = [original_shape] #[(776, 1200)]
for i in range(1,num_octave):
#准备一个由形状元组组成的列表,它定义了运行梯度上升的不同尺度
shape = tuple([int(dim/(octave_scale ** i)) for dim in original_shape])
successive_shapes.append(shape) #[(776, 1200), (554, 857), (395, 612)] successive_shapes = successive_shapes[::-1] #将形状列表反转,变为升序 original_img = np.copy(img)
shrunk_original_img = resize_img(img,successive_shapes[0])#将图像numpy数组的大小缩放到最小尺寸 for shape in successive_shapes:
print('Processing image shape',shape)
img = resize_img(img,shape)#将梦境图像放大
img = gradient_ascent(img,
iterations = iterations,
step = step,
max_loss = max_loss)
upscaled_shrunk_original_img = resize_img(shrunk_original_img,shape)
same_size_original = resize_img(original_img,shape)
lost_detail = same_size_original - upscaled_shrunk_original_img img += lost_detail
shrunk_original_img = resize_img(original_img,shape)
save_img(img,fname='dream_at_scale_'+str(shape)+'.png') save_img(img,fname='final_dream.png')

训练损失:

原图 效果图

4.keras实现-->生成式深度学习之DeepDream的更多相关文章

  1. 4.keras实现-->生成式深度学习之用变分自编码器VAE生成图像(mnist数据集和名人头像数据集)

    变分自编码器(VAE,variatinal autoencoder)   VS    生成式对抗网络(GAN,generative adversarial network) 两者不仅适用于图像,还可以 ...

  2. 4.keras实现-->生成式深度学习之用GAN生成图像

    生成式对抗网络(GAN,generative adversarial network)由Goodfellow等人于2014年提出,它可以替代VAE来学习图像的潜在空间.它能够迫使生成图像与真实图像在统 ...

  3. 从零开始学会GAN 0:第一部分 介绍生成式深度学习(连载中)

    本书的前四章旨在介绍开始构建生成式深度学习模型所需的核心技术.在第1章中,我们将首先对生成式建模领域进行广泛的研究,并从概率的角度考虑我们试图解决的问题类型.然后,我们将探讨我们的基本概率生成模型的第 ...

  4. 转:TensorFlow和Caffe、MXNet、Keras等其他深度学习框架的对比

    http://geek.csdn.net/news/detail/138968 Google近日发布了TensorFlow 1.0候选版,这第一个稳定版将是深度学习框架发展中的里程碑的一步.自Tens ...

  5. [AI开发]centOS7.5上基于keras/tensorflow深度学习环境搭建

    这篇文章详细介绍在centOS7.5上搭建基于keras/tensorflow的深度学习环境,该环境可用于实际生产.本人现在非常熟练linux(Ubuntu/centOS/openSUSE).wind ...

  6. 分别基于TensorFlow、PyTorch、Keras的深度学习动手练习项目

    ×下面资源个人全都跑了一遍,不会出现仅是字符而无法运行的状况,运行环境: Geoffrey Hinton在多次访谈中讲到深度学习研究人员不要仅仅只停留在理论上,要多编程.个人在学习中也体会到单单的看理 ...

  7. keras框架下的深度学习(一)手写体识别

    这个系列文章主要记录使用keras框架来搭建深度学习模型的学习过程,其中有一些自己的想法和体会,主要学习的书籍是:Deep Learning with Python,使用的IDE是pycharm. 在 ...

  8. keras框架下的深度学习(二)二分类和多分类问题

    本文第一部分是对数据处理中one-hot编码的讲解,第二部分是对二分类模型的代码讲解,其模型的建立以及训练过程与上篇文章一样:在最后我们将训练好的模型保存下来,再用自己的数据放入保存下来的模型中进行分 ...

  9. Python深度学习 deep learning with Python

    内容简介 本书由Keras之父.现任Google人工智能研究员的弗朗索瓦•肖莱(François Chollet)执笔,详尽介绍了用Python和Keras进行深度学习的探索实践,涉及计算机视觉.自然 ...

随机推荐

  1. 【线程】Thread中的join介绍

    因为sleep.wait.join等阻塞,可以使用interrupted exception异常唤醒. 一.作用 Thread类中的join方法的主要作用就是同步,它可以使得线程之间的并行执行变为串行 ...

  2. 【Spring源码分析系列】加载Bean

    /** * Create a new XmlBeanFactory with the given input stream, * which must be parsable using DOM. * ...

  3. Android手机资料拷贝导出工具 --- 91手机助手

    http://zs.91.com/

  4. 关于ASP.NET Web API的ModelBinding杂谈

    由于客户端调用Web API传递的数据属性命名一般偏向javascript规范,只是简单的大小写差异没有问题,但始终会有一些特殊情况.比如OAuth的请求: client_id : "val ...

  5. 【JSP】EL函数和自定义EL函数

    简介 EL原本是JSTL1.0中的技术(所以EL和JSTL感情如此好就是自然的了),但是从JSP2.0开始,EL就分离出来纳入了JSP的标准了.但是EL函数还是和JSTL技术绑定在一起.下面将介绍如何 ...

  6. 仿QQ、微信翻页查看聊天记录

    主界面MainActivity.class public class MainActivity extends Activity implements OnScrollListener{ privat ...

  7. vue之cli脚手架安装和webpack-simple模板项目生成

    ue-cli 是一个官方发布 vue.js 项目脚手架,使用 vue-cli 可以快速创建 vue 项目. GitHub地址是:https://github.com/vuejs/vue-cli 一.安 ...

  8. JavaEE Cookie HttpSession 学习笔记

    1. 会话管理概述 1.1 什么是会话 好比一次通话.打开浏览器,点击多次链接(发出多次请求和收到多次的响应),关闭浏览器,这个过程就是一次会话. 有功能 可以  文件 新建会话 1.2 解决的问题是 ...

  9. c++中system("pause")的作用和含义

    简单来说就是暂停的意思,一般在LINUX编程时会用到,等待接收信号,才会重新运行 . 在进行C/C++编程的时候,在运行程序查看输出效果时,会出现窗口闪一下就关闭的情况. 在C语言中一般通过添加get ...

  10. python调用exe程序

    最近在做测试,公司的产品做成了exe,让我去测试,C++写的程序啊,我直接用python调用那个exe,也有个坑,必须要到exe在的那个目录下,然后才能调用: import os def main() ...