1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
| from keras import backend as K
import numpy as np
def deep_dream(img, model, epochs, learning_rate, max_threshold):
'''
将VGG16的block4_conv1与block5_conv2用来做deep dream,其中block4_conv1的权重为0.05,block5_conv2的权重为0.2,并将图像返回
:param img: 预处理后的图像,类型为ndarray,shape为(样本个数,图像的宽,图像的高,通道数)
:param model: VGG16
:param epochs: 梯度上升的迭代次数
:param learning_rate: 梯度上升的学习率
:param max_threshold: 损失值的最大阈值
:return: deep dream后的图像,其中图像的维度为(图像的高,图像的宽,通道数)
'''
#********* Begin *********#
layer_contributions = {
'block4_conv1': 0.05,
'block5_conv2': 0.2
}
# 定义一个包含损失的张量,即上面列出的激活的L2范数的加权和。
layer_dict = dict([(layer.name, layer) for layer in model.layers])
# 定义损失
loss = K.variable(0.)
for layer_name in layer_contributions:
# 将丢失的图层特征的L2范数添加到损失中。
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[:, :, :, :])) / scaling
dream = model.input
# 计算损失的梯度的变化
grads = K.gradients(loss, dream)[0]
# 标准化梯度
grads /= K.maximum(K.mean(K.abs(grads)), 1e-7)
# 设置函数以检索给定输入图像的损失和梯度值。
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
for i in range(epochs):
loss_value, grad_values = eval_loss_and_grads(img)
if max_threshold is not None and loss_value > max_threshold:
break
img = img + learning_rate * grad_values
return img
#********* End *********#
|