DeepDream

在此就不进行介绍了,直接从ImageNet上预训练的卷积神经网络开始。Kreas中有许多这样的卷积神经网络。我们使用Inception V3模型

一:加载预训练的InceptionV3模型

#用keras实现DeepDream
from keras.applications import inception_v3
from keras import backend as K
K.set_learning_phase(0)#不需要训练模型,所以这个命令会禁用所有与训练有关的操作
model=inception_v3.InceptionV3(weights='imagenet',include_top=False)#构建不包括全连接的inceptionV3网络。适用预训练的ImageNet权重来加载模型

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

二:设置DeepDream配置

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

接下来定义一个包含损失的张量,损失就是上述代码中层激活的L2范数的加权求和。

三:定义需要最大化的损失

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'))
    loss+=coeff*K.sum(K.square(activation[:,2:-2,2:-2,:]))/scaling#将该层特征的L2范数添加到loss中。为了避免出现边界伪影,损失中仅包含非边界的像素

下面设置梯度上升过程

四:梯度上升过程

#梯度上升过程
dream=model.input#这个张量用于保存生成的图像
grads=K.gradients(loss,dream)[0]#计算损失相对于梦境图像的梯度
grads/=K.maximum(K.mean(K.abs(grads)),1e-7)#将梯度标准化(重要技巧)
outputs=[loss,grads]#给定一张输出图像,设置一个Keras函数来获取损失值和梯度值
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
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的细节损失。

五:在多个连续尺度上运行梯度上升

六:辅助函数

 

 

 建议你调节在损失中使用的层,从而探索能够得到什么样的结果。网络中更靠近底部的层包含更局部,不太抽象的表示,得到的梦境图案看起来更像是几何形状。更靠近顶部的层能够得到更容易识别的视觉图案,这些图案都是基于ImageNet中最常见的对象。可以随机生成layer_contributions字典中的参数,从而快速探索多种不同层的组合。

DeepDream的过程是反向运行一个卷积神经网络,基于网络学到的表示来生成输入

这个过程并不局限于图像模型,甚至并不局限于卷积网络,可以应用于语音、音乐等更多内容。

实在是写不动了,感谢大家,一键三连!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值