APP下载

基于TensorFlow 的Deep Dream 模型研究与实现

2019-11-05刘俊利

现代计算机 2019年27期
关键词:梯度卷积神经网络

刘俊利

(西南科技大学计算机科学与技术学院,绵阳621000)

0 引言

在过去的几年中,随着AI(人工智能)的快速崛起,许多科技公司、研究机构顺势展开了人工智能进军艺术领域的探索。截至目前,一直被认为是只有人类才可以步入的艺术领域人工智能已经闯入,虽然它目前只是参与,还未达到真正意义上艺术创作的水平,但前景值得期待。Deep Dream 是Google 在2015 年推出的一款人工智能系统,它可以通过识别图像,重新作画。Deep Dream 模型打破了给定相同输入只产生一种输出的传统思路,利用不断修改输入的方法最终获取最佳输出。其核心思想是利用反向传播更新输入图像中的像素点,通过不断迭代放大某一指定特征,最终达到输入图像向指定特征逼近的效果。本文将选取Inception模型的mixed4d_3x3_bottleneck_pre_relu 卷积层的第139 个通道进行最大化,结合TensorFlow[1]的算力实现Deep Dream 生成模型。

1 Inception模型

1.1 Inception简介

深度学习以及神经网络的快速发展让人们越来越意识到想要拥有性能和速度的提升仅仅是靠更给力的硬件、更大的数据集、更大的模型是不够的,新的结构、新的算法以及对模型的改进才是实现突破的关键。自2012 年AlexNet[2]做出历史性突破以来,一直到GoogLeNet[3]的提出,传统的CNN[4]模型设计,其提高网络性能的方法大多是直接增加网络的深度和宽度。但这种简单粗暴的方法会带来一些问题:

(1)容易发生过拟合,这种增加层数及增宽层的通道数的设计思路不可避免地需要在高密度计算的单元上实现,它必然会导致训练参数增加,巨大的参数容易发生过拟合;

(2)网络越大计算复杂度越大,单纯地增加密集计算单元的层数或每层宽度都会招至后续扩展计算量呈指数增加,应用难度大;

(3)容易造成梯度弥散问题,反向传播梯度的时候,梯度随着传播深度(网络越深传播深度越大)的增加越来越小,最终没有变化,导致优化困难,不能有效学习。

为了规避这些缺陷,提升神经网络的性能,GoogLeNet 团队经研究后提出了一种Inception 网络结构。这种结构通过早期将卷积转化为稀疏连接,后期再将稀疏矩阵聚类为较为密集的子矩阵的方法实现了稀疏连接和密集矩阵的互补,进而达到既降低了计算开销,又提高了计算性能还扩大了表达特征范围的效果。

1.2 Inception结构

Inception 结构的主要思路是怎样用密集成分来近似最优的局部稀疏结构。Inception 结构最原始的版本如图1 所示。

图1 Inception module,Naive version

图1 中,Inception 的基本组成结构包括四个部分:1×1 卷积、3×3 卷积、5×5 卷积、3×3 最大池化,这四个部分堆叠在一起,最后再将这四个成分运算结果进行通道上组合。一方面增加了网络的宽度,另一方面增加了网络对尺度的适应性。提取图像不同尺度的信息,然后进行融合,最终得到图像更好的表征正是Inception Module 的核心思想。

不过,如图1 所示,显然其在计算开销上隐藏着重大问题,即所有的卷积核都在上一层的所有输出上来做。这势必会导致特征图厚度很大,造成计算量指数级增加。为了避免这一现象,借鉴Network in Network[5]的思想,在3×3 前,5×5 前,max pooling 后分别加上了1×1 的卷积核进行降维。最终Inception 的网络结构具体如图2 所示。

图2 Inception module with dimension reductions

2 Deep Dream基本原理

Deep Dream 是对卷积神经网络(CNN)进行可视化的一种方法[6],在2015 年由Google 公司发布。其本质是使用梯度上升的方法可视化网络每一层的特征,特别之处在于反向更新的是初始图像的像素值而不是网络权重。在一般在实践中,我们常用卷积神经网络(CNN)来进行图像识别,根据大量标有label 的图像来训练卷积神经网络的梯度,通过训练好的卷积神经网络,即可得到图片的分类结果。而Deep Dream 模型恰恰相反,它不是输入一些图片去测试神经元提取的特征,而是我们选出一些神经元,看它能够模拟出最可能的图片是什么,将这些信息反向传回网络,每个神经元将会显示出它想增强的模式或者特征,如果我们不停地迭代输出,不断地激活特征,那么输出结果会和目标图像会越来越像。假设输入网络的图像为x,一共有n种分类,则设有n 维向量,其中pi表示图像x 为第i 类的概率。若该图像为第a 类的概率为pa,则pa的值越高,为图像x 为第a 类的概率就越高。那么我们反过来想,将pa作为我们的优化目标,不断调整图像的值,使得pa的值尽可能的大,同时,图像也越来越具有a 类的特征,进而就达到了放大特征生成Deep Dream 图片的效果。简单的Deep Dream 模型实现过程如图3 所示。

图3 Deep Dream模型实现过程

3 Python实现

3.1 导入Inception模型

原始的Deep Dream 模型只需要优化ImageNet 模型卷积层某个通道的激活值就可以。因此,应该先导入一个在ImageNet 上预训练的卷积神经网络,此处采用Inception 模型。

model_fn='tensorflow_inception_graph.pb'#导入inception网络结构及其对应的数据

with tf.gfile.FastGFile(model_fn,'rb')as f:

graph_def=tf.GraphDef()

graph_def.ParseFromString(f.read())

#定义t_input 为我们输入的图像

t_input=tf.placeholder(np.float32,name='input')

imagenet_mean=117.0

#输入图像需要经过处理才能送入网络中

#expand_dims 是添加一维

#t_input-imagenet_mean 是减去一个均值

t_preprocessed=tf.expand_dims(t_input-imagenet_mean,0)

tf.import_graph_def(graph_def,{'input':t_preprocessed})

由于在后面的程序中需要输入图像,所以此处需要设置占位符t_input 用于接收图像的传递;由于格式(height,width,channel)只能表示一张图像,而实际上训练神经网络时往往需要同时送入多张图像所以需要添加一维,将输入图像格式改为(batch,height,width,channel),只输入1 张图像时batch 为1;由于在训练Inception 模型时已经完成了为图像减去一个像素均值的预处理,因此为了保持输入一致,t_input 需要完成同样的预处理此处减去一个均值117。

3.2 生成原始的Deep Dream图像

(1)生成初始图像

生成一张尺寸为(224,224,3)的随机噪声图片表示初始化图像优化起点。

img_noise = np.random.uniform(size=(224,224,3))+100.0

(2)选择优化目标

定义卷积层、通道数,并取出对应的Tensor。

name='mixed4d_3x3_bottleneck_pre_relu'#定义卷积层

channel=139#选择任意的通道,这里是139

# 取出mixed4d_3x3_bottleneck_pre_relu 卷积层的输出层

layer_output = graph.get_tensor_by_name("import/% s:0"%name)

(3)渲染图片

t_obj 为卷积层某个通道的值;img0 对应初始图像;iter_n 为迭代步数;step 为学习率。render_naive 函数利用梯度下降下降法不断调整输入图像来使得优化目标t_score 尽可能的大。最后经过iter_n 步迭代生成原始的Deep Dream 图片。

def render_naive(t_obj,img0,iter_n=60,step=1.0):

#t_score 是优化目标。它是t_obj 的平均值

t_score=tf.reduce_mean(t_obj)

#计算t_score 对t_input(初始图像)的梯度

t_grad=tf.gradients(t_score,t_input)[0]

#创建新图

img=img0.copy()

for i in range(iter_n):

#在sess 中计算梯度,以及当前的score

g,score=sess.run([t_grad,t_score],{t_input:img})

#对img 应用梯度。step 可以看做“学习率”

g/=g.std()+1e-8

img+=g*step

print('score(mean)=%f'%(score))

#保存图片

scipy.misc.toimage(img).save('naive.jpg')

3.3 生成更大尺寸的Deep Dream图像

生成更大尺寸的Deep Dream 图像与生成原始的Deep Dream 图像相比,前者的实现方法需要在后者的实现方法的基础上做出一些必要的改进。主要需要解决图片越大,内存占用越大导致图片渲染失败的问题。此处的解决方案为将图片分为几部分,每次只对一部分进行优化,每次优化只消耗固定大小的内存。函数calc_grad_tiled 利用图片分块化的方法可以计算任意大小的梯度。其中img 对应初始图像;t_grad 为优化目标对初始图像的梯度;tile_size 表示将初始图像分成多张tile_size*tile_size 大小的图像分别进行优化。

def calc_grad_tiled(img,t_grad,tile_size=512):

#每次只对tile_size×tile_size 大小的图像计算梯度,避免内存问题

sz=tile_size

h,w=img.shape[:2]

# img_shift:先在行上做整体移动,再在列上做整体移动

#防止在tile 的边缘产生边缘效应

sx,sy=np.random.randint(sz,size=2)

img_shift=np.roll(np.roll(img,sx,1),sy,0)

grad=np.zeros_like(img)

#y,x 是开始位置的像素

for y in range(0,max(h-sz//2,sz),sz):

for x in range(0,max(w-sz//2,sz),sz):

# 每次对sub 计算梯度。sub 的大小是tile_size×

tile_size

sub=img_shift[y:y+sz,x:x+sz]

g=sess.run(t_grad,{t_input:sub})

grad[y:y+sz,x:x+sz]=g

#使用np.roll 移动回去

return np.roll(np.roll(grad,-sx,1),-sy,0)

4 程序运行界面效果

利用深度学习框架TensorFlow 导入Inception 模型进而实现Deep Dream 生成模型的运行结果:原始的Deep Dream 图像和更大尺寸的Deep Dream 图像,分别如图4 和图5 所示。运行效果非常直观,Deep Dream模型可以实现图像的自动生成,且当面对较大的图片时,利用将图片分成小块再分别优化的方法也可以实现大尺寸图像的自动生成。

图4 原始的Deep Dream图像

图5 更大尺寸的Deep Dream图像

5 结语

本文首先介绍了Inception v1 模型,之后给出了Deep Dream 模型的基本原理,然后利用TensorFlow 导入训练好的Inception 模型并合理地选取了卷积层和通道,最后实现了Deep Dream 生成模型,完成了原始的Deep Dream 图像和更大尺寸的Deep Dream 图像的生成,两张图片均取得了较好的效果,证明了mixed4d_3x3_bottleneck_pre_relu 层的第139 个通道学习到的特征为花的纹理图特征。Deep Dream 模型是人工智能向绘画领域探索的标志性成果,虽然只是初期,但是它向我们展示了人工智能绘画的可能,未来,人工智能必将给艺术领域带来新的灵感和惊喜。

猜你喜欢

梯度卷积神经网络
基于全卷积神经网络的猪背膘厚快速准确测定
基于神经网络的船舶电力系统故障诊断方法
基于应变梯度的微尺度金属塑性行为研究
MIV-PSO-BP神经网络用户热负荷预测
基于改进Hopfield神经网络的对地攻击型无人机自主能力评价
一种基于卷积神经网络的地磁基准图构建方法
基于3D-Winograd的快速卷积算法设计及FPGA实现
一种并行不对称空洞卷积模块①
一个具梯度项的p-Laplace 方程弱解的存在性
内容、形式与表达——有梯度的语言教学策略研究