该笔记是以斯坦福cs231n课程的python编程任务为主线,展开对该课程主要内容的理解和部分数学推导。这篇文章是关于计算机视觉处理的,分为两篇文章撰写完成。此为第二篇:根据上篇文章提到,利用深度学习里的RNN和LSTM等神经网络处理后的数据来计算图像的梯度,并且利用不同的图像梯度来生成不同类型的图像。
04
图像梯度(Image Gradients)
这部分我们将用预训练好的CNN模型来计算图像的梯度,并用图像梯度来产生class saliency maps 和 fooling images。这部分我们会用到TinyImageNet数据集,它是ILSVRC-2012分类数据集的一个子集,包含了200个类,每一个类拥有500张训练图片,50张验证图片和50张测试图片,每张图片大小为64x64。TinyImageNet数据集被分成了两部分:TinyImageNet-100-A和TinyImageNet-100-B,每部分包含100个类,这里我们使用的是TinyImageNet-100-A。
Examples of the TinyImageNet-100-A
1.Saliency Maps
给定一张图片X,我们想要知道到底是图片中的哪些部分决定了该图片的最终分类结果。给定一个类,我们可以通过反向传播求出X关于loss function的偏导矩阵,这个偏导矩阵就是该图片的图像梯度,然后计算出类显著度图(class saliency map, csm)。Karen Simonyan论文的3.1节(https://arxiv.org/pdf/1312.6034.pdf)给出了计算方法:如果图片是灰度图,那么csm就取图像梯度的绝对值;如果是RGB图,csm就取图像梯度3个通道中绝对值最大的那个通道。csm中元素值的大小表示对应位置的图片像素对最终分类结果的影响程度。
代码如下:
def compute_saliency_maps(X, y, model):
N,C,H,W = X.shape
saliency = np.zeros((N,H,W))
# Compute the score by a single forward pass
scores, cache = model.forward(X, mode='test') # Score size (N,100)
# The loss function we want to optimize(maximize)
# loss = (scores[np.arange(N), y] - lambda*np.sqrt(np.sum(X**2))) # Size (N,)
# The gradient of this loss wih respect to the input image
dscores = np.zeros_like(scores)
dscores[np.arange(N), y] = 1.0
dX, grads = model.backward(dscores, cache)
saliency += np.max(np.abs(dX), axis=1)
return saliency
下图是一些saliency maps的可视化结果:
Random images
Cherry-picked images
2.Fooling Images
我们可以用图像梯度来生成 虚假图像(fooling images)。给定一张图片和一个目标类,我们可以对该图片执行梯度上升(将图像梯度不断地叠加到原图片上),以产生一个fooling image。该fooling image和原图片在视觉上非常接近,但是CNN会把它识别成我们预先设定的目标类。
代码如下:
def make_fooling_image(X, target_y, model):
X_fooling = X.copy()
N,C,H,W = X_fooling.shape # N=1
i = 0
y_pred = -1
lr = 200.0
while (y_pred != target_y) & (i<200):
scores, cache = model.forward(X_fooling, mode='test') # Score size (N,100)
# The loss function we want to optimize(maximize)
# loss = scores[np.arange(N), target_y] # Size (N,)
# print loss
# The gradient of this loss wih respect to the input image
dscores = np.zeros_like(scores)
dscores[np.arange(N), target_y] = 1.0
dX, grads = model.backward(dscores, cache)
X_fooling += lr*dX
y_pred = model.loss(X_fooling).argmax(axis=1)
i+=1
print 'Iteration %d: current class: %d; target class: %d ' % (i, y_pred, target_y)
return X_fooling
Left: original image, Middle: fooling image, Right: difference
从上图结果我们可以看出:CNN依旧无法摆脱维度的诅咒这一难题,因为存在对抗样本使它无法正确辨识。
05
图像生成(Image Generation)
这一部分我们继续探索图像梯度,我们将使用不同的方法通过图像梯度生成图像。
1.Class visualization
给定一个目标类(比如蜘蛛),我们可以在一个随机噪声图像上,利用梯度上升来生成一个(蜘蛛)图像,并且CNN会把它识别成目标类。具体实现方法可以参见论文:Deep Inside Convolutional Networks: Visualising Image Classification Models and Saliency Maps(https://arxiv.org/pdf/1312.6034.pdf)。
代码如下:
def create_class_visualization(target_y, model, **kwargs):
learning_rate = kwargs.pop('learning_rate', 10000)
blur_every = kwargs.pop('blur_every', 1)
l2_reg = kwargs.pop('l2_reg', 1e-6)
max_jitter = kwargs.pop('max_jitter', 4)
num_iterations = kwargs.pop('num_iterations', 200)
show_every = kwargs.pop('show_every', 25)
X = np.random.randn(1, 3, 64, 64)
for t in xrange(num_iterations):
# As a regularizer, add random jitter to the image
ox, oy = np.random.randint(-max_jitter, max_jitter+1, 2)
X = np.roll(np.roll(X, ox, -1), oy, -2)
# Compute the score and gradient
scores, cache = model.forward(X, mode='test')
# loss = scores[0, target_y] - l2_reg*np.sum(X**2)
dscores = np.zeros_like(scores)
dscores[0, target_y] = 1.0
dX, grads = model.backward(dscores, cache)
dX -= 2*l2_reg*X
X += learning_rate*dX
# Undo the jitter
X = np.roll(np.roll(X, -ox, -1), -oy, -2)
# As a regularizer, clip the image
X = np.clip(X, -data['mean_image'], 255.0 - data['mean_image'])
# As a regularizer, periodically blur the image
if t % blur_every == 0:
X = blur_image(X)
# Periodically show the image
if t % show_every == 0:
print 'The loss is %f' % loss
plt.imshow(deprocess_image(X, data['mean_image']))
plt.gcf().set_size_inches(3, 3)
plt.axis('off')
plt.title('Iteration: %d' % t)
plt.show()
return X
下图是迭代过程中生成的(蜘蛛)图像:
Generated images
2.Feature Inversion
这部分我们将完成一个很有意思的工作:在一张随机噪声图像上重建出指定层CNN学习到的图像特征表达。详细的实现方法参见论文: Understanding Deep Image Representations by Inverting them (https://www.robots.ox.ac.uk/~vedaldi/assets/pubs/mahendran15understanding.pdf)和 Understanding Neural Networks Through Deep Visualization(http://yosinski.com/media/papers/Yosinski__2015__ICML_DL__Understanding_Neural_Networks_Through_Deep_Visualization__.pdf)。
代码如下:
def invert_features(target_feats, layer, model, **kwargs):
learning_rate = kwargs.pop('learning_rate', 10000)
num_iterations = kwargs.pop('num_iterations', 500)
l2_reg = kwargs.pop('l2_reg', 1e-7)
blur_every = kwargs.pop('blur_every', 1)
show_every = kwargs.pop('show_every', 50)
X = np.random.randn(1, 3, 64, 64)
for t in xrange(num_iterations):
# Forward until target layer
feats, cache = model.forward(X, end=layer, mode='test')
# Compute the loss
loss = np.sum((feats-target_feats)**2) + l2_reg*np.sum(X**2)
# Compute the gradient of the loss with respect to the activation
dfeats = 2*(feats-target_feats)
dX, grads = model.backward(dfeats, cache)
dX += 2*l2_reg*X
X -= learning_rate*dX
# As a regularizer, clip the image
X = np.clip(X, -data['mean_image'], 255.0 - data['mean_image'])
# As a regularizer, periodically blur the image
if (blur_every > 0) and t % blur_every == 0:
X = blur_image(X)
if (show_every > 0) and (t % show_every == 0 or t + 1 == num_iterations): print loss
plt.imshow(deprocess_image(X, data['mean_image'])) plt.gcf().set_size_inches(3, 3)
plt.axis('off')
plt.title('Iteration: %d' % t)
plt.show()
下图是迭代过程中生成的图像特征(浅层和深层):
Shallow feature reconstruction
Deep feature reconstruction
3.DeepDream
这部分我们体验一下简化版的DeepDream。实现思想很简单,我们先选定CNN的某一层(我们将在该层dream),然后将需要dream的图像输入进预训练好的CNN。前向传播至目标层,令该层的梯度等于该层的激活值(特征)。然后反向传播至输入层,求出图像梯度,同过梯度下降法将图像梯度不断叠加到输入图像上。
代码如下:
def deepdream(X, layer, model, **kwargs):
X = X.copy()
learning_rate = kwargs.pop('learning_rate', 5.0)
max_jitter = kwargs.pop('max_jitter', 16)
num_iterations = kwargs.pop('num_iterations', 200)
show_every = kwargs.pop('show_every', 50)
for t in tqdm(xrange(num_iterations)):
# As a regularizer, add random jitter to the image
ox, oy = np.random.randint(-max_jitter, max_jitter+1, 2)
X = np.roll(np.roll(X, ox, -1), oy, -2)
# Forward until dreaming layer
fea, cache = model.forward(X, end=layer ,mode='test')
# Set the gradient equal to the feature
dfea = fea
dX, grads = model.backward(dfea, cache)
X += learning_rate*dX
# Undo the jitter
X = np.roll(np.roll(X, -ox, -1), -oy, -2)
# As a regularizer, clip the image
mean_pixel = data['mean_image'].mean(axis=(1, 2), keepdims=True)
X = np.clip(X, -mean_pixel, 255.0 - mean_pixel)
# Periodically show the image
if t == 0 or (t + 1) % show_every == 0:
img = deprocess_image(X, data['mean_image'], mean='pixel')
plt.imshow(img)
plt.title('Iteration: %d' % (t + 1))
plt.gcf().set_size_inches(8, 8)
plt.axis('off')
plt.show()
return X
接下来我们就可以生成DeepDream图像啦!
Tibidabo
Deeplayer
Leaning Tower
扫码关注腾讯云开发者
领取腾讯云代金券
Copyright © 2013 - 2025 Tencent Cloud. All Rights Reserved. 腾讯云 版权所有
深圳市腾讯计算机系统有限公司 ICP备案/许可证号:粤B2-20090059 深公网安备号 44030502008569
腾讯云计算(北京)有限责任公司 京ICP证150476号 | 京ICP备11018762号 | 京公网安备号11010802020287
Copyright © 2013 - 2025 Tencent Cloud.
All Rights Reserved. 腾讯云 版权所有