计算机视觉任务:图像梯度和图像完成

该笔记是以斯坦福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

原文发布于微信公众号 - 人工智能LeadAI(atleadai)

原文发表时间:2017-09-12

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏mantou大数据

[机器学习Lesson 2]代价函数之线性回归算法

x(1) 指的是 第一个训练集里值为2104的输入值, 这个就是第一行里的x x(2) 等于1416。这是第二个x y(1) 等于460,这是第一个训练集样本的...

43410
来自专栏深度学习自然语言处理

详解循环神经网络RNN(理论篇)

让我们从一个问题开始,你能理解下面这句英文的意思吗?“working love learning we on deep”,答案显然是无法理解。那么下面这个句子呢...

873
来自专栏AI研习社

只需 130 行代码!用 GAN 生成二维样本的小例子

50行GAN代码的问题 Dev Nag 写的 50 行代码的 GAN,大概是网上流传最广的,关于GAN最简单的小例子。这是一份用一维均匀样本作为特征空间(l...

2994
来自专栏AI研习社

视频 | 手把手教你构建图片分类器,备战 kaggle 大赛!

AI 研习社按:今天为大家带来硅谷深度学习网红 Siraj 的一则教学视频:如何从零开始构建一个图像分类器来对猫和狗进行分类。(内心OS:终于要开始图像部分了!...

3264
来自专栏IT派

对数几率回归 —— Logistic Regression

首先,在引入LR(Logistic Regression)模型之前,非常重要的一个概念是,该模型在设计之初是用来解决0/1二分类问题,虽然它的名字中有回归二字,...

1072
来自专栏量化投资与机器学习

Matlab编程之——卷积神经网络CNN代码解析

这这是之前我共享的一个深度学习工具包,这是解释代码的一部分,具体的一些细节还还望大家根据自己的能力去做,慢慢去理解。不急昂! 源代码我公布出来希望大家学习交流,...

27310
来自专栏AI研习社

教你用Keras做图像识别!只会图像检测并不强力

AI 研习社按:今天为大家带来硅谷深度学习网红 Siraj 的一则教学视频:如何从零开始构建一个图像分类器来对猫和狗进行分类。(内心OS:终于要开始图像部分了!...

3647
来自专栏机器学习算法全栈工程师

如果Boosting 你懂、那 Adaboost你懂么?

作者:崔家华 编辑:王抒伟 转载请注明作者和出处: https://zhuanlan.zhihu.com/ml-jack 机器学习知乎专栏: h...

2835
来自专栏郭耀华‘s Blog

卷积神经网络CNN的意义

1393
来自专栏wOw的Android小站

[Tensorflow] Tensorflow卷积理解

CNN对于学习深度学习的人来说应该是比较耳熟的名词了.但很多人只是听过,但不知道是什么.

922

扫码关注云+社区