• 深度学习暑期学校(加拿大、蒙特利尔,2016.8.1-7)


    learning to see.pdf

    @lutingting 2016-11-04 16:15 字数 10899 阅读 4087
     
     

    SIFT特征提取及匹配

    数字图像处理 图像特征提取


     

     

    1.SIFT(Scale-invariant feature transform)算子的核心思想

    • 利用不同尺度的高斯核函数对图像进行平滑,即构造图像的尺度空间
    • 比较不同尺度平滑后的图像差别,在某局部范围内,差别最大或者差别最小的像素点就是特征明显的点

    由于SIFT特征的检测方式,使得它具有:

    • 尺度不变性:在尺度空间内进行的特征点检测
     

    2.什么是尺度空间呢?

     

    2.1 一篇百度文库的文章关于尺度空间的分析

    具体内容参考文献4

    通常会听到尺度变化等这类词语,看到的也总是一堆的数学公式,有时候真的不知道这到底有啥用,有啥意义,没有弄懂这些意义,当然就更不可能理解,不可能去掌握、应用它了,现在我才理解,小波变化其实也是一种尺度变化。今天我看到一篇南航数学系写的关于尺度空间解释的文章,感觉很通俗易懂,我们不从数学上来推导什么是尺度空间,只是从生活常识方面来解释尺度空间的意义,意义懂了,数学方面自然就好理解了。

     

    例子1

    首先我们提出一个问题,请看下面的图片,让我们人为的进行判断:下面所显示的左右图片中哪个的角尖锐?
    image_1b0klk03k7tq1eqtfou11jgtbs9.png-200.8kB

    • 图1(a)中,显然右边的角更尖锐,这是因为同左边的角相比其角度值较小
    • 图1(b)中,也是右边的角更尖锐,这是因为同左边的角相比其曲率值较大
    • 图1(c)中,问题的答案则要困难得多。左边的角一方面具有较小的角度值(因此更尖锐),另一方面又具有较小的曲率值(因此更圆钝)。右边的角情形刚好相反,一方面因为具有较大的角度值更圆钝,另一方面又因为具有较大的曲率值显得更尖锐。事实上,本问题对于图1(a)和图1(b)来说是纯粹的数学问题,依据数学上的基本概念(即角度、曲率)便可以做出判断。而图1(c)中两个角之间的比较已经不再是纯粹的数学问题,在数学上没有明确的答案。确切地说,这是一个尺度空间中的视觉问题,其答案取决于问题所在的“尺度”而不是某个数学指标。这里,“尺度”可以被直观地理解为观察窗口的大小。在图1(c)中,我们观察两个角的窗口大小都是
    • 图1(d)中,调整了观察窗口,其大小变成(假设所比较的两个角都具有无限长的边)。在这个较大的尺度下,问题的答案变得非常明朗:左边的角更加尖锐。
    • 图1(e)中,观察窗口的大小变更为在这个较小的尺度下,问题的答案发生了有趣的变化:此时右边的角更加尖锐。

    此例子的结果阐述了“尺度”对于解决视觉问题的重要性,即一个视觉问题的答案往往会依赖于其所在的尺度。在生活中这样的例子也比比皆是,比如要观察一棵树,所选择的尺度应该是“米”级;如果观察树上的树叶,所选择的尺度则应该是“厘米”级。一般来说,摄像设备所能呈现的画面分辨率是固定的。要以同样的分辨率分别观察树和树叶,我们需要调整摄像设备的摄像位置。因此,视觉问题中的“尺度”概念也可以被形象地理解为摄像设备与被观察物体之间的距离:较远的距离对应较大的尺度,较近的距离对应较小的尺度。

     

    例子2

    接下来我们看看第二个例子吧,看看图二中显示的图片那些是角点?
    image_1b0klkria1pfs53v1hun1t3j1cj3m.png-162.3kB

    • 图2(a) 呈现了一片雪花的形状轮廓,要求我们找出该形状上的角点。在很多计算机视觉任务中,角点都有着重要的作用。数学上,角点一般是指大曲率点或曲率无穷大点。
    • 在图2(b)中,雪花形状上所有曲率无穷大点都被确认为角点,一共有192个,如圆圈所标记。这个答案在数学上无疑是正确的、完美的令人惊奇的,但它对于完成一个视觉任务(比如理解和分析这个形状)来说并没有多大的意义。
    • 如果我们仅选择图2(c)中所标记出的48个点作为角点,感觉上要更好点。作为图2(b)中所标记的192个角点中的一部分,这48个角点在理解和分析雪花形状的结构时要比其余的角点具有更高的重要性。
    • 实际上,按照这一思路,我们不难发现在这48个角点中又有12个角点其重要性还要更高一些,如图2(d)中所标记。

    同例1 一样,本例中问题的答案依赖于问题所在的尺度:当我们非常靠近雪花形状观察它时(即在较小的尺度下),能够看清楚所有的细节,却不容易感知其整体轮廓,从而倾向于不加区分地选取图2(b)中所标记的192 个点作为角点。反过来,当我们从一个很远的距离观察雪花形状时(即在较大的尺度下),虽然轮廓的细节已经模糊不清,但却能够一眼看出其整体结构,从而倾向于选取图2(d) 中所标记的12 个点作为角点。此外,图2(c) 中所标记的角点对于理解雪花形状也很有帮助。事实上,如果我们不是保守地将自己固定在某个尺度下来观察物体,便能够获得充足的视觉信息。比如说图2(b)-2(d) 所呈现的三组角点已经很好地向我们展示了雪花形状的三个结构层次。这一效果是其中的任意一组角点都无法实现的。

     

    现实生活中的例子

    现实生活中视觉问题的复杂性也往往需要我们做到这一点:当我们去参观某处文化遗迹时,远远地就已经开始观察建筑物的外形,然后较近距离时开始注意到门窗、台阶、梁柱的建筑风格,最后会凑上前去细看门窗上的图案、石碑上的碑文等。当一部机器人也能够自主地做到这一点时,说明它已经具备了更高的人工智能。我们对尺度空间技术的研究也正是朝着这个方向努力。概括地说,“尺度空间”的概念就是在多个尺度下观察目标,然后加以综合的分析和理解。 这里用的是图像来解释尺度,当然,对于抽象的信号,理解还是一样的,不过到时候我们看的工具不是我们人眼或者是摄像机从外表区分了,这时候我们用的工具也可能是时域的分析法,也可能是频率域的傅里叶变化等分析法,它是我们进一步发现我们感兴趣事物的工具。

     

    2.2 SIFT中的尺度空间的概念

    • David Lowe关于Sfit算法,2004年发表在Int. Journal of Computer Vision的经典论文中,对尺度空间(scale space)是这样定义的

      It has been shown by Koenderink (1984) and Lindeberg (1994) that under a variety of reasonable assumptions the only possible scale-space kernel is the Gaussian function. Therefore,the scale space of an image is defined as a function, L(x; y; sigma) that is produced from the convolution of a variable-scale Gaussian, G(x; y; sigma), with an input image, I(x; y)

    • 从上面的定义可以看到:

      • 高斯卷积核是实现尺度变换的唯一变换核
      • 一幅图像的尺度空间被定义为:高斯卷积核与该图像的卷积,它是高斯卷积核中的参数的函数,这里用到“空间”这个词,是因为是可以连续变化的,具体地,图像的尺度空间为:

         

        其中:

        • 是高斯核函数
        • 是尺度因子,的大小决定图像的平滑程度,大尺度对应图像的概貌特征,小尺度对应图像的细节特征。大的值对应粗糙尺度(低分辨率),小的值对应精细尺度(高分辨率)。
        • 是卷积操作
        • 就是输入图像的尺度空间。
     

    3.SIFT特征提取

    一幅图像的SIFT特征提取,分为4个步骤:

    • 尺度空间极值检测
    • 关键点位置及尺度确定
    • 关键点方向确定
    • 特征向量生成

    下面分别是这四部分的详细内容

     

    3.1 尺度空间极值检测

    SIFT特征点其实就是尺度空间中稳定的点/极值点,那么,为了得到这些稳定点:

    • 首先,需要对输入图像建立尺度空间(通过图像高斯金字塔)
    • 然后,需要从建立得到的尺度空间中检测极值点(转换为图像差分高斯金字塔中极值点的检测)
      • 获取差分高斯金字塔
      • DoG中极值点的检测
     

    3.1.1 尺度空间的建立(高斯金字塔的建立)

    对于一幅输入图像,为了进行sift特征检测、实现scale-invariant(任何尺度下都能够有对应的特征点),需要对该图像的尺度空间进行分析,即建立高斯金字塔图像、得到不同scale的图像,这里的高斯金字塔与最原始的高斯金字塔稍微有点区别,因为它在构造尺度空间时,将这些不同尺度图像分为了多个Octave、每个Octave又分为了多层。下图左侧框内给出了Sift中的高斯金字塔的结构图;
    image_1b0klmhj016gr9jl1blb83s3am13.png-561.5kB

    • 高斯金字塔分为S组(即S个塔、或者称为S个octave),每个塔中有s层;具体有几个塔、每个塔包含几层由输入图像的尺寸决定!对于上图而言:有S=2组,每组由s=5层;
    • 同一塔中图像尺寸相同但尺度不同、不同塔中图像尺寸和尺度都不同(注意:这里的尺寸和尺度概念不同!尺寸对应图像分辨率、尺度为高斯核大小)

      • 每一个塔中图像尺寸确定方法为:第一个塔的尺寸为原图大小,后面每个塔的尺寸为上一个塔的降采样的结果(即长宽分别减半的结果)
      • 每个塔中各层图像的尺度不同,即取值不同,各层之间相差一个值。例如:上图中第一个塔中各层的尺度因子分别为:;而第二个塔中各层的尺度因子分别为:
    • 如何确定相邻层之间的比例因子k呢?下图是同一Octave中不同层和不同Octave之间的尺度大小关系,为了满足尺度变化的连续性,即某一组的最后一层对应的尺度与下一组的第一层对应的尺度应该相差一个k倍,所以应该有,所以,,即,其中,为基础尺度因子。
      image_1b0klmvqpfmf1ptoe6510j51urh1g.png-95.9kB
      image_1b0kln4dr1k8o1dpi1org1345h161t.png-339.8kB
      image_1b0kln8bf1e1jm301ciq17ba1k4s2a.png-119kB

    注1:关于尺度变化的连续性应该就是指:金字塔图像中所有图像之间的尺度因子都相差一个k倍:每个octave中相邻图像之间尺度因子相差一个k,相邻2个octave的最后一层与第一层的图像之间尺度因子相差一个k!
    注2:英文Octave是音乐上一个八度的意思,在这里指的是一组图像。这一组图像的分辨率是相同的,但是采用了不同尺度的高斯函数进行滤波,因此从模糊程度上看(或者说从关注的尺度上看)是有区别的。而不同组的图像具有不同的分辨率,在尺度上的差别就更大。


    为什么已经使用了不同尺度的高斯函数进行滤波还需要引入高斯金字塔呢?
    这是因为SIFT算法希望能具有更高的尺度分辨率(也就是希望相邻尺度的变化比较精细),所以就需要有很多层。如果不用高斯金字塔,都在原始分辨率上靠采用不同的高斯函数实现多尺度检测,那么对于比较粗尺度的特征提取在计算量上就相当浪费。因为在保持图像原始分辨率不变的情况下,提取粗尺度特征需要高斯函数的方差较大,相应的滤波窗口也比较大,计算量会激增,而由于图像在大尺度上的模糊,保持原始分辨率已经没有必要了,这种计算消耗就更是得不偿失。所以采用高斯金字塔是为了高效地提取不同尺度的特征。

    不同octave之间的尺度差异靠高斯金字塔在分辨率上的区别实现,同一个octave内部不同层之间的尺度差异靠高斯函数的方差变化来实现。另外SIFT在DOG问题上并不是使用DOG函数直接滤波,而是用相邻两层的高斯滤波结果相减得到的,为什么要这样呢?
    也是为了节省计算量。因为如果直接采用DOG函数,为了提取不同的尺度,就必须逐渐扩大DOG函数的窗口,这会引起计算量的增加。在实际操作中,SIFT首先对当前octave对应的分辨率的采样图像用一个窗口相对较小的高斯函数滤波,之后同一个octave的第2层一直到第k层,都是通过对前一层已经滤波过的结果再进行一次高斯滤波。对一副原始图像用方差为的高斯函数连续做两次滤波的结果,相当于对这幅图像直接用一个的高斯函数做一次滤波。所以每次都在前一层的滤波结果基础上进行滤波,跟对原始图像分别用不同窗口大小的高斯函数滤波的结果是一样的,但是因为避免了滤波函数窗口的扩大,可以有效减少计算量。

    不同对应的高斯核函数到底有什么作用呢?下面做个小实验,可以发现,不同高斯核尺度会对图像产生不同的平滑效果,尺度因子越大(高斯函数方差越大),对图像的平滑程度越大;

     
    1. %读入图像并将其转换成灰度图像
    2. I=imread('qingdao.jpg');
    3. I=rgb2gray(I);
    4. % 利用尺度为3*3的高斯核进行滤波
    5. w1=fspecial('gaussian',3,0.5);
    6. g1=imfilter(I,w1,'conv','symmetric','same');
    7. % 利用尺度为11*11的高斯核进行滤波
    8. w2=fspecial('gaussian',11,0.5);
    9. g2=imfilter(I,w2,'conv','symmetric','same');
    10. % 显示处理结果
    11. figure;subplot(1,3,1);imshow(I);title('原始图像');
    12. subplot(1,3,2);imshow(g1);title('3*3高斯');
    13. subplot(1,3,3);imshow(g2);title('11*1高斯');
    • matlab中利用fspecial函数产生离散高斯核:H=fspecial('gaussian',hsize,sigma)
    • H是一个矩阵,它是由离散高斯卷积核计算得到的
      image_1b0klo9h2109mntu10ct1rno32n.png-1.4kB
      • 它是利用二维高斯函数计算得到的
      • 其中的hsize为高斯核的大小,sigma为高斯核的标准偏差,即高斯核的大小

    得到了图像的尺度空间后,需要在尺度中间内检测稳定特征点,从而需要比较不同尺度图像之间的差别,实现极值点的检测,实际上,Laplacian of Gaussian和Difference of Gaussian都能够实现这样的目的,但LoG需要大量的计算,而DoG的计算相对简单,并且DoG是对LoG的一个很好的今昔

     

    3.1.2 图像差分高斯金字塔(DoG)的建立

    对于高斯金字塔中的每一个塔的不同层,可以计算得到相邻层之间的差值,从而可以得到差分高斯,对高斯金字塔中每一个塔都进行同样的操作,从而得到差分高斯金字塔,如下图右侧所示,即显示了由左侧的高斯金字塔构造得到的差分高斯金字塔,该差分高斯金字塔包含2个塔,每个塔都有四层
    image_1b0kloibp113e21r1ju9g5012o34.png-249.9kB

    差分高斯表征了相邻尺度的高斯图像之前的差别,大值表示区别大,小值表示区别小,后续的特征点检测都是差分高斯图像金字塔中进行的!

     

    3.1.3 尺度空间中特征点的检测(DoG中极值点的检测)

    构造完尺度空间(差分高斯金字塔)后,接下来的任务就是“在尺度中间中检测出图像中的稳定特征点”:

    对于DoG中每一个采样点(每一个Octave中每一层),将其与它邻域内所有像素点(8+18=26)进行比较,判断其是否为局部极值点(极大或者极小),更加具体地:如下图所示,中间的检测点和它同尺度的8个相邻点和上下相邻尺度对应的9×2个点共26个点比较,以确保在尺度空间和二维图像空间都检测到极值点。 一个点如果在DOG尺度空间本层以及上下两层的26个领域中是最大或最小值时,就认为该点是图像在该尺度下的一个特征点。但要注意:这种相邻层之间的极值点的寻找是在同一Octave中的相邻尺度之间进行寻找的,而不要跨组!
    image_1b0klp3ope2gr4m1evh2urbef3h.png-46.6kB

    同时,应该注意到一个问题,在极值比较的过程中,每一Octave图像的首末两层是无法进行极值比较的,为了满足尺度变化的连续性,需要进行一些修正:在高斯金字塔中生成S+3层图像,具体解释如下:假设s=3,也就是每个塔里有3层,则k=21/s=21/3:

    • 那么按照上图可得Gauss Space和DoG space 分别有3个(s个)和2个(s-1个)分量,在DoG space中,1st-octave两项分别是σ,kσ; 2nd-octave两项分别是2σ,2kσ;
      image_1b0klpd3g1i3du171i2jb96bh3u.png-132.5kB

    • 由于无法比较极值,我们必须在高斯空间继续添加高斯模糊项,使得DoG中第一个Octave形成σ,kσ,k2σ,k3σ,k4σ,这样就可以选择中间三项kσ,k2σ,k3σ(只有左右都有才能有极值);那么下一octave中(由上一层降采样获得)所得三项即为2kσ,2k2σ,2k3σ,其首项2kσ=24/3。刚好与上一octave末项k3σ=23/3尺度变化连续起来,所以每次要在Gaussian space添加3项,每组(塔)共S+3层图像,相应的DoG金字塔有S+2层图像。
      image_1b0klpmj0gk82tu4fi1p9m134g4b.png-124kB
      image_1b0klq8iv1ilthqn1a991u9tepd4o.png-126.8kB

     

    3.2 关键点位置及尺度确定

    通过拟和“三维二次函数”可以精确确定关键点的位置和尺度(达到亚像素精度),具体方法还未知,可以得到一系列的SIFT候选特征点集合,但由于这些关键点中有些具有较低的对比对,有些输属于不稳定的边缘响应点(因为DoG算子会产生较强的边缘响应),所以,为了增强匹配稳定性、提高抗噪声能力,应该将这2类关键点去除,实现对候选SIFT特征点集合的进一步净化:

    • 剔除对比度低的点
    • 剔除边缘点
     

    3.3 关键点方向确定

    • 计算关键点的方向,需要利用以该关键点为中心的某邻域窗口内所有像素点的梯度分布特性(目的是为了使的sift算子具备旋转不变性),所以,下面首先给出计算尺度空间中每个像素点的梯度模值和方向的方法,按照下面公式计算:
      image_1b0klqvubd7fq6r1vl91f49g855.png-30.6kB

      • 其中L所用的尺度为每个关键点各自所在的尺度。
        image_1b0klrbeh13ciebk13mb1r87c5o5i.png-23.2kB
    • 接下来,对于每个关键点(假设尺度为sigma),利用直方图统计其相邻窗口内的像素的梯度分布,从而,确定该关键点的方向,具体方法如下:

      • 分别计算以该关键点为中心的相邻窗口中像素点的梯度方向和模值
      • 为该窗口内每一个像素点赋予一个权值:由每个像素点对应的梯度模值和以关键点为中心尺度为1.5sigma的高斯核决定
      • 设定某种规则,开始统计直方图,例如,这里将方向(0~360°)分为8份,那么,梯度方向直方图将有8个柱,窗口内每个像素到底属于哪个柱由该像素点的梯度方向确定(见下图右侧子图所示)
        image_1b0klrrtj2hfhit1b62189412rd5v.png-11.7kB
        image_1b0kls3cv1h5973d10au165314ge6c.png-45.1kB
      • 在该关键点对应的梯度方向直方图中,找到包含像素点最多的那个方向作为该关键点的方向,对于上图而言,方向角(0.25π,0.5π)这个区间内的像素点最多,所以,以(0.25π+0.5π)/2 = 0.375π作为该关键点的方向

    至此,得到了图像中所有关键点的方向!实际上,关键点方向的确定是为了接下来的特征向量生成中的坐标旋转使用的!

     

    3.4 特征向量生成

    上面只是得到了每个关键点的方向,接下来,需要确定每个关键点的特征向量,具体方式如下:

    • 将坐标轴旋转到关键点的方向
      image_1b0klsvfv1la515ed19m21n4h1o4r6p.png-26.9kB

    • 对于某一个关键点,取其周围窗口,如下图绿色区域所示,其中,窗口内每个小矩形框为一个像素,箭头表示该像素位置的梯度方向和模值
      image_1b0klt3us15h41ddc11t4kjj15r76.png-111.7kB

    • 在该窗口对应的4个(称为4个种子点)的小块儿上,分别计算该小块儿包含的16个像素点的梯度直方图(8个柱),并进行累加(每个柱对应的所有像素点的梯度模值累加),每个小块儿可以得到8个特征(8个方向对应的模值的累加),从而,4个种子点将得到关键点的4*8=32个特征,如下图右侧所示,4个种子点,每个种子点产生8个特征
      image_1b0klte27vs5vgg1t32dpojac7j.png-152.1kB

    • 实际中,Lowe建议使用个子块儿(称为16个种子点)进行特征计算,那么,每个关键点将具有16*8=128个特征,如下图所示,此时,需要在特征点周围取的窗口,分割为个子块儿(这样做的目的是为了增强后续匹配的稳健性)。
      image_1b0kltmqi1nugij91r5gbk61olh80.png-92.8kB

    至此,关键点特征向量完全确定!此时SIFT特征向量已经去除了尺度变化、旋转等几何变形因素的影响,再继续将特征向量的长度归一化,则可以进一步去除光照变化的影响。
    image_1b0klud1uv091h771pr09uo1d758d.png-24.1kB

     

    4.SIFT特征的匹配

    现有A、B两幅图像,分别利用上面的方法从各幅图像中提取到了k1个sift特征点和k2个特征点及其对应的特征描述子,即维和维的特征,现在需要将两图中各个scale(所有scale)的描述子进行匹配。

    接下来采用关键点特征向量的欧式距离来作为两幅图像中关键点的相似性判定度量。

    • 取图像A中的某个关键点,并找出其与图像B中欧式距离最近的前两个关键点
      • 在这两个关键点中,如果最近的距离除以次近的距离少于某个比例阈值,则接受这一对匹配点。降低这个比例阈值,SIFT匹配点数目会减少,但更加稳定。
      • 利用2个近邻点比较的目的是为了排除因为图像遮挡和背景混乱而产生的无匹配关系的关键点,所以Lowe提出了比较最近邻距离与次近邻距离的方法,距离比率ratio小于某个阈值的认为是正确匹配。因为对于错误匹配,由于特征空间的高维性,相似的距离可能有大量其他的错误匹配,从而它的ratio值比较高。Lowe推荐ratio的阈值为0.8。但作者对大量任意存在尺度、旋转和亮度变化的两幅图片进行匹配,结果表明ratio取值在0. 4~0. 6之间最佳,小于0. 4的很少有匹配点,大于0. 6的则存在大量错误匹配点。(如果这个地方你要改进,最好给出一个匹配率和ration之间的关系图,这样才有说服力),作者建议ratio的取值原则如下:
        • ratio=0. 4 对于准确度要求高的匹配;
        • ratio=0. 6 对于匹配点数目要求比较多的匹配;
        • ratio=0. 5 一般情况下。
        • 也可按如下原则: 当最近邻距离<200时,ratio=0. 6;反之,ratio=0. 4。ratio的取值策略能排分错误匹配点。

    Reference
    1. SIFT keypoint detector实现代码:http://www.cs.ubc.ca/~lowe/keypoints/
    2. David Lowe个人主页:http://www.cs.ubc.ca/~lowe/home.html
    3. David Lowe关于SIFT的论文2004《Distinctive Image Features
    from Scale-Invariant Keypoints》pdf版本:http://www.cs.ubc.ca/~lowe/papers/ijcv04.pdf
    4. http://wenku.baidu.com/link?url=rsMoC8dnNclI54HCm1YDvANsj5h1dsUxGnjVCY5KOsXxdSt0XKP3ix5pgH5W41bJ9RKSn7gsZTtXIur3r8ULfTANuF2o5mCpM2kMP_MI0Pm
    5. Rachel-Zhang博客-SIFT特征提取分析. http://blog.csdn.net/abcjennifer/article/details/7639681
    6. http://www.zhihu.com/question/19911080
    7. http://blog.csdn.net/songzitea/article/details/16986423


     

    5.下面是一些参考程序

     

    5.1

     
    1. %size为模板大小
    2. %sigma为标准差
    3. size = 3;
    4. sigma =3 ;
    5. %下面的代码其实是从fspecial中摘录出来的,我做了一些更改放到自己写的函数里面便于解释
    6. %计算高斯模板的中心位置
    7. siz = ([size size]-1)/2;
    8. sig = sigma;
    9. %用meshgrid是为了加速,不用for循环
    10. [x y] = meshgrid(-siz(2):siz(2),-siz(1):siz(1));
    11. %计算exp(-(x^2+y^2)/(2*sig^2))
    12. %我想你肯定有一个疑问,那就是为什么不除以2*pi*sig^2
    13. %因为不除也没有关系,因为最后归一化之后会约掉
    14. arg = -(x.*x+y.*y)./(2*sig*sig);
    15. h = exp(arg);
    16. %不知道它为什么要这样,忘懂得人解释一下
    17. h(h<eps*max(h(:))) = 0;
    18. %求和,用来归一化
    19. sumh = sum(h(:));
    20. %防止求和之后出现为0的情况,然后再归一化一下使高斯,模板为小数
    21. if sumh ~=0
    22. h=h/sumh;
    23. end
    24. %% 绘制二维高斯曲面
    25. u=[-10:0.1:10];
    26. v=[-10:0.1:10];
    27. [U,V]=meshgrid(u,v);
    28. H=1/2/pi/sigma*exp(-(U.^2+V.^2)./2/sigma^2);
    29. mesh(u,v,H); %绘制三维曲面的函数
    30. title('高斯函数曲面');
    31. %% 利用fspecial产生高斯核
    32. hold on;
    33. for i=1:3
    34. for j=1:3
    35. plot3(i-2,j-2,h(j,i),'r*');
    36. end
    37. end
     

    5.2

     
    1. clear;clc;close all
    2. %% 输入图像,并归一化到统一的尺寸
    3. row=256;colum=256;
    4. img=imread('lenna.png');
    5. img=imresize(img,[row,colum]);
    6. img=rgb2gray(img);
    7. img=im2double(img);
    8. origin=img;
    9. %% 下面分别利用不同的sigma值对输入图像进行卷积操作
    10. sigma0 = sqrt(2);
    11. level = 3;
    12. for i=1:level
    13. scale=sigma0*sqrt(2)^(1/level)^((i-1)*level+i);
    14. f=fspecial('gaussian',[1,floor(6*scale)],scale);
    15. image_output=conv2(origin,f','same');
    16. figure;imshow(image_output);hold on;
    17. title(['scale = ',num2str(scale),',and size of kernel is ',num2str(size(f,1)),'*',num2str(size(f,2))]);
    18. end
    19. %% 绘制二维高斯曲面
    20. sigma = 3;
    21. u=[-10:0.1:10];
    22. v=[-10:0.1:10];
    23. [U,V]=meshgrid(u,v);
    24. H=1/2/pi/sigma*exp(-(U.^2+V.^2)./2/sigma^2);
    25. mesh(u,v,H); %绘制三维曲面的函数
    26. title('高斯函数曲面');
    27. %% 利用fspecial产生高斯核
    28. f=fspecial('gaussian',[3,3],sigma);
    29. hold on;
    30. for i=1:3
    31. for j=1:3
    32. plot3(i,j,f(j,i),'r*');
    33. end
    34. end
     
     
     
       

      3.Hough变换的优缺点

      优点:

      • 抗噪能力强
      • 对边缘间断不敏感

      缺点:

      • 运算量大:对图像中每一个像素点,都需要计算所有的theta对一个的rho
      • 占用内存多

      Hough变换利用的是一种投票思想


      Reference

      1. stackoverflow=explain hough transformation.http://stackoverflow.com/questions/4709725/explain-hough-transformation
      2. Polar and Cartesian Coordinates. https://www.mathsisfun.com/polar-cartesian-coordinates.html
      3. 百度百科.http://baike.baidu.com/link?url=mSklh9U7fzEEBhsSzfU1rkB4LOKwyptqZREe6KSd1VoNddlX4KVw92d644BVODlklByXHBv2V0fsemww4pD61q
      4. http://www.nabla.hr/Z_MemoHU-015.htm
      5. hough变换是如何检测出直线和圆的? http://blog.163.com/yuyang_tech/blog/static/21605008320130233343990/
      6. 现代数字图像处理技术提高及应用案例详解(MATLAB版). 赵小川
       

      转自: http://www.bfcat.com/index.php/2012/12/inverting-visualizing-features-object-detection/

      所有人都知道,计算机视觉是关于看的学问,在调程序的时候,可视化占到了一大部分的地位。当我们使用描述子的时候我们也希望能够看到这个描述字的图案,例如我们很熟悉的SIFT,SURF等描述子的可视化方式。

      很多做目标检测的人都对HoG特征描述子非常熟悉,也经常用到。MIT的Carl Vondrick(老板是Antonio Torralba)公布了一个可以用来可视化HoG算子的代码。这段代码提供了4种可视化HoG算子的方式,和普通的,直接把描述子画在图像上的方式不同,这几种可视化方式更直观的展示了HoG描述子在图像上的响应。好像让研究者戴上“HoG眼镜”来像计算机一样观察世界。

      在我们用HoG算子进行样本训练的时候,可以利用这种可视化来检查为什么一些负样本会导致虚警,也可以检查正样本自己的类内方差。

      最后,作者还和Weinzaepfel et al.设计的SIFT 可视化方式(P. Weinzaepfel, H. Jegou, and P. Perez. Reconstructing an image from its local descriptors. In CVPR, 2011.)进行了对比。

      这个程序以及技术报告的网页在这里:http://mit.edu/vondrick/ihog/index.html#overview

      https://github.com/cvondrick/ihog

      Pinned

      1. Generating Videos with Scene Dynamics. NIPS 2016.

         Lua  636  130

      2. SoundNet: Learning Sound Representations from Unlabeled Video. NIPS 2016

         Lua  386  84

      3. Efficiently Scaling Up Video Annotation with Crowdsourced Marketplaces. IJCV 2012

         HTML  471  236

      4. Visualizing Object Detection Features. ICCV 2013

         C++  216  131

      5. Simple starter package for training neural nets in torch7

         Lua  55  17

      6. ffmpeg in torch that is simple and easy to install

         Lua  30  10

       
         

      想法:怎么把一些“常识”约束加进来——或者“object 和 ambient things 的关系概率”

      或者检测出来:鸳鸯、水、以及“汽车”之后,再做一轮PK —— 背后的核心思路是说,“汽车”这个物体和周围的从像素到物体的金字塔各层的关联性(共现)要比较好才行~

      pat 点

      CNN网络可视化·Visualizing and Understanding Convolutional Networks

      深度学习


       

      Matthew D. Zeiler,Rob Fergus. Visualizing and Understanding Convolutional Networks.CVPR2014.论文下载



       

      一、相关理论

      本篇博文主要讲解2014年ECCV上的一篇经典文献:《Visualizing and Understanding Convolutional Networks》,可以说是CNN领域可视化理解的开山之作,这篇文献告诉我们CNN的每一层到底学习到了什么特征,然后作者通过可视化进行调整网络,提高了精度。最近两年深层的卷积神经网络,进展非常惊人,在计算机视觉方面,识别精度不断的突破,CVPR上的关于CNN的文献一大堆。然而很多学者都不明白,为什么通过某种调参、改动网络结构等,精度会提高。可能某一天,我们搞CNN某个项目任务的时候,你调整了某个参数,结果精度飙升,但如果别人问你,为什么这样调参精度会飙升呢,你所设计的CNN到底学习到了什么牛逼的特征?

      这篇文献的目的,就是要通过特征可视化,告诉我们如何通过可视化的角度,查看你的精度确实提高了,你设计CNN学习到的特征确实比较牛逼。这篇文献是经典必读文献,才发表了一年多,引用次数就已经达到了好几百,学习这篇文献,对于我们今后深入理解CNN,具有非常重要的意义。总之这篇文章,牛逼哄哄。

       

      二、利用反卷积实现特征可视化

      为了解释卷积神经网络为什么work,我们就需要解释CNN的每一层学习到了什么东西。为了理解网络中间的每一层,提取到特征,paper通过反卷积的方法,进行可视化。反卷积网络可以看成是卷积网络的逆过程。反卷积网络在文献《Adaptive deconvolutional networks for mid and high level feature learning》中被提出,是用于无监督学习的。然而本文的反卷积过程并不具备学习的能力,仅仅是用于可视化一个已经训练好的卷积网络模型,没有学习训练的过程。

      反卷积可视化以各层得到的特征图作为输入,进行反卷积,得到反卷积结果,用以验证显示各层提取到的特征图。举个例子:假如你想要查看Alexnet 的conv5提取到了什么东西,我们就用conv5的特征图后面接一个反卷积网络,然后通过:反池化、反激活、反卷积,这样的一个过程,把本来一张13*13大小的特征图(conv5大小为13*13),放大回去,最后得到一张与原始输入图片一样大小的图片(227*227)。

       

      1、反池化过程

      我们知道,池化是不可逆的过程,然而我们可以通过记录池化过程中,最大激活值得坐标位置。然后在反池化的时候,只把池化过程中最大激活值所在的位置坐标的值激活,其它的值置为0,当然这个过程只是一种近似,因为我们在池化的过程中,除了最大值所在的位置,其它的值也是不为0的。刚好最近几天看到文献:《Stacked What-Where Auto-encoders》,里面有个反卷积示意图画的比较好,所有就截下图,用这篇文献的示意图进行讲解:
      此处输入图片的描述

      以上面的图片为例,上面的图片中左边表示pooling过程,右边表示unpooling过程。假设我们pooling块的大小是3*3,采用max pooling后,我们可以得到一个输出神经元其激活值为9,pooling是一个下采样的过程,本来是3*3大小,经过pooling后,就变成了1*1大小的图片了。而upooling刚好与pooling过程相反,它是一个上采样的过程,是pooling的一个反向运算,当我们由一个神经元要扩展到3*3个神经元的时候,我们需要借助于pooling过程中,记录下最大值所在的位置坐标(0,1),然后在unpooling过程的时候,就把(0,1)这个像素点的位置填上去,其它的神经元激活值全部为0。再来一个例子:
      此处输入图片的描述

      在max pooling的时候,我们不仅要得到最大值,同时还要记录下最大值得坐标(-1,-1),然后再unpooling的时候,就直接把(-1-1)这个点的值填上去,其它的激活值全部为0。

       

      2、反激活

      我们在Alexnet中,relu函数是用于保证每层输出的激活值都是正数,因此对于反向过程,我们同样需要保证每层的特征图为正值,也就是说这个反激活过程和激活过程没有什么差别,都是直接采用relu函数。

       

      3、反卷积

      对于反卷积过程,采用卷积过程转置后的滤波器(参数一样,只不过把参数矩阵水平和垂直方向翻转了一下),这一点我现在也不是很明白,估计要采用数学的相关理论进行证明。

      最后可视化网络结构如下:
      此处输入图片的描述

      网络的整个过程,从右边开始:输入图片-》卷积-》Relu-》最大池化-》得到结果特征图-》反池化-》Relu-》反卷积。到了这边,可以说我们的算法已经学习完毕了,其它部分是文献要解释理解CNN部分,可学可不学。

      总的来说算法主要有两个关键点:1、反池化 2、反卷积,这两个源码的实现方法,需要好好理解。

       

      三、理解可视化

      特征可视化:一旦我们的网络训练完毕了,我们就可以进行可视化,查看学习到了什么东西。但是要怎么看?怎么理解,又是一回事了。我们利用上面的反卷积网络,对每一层的特征图进行查看。

       

      1、特征可视化结果:

      此处输入图片的描述

      总的来说,通过CNN学习后,我们学习到的特征,是具有辨别性的特征,比如要我们区分人脸和狗头,那么通过CNN学习后,背景部位的激活度基本很少,我们通过可视化就可以看到我们提取到的特征忽视了背景,而是把关键的信息给提取出来了。从layer 1、layer 2学习到的特征基本上是颜色、边缘等低层特征;layer 3则开始稍微变得复杂,学习到的是纹理特征,比如上面的一些网格纹理;layer 4学习到的则是比较有区别性的特征,比如狗头;layer 5学习到的则是完整的,具有辨别性关键特征。

       

      2、特征学习的过程。

      此处输入图片的描述

      作者给我们显示了,在网络训练过程中,每一层学习到的特征是怎么变化的,上面每一整张图片是网络的某一层特征图,然后每一行有8个小图片,分别表示网络epochs次数为:1、2、5、10、20、30、40、64的特征图:

      结果:(1)仔细看每一层,在迭代的过程中的变化,出现了sudden jumps;(2)从层与层之间做比较,我们可以看到,低层在训练的过程中基本没啥变化,比较容易收敛,高层的特征学习则变化很大。这解释了低层网络的从训练开始,基本上没有太大的变化,因为梯度弥散嘛。(3)从高层网络conv5的变化过程,我们可以看到,刚开始几次的迭代,基本变化不是很大,但是到了40~50的迭代的时候,变化很大,因此我们以后在训练网络的时候,不要着急看结果,看结果需要保证网络收敛。

       

      3、图像变换。

      从文献中的图片5可视化结果,我们可以看到对于一张经过缩放、平移等操作的图片来说:对网络的第一层影响比较大,到了后面几层,基本上这些变换提取到的特征没什么比较大的变化。

      个人总结:我个人感觉学习这篇文献的算法,不在于可视化,而在于学习反卷积网络,如果懂得了反卷积网络,那么在以后的文献中,你会经常遇到这个算法。大部分CNN结构中,如果网络的输出是一整张图片的话,那么就需要使用到反卷积网络,比如图片语义分割、图片去模糊、可视化、图片无监督学习、图片深度估计,像这种网络的输出是一整张图片的任务,很多都有相关的文献,而且都是利用了反卷积网络,取得了牛逼哄哄的结果。所以我觉得我学习这篇文献,更大的意义在于学习反卷积网络。

      参考文献:

      1、《Visualizing and Understanding Convolutional Networks
      2、《Adaptive deconvolutional networks for mid and high level feature learning
      3、《Stacked What-Where Auto-encoders

      ******************作者:hjimce 时间:2016.1.10 联系QQ:1393852684 原创文章,转载请保留原文地址、作者等信息**********

       
         

      利用pytorch实现Visualising Image Classification Models and Saliency Maps

      素材来源自cs231n-assignment3-NetworkVisualization

      saliency map

      saliency map即特征图,可以告诉我们图像中的像素点对图像分类结果的影响。

      计算它的时候首先要计算与图像像素对应的正确分类中的标准化分数的梯度(这是一个标量)。如果图像的形状是(3, H, W),这个梯度的形状也是(3, H, W);对于图像中的每个像素点,这个梯度告诉我们当像素点发生轻微改变时,正确分类分数变化的幅度。

      计算saliency map的时候,需要计算出梯度的绝对值,然后再取三个颜色通道的最大值;因此最后的saliency map的形状是(H, W)为一个通道的灰度图。

      下图即为例子:

      《利用pytorch实现Visualising Image Classification Models and Saliency Maps》

      上图为图像,下图为特征图,可以看到下图中亮色部分为神经网络感兴趣的部分。

      理论依据

      《利用pytorch实现Visualising Image Classification Models and Saliency Maps》

      《利用pytorch实现Visualising Image Classification Models and Saliency Maps》

      程序解释

      下面为计算特征图函数,上下文信息通过注释来获取。

      1. def compute_saliency_maps(X, y, model):
      2. """
      3. 使用模型图像(image)X和标记(label)y计算正确类的saliency map.
      4. 输入:
      5. - X: 输入图像; Tensor of shape (N, 3, H, W)
      6. - y: 对应X的标记; LongTensor of shape (N,)
      7. - model: 一个预先训练好的神经网络模型用于计算X.
      8. 返回值:
      9. - saliency: A Tensor of shape (N, H, W) giving the saliency maps for the input
      10. images.
      11. """
      12. # Make sure the model is in "test" mode
      13. model.eval()
      14. # Wrap the input tensors in Variables
      15. X_var = Variable(X, requires_grad=True)
      16. y_var = Variable(y)
      17. saliency = None
      18. ##############################################################################
      19. #
      20. # 首先进行前向操作,将输入图像pass through已经训练好的model,再进行反向操作,
      21. # 从而得到对应图像,正确分类分数的梯度
      22. #
      23. ##############################################################################
      24. # 前向操作
      25. scores = model(X_var)
      26. # 得到正确类的分数,scores为[5]的Tensor
      27. scores = scores.gather(1, y_var.view(-1, 1)).squeeze()
      28. #反向计算,从输出的分数到输入的图像进行一系列梯度计算
      29. scores.backward(torch.FloatTensor([1.0,1.0,1.0,1.0,1.0])) # 参数为对应长度的梯度初始化
      30. # scores.backward() 必须有参数,因为此时的scores为非标量,为5个元素的向量
      31. # 得到正确分数对应输入图像像素点的梯度
      32. saliency = X_var.grad.data
      33. saliency = saliency.abs() # 取绝对值
      34. saliency, i = torch.max(saliency,dim=1) # 从3个颜色通道中取绝对值最大的那个通道的数值
      35. saliency = saliency.squeeze() # 去除1维
      36. # print(saliency)
      37. return saliency
      38. 再定义一个显示图像函数,进行图像显示
      39. def show_saliency_maps(X, y):
      40. # Convert X and y from numpy arrays to Torch Tensors
      41. X_tensor = torch.cat([preprocess(Image.fromarray(x)) for x in X], dim=0)
      42. y_tensor = torch.LongTensor(y)
      43. # Compute saliency maps for images in X
      44. saliency = compute_saliency_maps(X_tensor, y_tensor, model)
      45. # Convert the saliency map from Torch Tensor to numpy array and show images
      46. # and saliency maps together.
      47. saliency = saliency.numpy()
      48. N = X.shape[0]
      49. for i in range(N):
      50. plt.subplot(2, N, i + 1)
      51. plt.imshow(X[i])
      52. plt.axis('off')
      53. plt.title(class_names[y[i]])
      54. plt.subplot(2, N, N + i + 1)
      55. plt.imshow(saliency[i], cmap=plt.cm.hot)
      56. plt.axis('off')
      57. plt.gcf().set_size_inches(12, 5)
      58. plt.show()
      59. show_saliency_maps(X, y)

      输出为:

      《利用pytorch实现Visualising Image Classification Models and Saliency Maps》

      另一种梯度的计算法,通过了损失函数计算出来的梯度

      1. out = model( X_var )
      2. loss_func = torch.nn.CrossEntropyLoss()
      3. loss = loss_func( out, y_var )
      4. loss.backward()
      5. grads = X_var.grad
      6. grads = grads.abs()
      7. mx, index_mx = torch.max( grads, 1 )
      8. # print(mx, index_mx)
      9. saliency = mx.data
      10. # print(saliency)

      这中方法的output为:

      《利用pytorch实现Visualising Image Classification Models and Saliency Maps》

      参考资料:

      1、 Karen Simonyan, Andrea Vedaldi, and Andrew Zisserman. “Deep Inside Convolutional Networks: Visualising Image Classification Models and Saliency Maps”, ICLR Workshop 2014.
      2、http://cs231n.stanford.edu/syllabus.html

       
         

      卷积神经网络可视化 

      clgo
        clgo 发布于 2017/09/22 10:44
       
      字数 818
       
      阅读 141
       
      收藏 0
         

      可视化可以让我们知道一个神经网络正在学习什么。当我们建立一个神经网络结构来进行图片分类预测时,我们想要解释网络预测的原理,例如,我们想要知道为什么网络会预测一张图片是宇宙飞船。

      论文一:Deep Inside Convolutional Networks: Visualising Image Classification Models and Saliency Maps

      论文一为可视化一个正在运行的神经网络提供了两种思路,它们都需要计算输出图片相对于输入图片的梯度。

      分类模型可视化:分类任务是产生一个最具代表性的图片。思考:图片的什么地方看起来更像一艘宇宙飞船?我们会发现当图片I的最大分数是Sc(I) 时,这个图片被归类为c。

      注:得分Sc(I)是卷积神经网络输出经过softmax函数得出的值,并不是预测可能性。

      我们可以开始图片I,使用后向传播算法计算相对于I的梯度,使用梯度上升发现一个更好的I。这个过程是非常相似于优化一个神经网络,不同的是,我们保持权重固定不变,优化图片

      点:有点像E-M?也会存在局部极小点的问题?这个问题可以/值得深入研究?

      输入图片说明

      图片分类的显著性:这个任务的目标是发现图片中的那些像素对确定为一个类别有着比较大的影响力。思考:图片中的那些像素对把图片分类为宇宙飞船有着比较大的影响力?记下分数Sc相对于输入图片I,然后计算图片I0。

      输入图片说明

      上面的计算会使我们在每个像素点处获得一个标量值,利用标量值进行正则化可以获得图片的显著图。

      输入图片说明

      图片的显著图可以用来定位感兴趣的目标,使用分割算法进行分割。注意分类模型智能给出类别,不能进行定位,被称为弱监督定位

      论文二: Learning Deep Features for Discriminative Localization

      论文二提出了一种不同的方法可视化图片的显著性图,与论文一使用的后向传播算法不同的是,论文二提出修改前向网络结构实现分类和定位。

      网络使用一系列卷积层作为网络的开始,通过一个图片,卷积网络生成K个特征图。每个特征图包含i*j个激活,f(k)(i,j)代表特征图k中的定位点(i,j)。

      输入图片说明

      注:通常情况,图像分类使用卷积层后接全链接层和softmax层,使得输入图片的大小需要一致,论文二采用特征映射的方法使得网络可以处理不同大小的输入,了解更多可以参考Global Average Pooling

      为了使用上面的结构进行分类操作,我们可以获得一个显著图,也叫激活图,对每一个特征图学习一个权重。

      输入图片说明

      论文二的方法可以从激活图中计算分类分数,同时相对于后向优化可以产生更好的可视化效果(?)

      **参考资料:**https://rajpurkar.github.io/mlx/visualizing-cnns/

       

      Pinned

      1. Visually Explore the Stanford Question Answering Dataset

         JavaScript  338  70

      2. A web tool that enables crowds to label lane complexes in the 3D environment around a car.

         JavaScript  4  5

      3. machine learning experiments

         HTML  7  1

      4. Fast javascript implementation of T-SNE with tree-based acceleration

         JavaScript  10  1

       
         

      http://davidlau.me/2018/01/12/cnn-saliency-maps/

      https://huwang.blog.csdn.net/article/details/78519083

       
         

      http://davidlau.me/archives/

      Nice! 56 posts in total. Keep on posting.

      2019

      淘宝 oCPC 算法笔记

      graph-embedding

      假设检验

      pCTR

      deep-ctr-models

      贝叶斯定理

      Xavier 初始化方法

      RTB 广告竞价策略

      2018

      Lookalike 算法综述

      量化交易笔记

      CNN 模型压缩方法

      Optical Flow

      Loss Function

      AI 精彩视频剪辑:战术竞技类游戏直播

      视频静态区域检测

      小波变换简介

      CNN:目标检测

      CNN:细粒度分类

      Backprop

      CNN 可视化解释:Saliency Maps

      ResNet 学习笔记

      2017

      生成模型

      无约束最优化问题求解

      iOS 私有 API 调用检测机制探讨

      在线学习方法概述

      GloVe

      GBDT

      Reinforce Learning

      Deep Learning

      Activation

      Factorization Machine

      Matrix Factorization

      尝试改进微信读书个性化推荐:一个基于 CTR 预估的方法

      iOS App 启动必 crash 监控

      R 语言线性回归应用:拟合 iOS 录音波形图

      HTML

      基于word2vec协同过滤推荐

      2016

      微信读书冷启动推荐实战:一种基于用户属性的方法

      学习协同过滤推荐 w 100行Python代码

      thai-photos

      初学潜水

      微信读书冷启动用户书籍推荐初探:一个借助微信用户画像的方法

      微信读书排版引擎自动化测试

      iOS 启动连续闪退保护方案

      2015

      尝试解决 Xcode7.1 覆盖率测试 GCDA 文件损坏问题

      notes-on-7-concurrency-model-in-7-weeks

      learn-haskell

      五毛和阴谋论

      SCIP学习笔记

      通过Swift学函数式编程

      笔记:软件开发的转折——并发化

      我的马克思主义观是如何崩塌的

      Google Chrome Canary:一个可以慢速调试css动画的浏览器

      2014

      TODO

      每晚睡4.5小时,保持精力充沛的秘诀

      编程珠玑II C12笔记: rand num generator

       
       
         

      对卷积网络可视化与可解释性相关资料的一些整理,不断更新中~

      目的

      • 可视化网络的关注区域(attention map),理解与分析网络的学习情况
      • 利用可视化的信息引导网络更好的学习

      博客:

      论文:

      代码:

      《Deep learning with python》下载地址​pan.baidu.com

       

      1. Visualizing and Understanding Convolutional Networks
      https://arxiv.org/pdf/1311.2901v3.pdf
      https://neukom.dartmouth.edu/docs/bbat-wacv2016.pdf
      http://cs231n.github.io/understanding-cnn/
      
      2. Net surgery trick
      http://cs231n.github.io/convolutional-networks/#convert
      https://github.com/BVLC/caffe/blob/master/examples/net_surgery.ipynb
      
      https://leonardoaraujosantos.gitbooks.io/artificial-inteligence/content/image_segmentation.html
      https://arxiv.org/pdf/1502.02766v3.pdf
      https://arxiv.org/pdf/1411.4038v2.pdf
      http://www.cv-foundation.org/openaccess/content_cvpr_2015/papers/Long_Fully_Convolutional_Networks_2015_CVPR_paper.pdf
      https://arxiv.org/pdf/1605.06211v1.pdf
      
      `convert fully connected layers to their
          equivalent convolutional layers, since the weights are the same and only
          the shapes are different.`
      
      3. Global average pooling layer
      Network In Network
      https://arxiv.org/pdf/1312.4400.pdf
      
      4. Learning Deep Features for Discriminative Localization
      http://cnnlocalization.csail.mit.edu/
      https://github.com/jacobgil/keras-cam
      
      5. Grad-CAM: Gradient-weighted Class Activation Mapping
      https://github.com/ramprs/grad-cam
      http://gradcam.cloudcv.org/
      https://arxiv.org/pdf/1610.02391v2.pdf
      
      6. Is object localization for free? – Weakly Supervised Object Recognition with Convolutional Neural Networks
      http://www.di.ens.fr/willow/research/weakcnn/
      http://www.di.ens.fr/willow/research/cnn/
      

      Additional:

      1. Deep Inside Convolutional Networks: Visualising Image Classification Models and Saliency Maps
      https://arxiv.org/pdf/1312.6034v2.pdf
      
      2. Top-down NeuralAttention by Excitation Backprop (c-MWP)
      https://arxiv.org/pdf/1608.00507v1.pdf
      http://cs-people.bu.edu/jmzhang/excitationbp.html
      
      3. Paying More Attention to Attention: Improving the Performance of Convolutional Neural Networks via Attention Transfer
      https://arxiv.org/pdf/1612.03928v1.pdf
      https://github.com/szagoruyko/attention-transfer
      
      4. Visualizing Deep Neural Network Decisions: Prediction Difference Analysis
      https://openreview.net/pdf?id=BJ5UeU9xx
      https://github.com/lmzintgraf/DeepVis-PredDiff
      A New Method to Visualize Deep Neural Networks
      https://icmlviz.github.io/assets/papers/23.pdf
      
      5. Self-Taught Object Localization with Deep Network
      https://arxiv.org/pdf/1409.3964.pdf
      
      6. Shallow and Deep Convolutional Networks for Saliency Prediction
      https://github.com/imatge-upc/saliency-2016-cvpr
      

      Keras codebase:

      https://github.com/raghakot/keras-vis
      
      Oclusion based technique:
      https://github.com/waleedka/cnn-visualization/blob/master/cnn_visualization.ipynb
      
      Net surgery trick:
      https://github.com/heuritech/convnets-keras
      
      GAP-CAM
      https://github.com/alexisbcook/ResNetCAM-keras/
      https://github.com/jacobgil/keras-cam
      https://github.com/tdeboissiere/VGG16CAM-keras
      
      Grad-CAM
      https://github.com/jacobgil/keras-grad-cam
      
      https://raghakot.github.io/keras-vis/visualizations/attention/
      
      https://github.com/mlhy/ResNet-50-for-Cats.Vs.Dogs
      

      Tensorflow codebase:

      GAP
      https://github.com/sjchoi86/tensorflow-101/blob/master/notebooks/gap_mnist.ipynb
      
      GAP-CAM
      https://github.com/jazzsaxmafia/Weakly_detector
      
      Grad-CAM
      https://github.com/Ankush96/grad-cam.tensorflow
      

      PyTorch

      Grad-CAM
      https://github.com/kazuto1011/grad-cam-pytorch
      
      GAP-CAM
      https://github.com/metalbubble/CAM/blob/master/pytorch_CAM.py
      
      SPN
      https://github.com/yeezhu/SPN.pytorch
      
      https://github.com/utkuozbulak/pytorch-cnn-visualizations
      
      https://github.com/jacobgil/pytorch-explain-black-box
      

      Regression Activation Map

      https://github.com/cauchyturing/kaggle_diabetic_RAM
      

      Other

      https://github.com/metalbubble/cnnvisualizer
      
      https://github.com/InFoCusp/tf_cnnvis
      
      https://github.com/ppwwyyxx/tensorpack/tree/master/examples/Saliency
      
      https://github.com/InFoCusp/tf_cnnvis
      
      https://github.com/keplr-io/quiver
      
      https://jacobgil.github.io/deeplearning/vehicle-steering-angle-visualizations
      https://jacobgil.github.io/deeplearning/class-activation-maps
      
      https://jacobgil.github.io/deeplearning/filter-visualizations
      https://jacobgil.github.io/computervision/saliency-from-backproj
      
      https://github.com/CSAILVision/NetDissect
      
      https://medium.com/merantix/picasso-a-free-open-source-visualizer-for-cnns-d8ed3a35cfc5
      
      https://github.com/CSAILVision/NetDissect
      http://netdissect.csail.mit.edu/
      
      https://github.com/imatge-upc/saliency-salgan-2017
      
      http://imatge-upc.github.io/saliency-2016-cvpr/
      https://github.com/imatge-upc/saliency-2016-cvpr
      

      Visualization:

      https://github.com/shaohua0116/Activation-Visualization-Histogram
      

      To look at:

      http://blog.qure.ai/notes/visualizing_deep_learning
      编辑于 2019-01-09
       
       
         
       

      CNN可视化

      [TOC]

      Markdown Revision 1;
      Date: 2019/07/23
      Editor: Tan
      Contact: scutjy2015@163.com
      

      参考文献:胡秀. 基于卷积神经网络的图像特征可视化研究[D].

      ​ 对 CNN 模型的可解释性问题,也称之为深度可视化问题[35]。目前深度可视化方法主要分为两大类,一类通过前向计算直接可视化深度卷积网络每一层的卷积核以及提取的特征图,然后观察其数值变化。一个训练成功的 CNN 网络,其特征图的值会伴随网络深度的加深而越来越稀疏。

      ​ 另一类可视化方法则通过反向计算,将低维度的特征图反向传播至原图像像素空间,观察特征图被原图的哪一部分激活,从而理解特征图从原图像中学习了何种特征。经典方法有反卷积(Deconvolution)[36]和导向反向传播(Guided-backpropagation)。这两种方法能够在一定程度上“看到”CNN 模型中较深的卷积层所学习到的特征。从本质上说,反卷积和导向反向传播的基础都是反向传播,即对输入进行求导。二者唯一的区别在于反向传播过程中经过 ReLU 层时对梯度的处理策略不同。虽然借助反卷积和导向反向传播方法,能够了解 CNN 模型神秘的内部,但这些方法同时把所有能提取的特征都展示出来了,而对类别并不敏感,因此还不能解释 CNN 分类的结果。

      ​ 为了更好地理解 CNN,近几年有大量研究工作都在对 CNN 所学到的内部特征进行可视化分析。最初的可视化工作由多伦多大学的 Krizhevshy 等人在 2012 年提出的AlexNet 一文中出现[20]。在这篇开创深度学习新纪元的论文中,Krizhevshy 直接可视化了第一个卷积层的卷积核,如图 1-4 所示[20]。最早使用图片块来可视化卷积核是在 RCNN论文中出现[37]。Girshick 的工作显示了数据库中对 AlexNet 模型较高层某个通道具有较强响应的图片块。如图 1-5 所示[37]

      ​ 另一种可视化神经网络的思路是通过特征重构出图像,将重构结果与原图进行比较来分析 CNN 的每一层保留了图像的哪些特征。这种可视化思路将 CNN 提取特征的过程视为编码的过程,而对提取到的特征进行重建的过程正好是编码的逆过程,称为解码过程。2014 年,Aravindh Mahendran 等人就提出这种通过重构特征的思想来可视化分析CNN[39]。图像理解的关键部分是图像特征表达。而人对图像特征表征的理解是有限的,因此 Mahendran 采用了一种反演的方法来分析图像特征中所含的视觉信息。之后,Mahendran 又加入自然图像先验的信息进一步通过一些可视化技术来加深人们对图像表示的理解。

      ​ 2015 年,Yosinski[40]根据以往的可视化成果开发出了两个可视化 CNN 模型的工具。其中一个是针对已经训练好的网络,当传入一张图片或一段视频时,通过对该网络中每一层的激活值进行可视化。另一个可视化工具是通过在图像空间加正则化优化来对深度神经网络每一层提取的特征进行可视化。

      ​ 在通过重建特征可视化 CNN 的基础上,2016 年,Alexey Dosovitskiy 等人通过建立一个上卷积神经网络(Up-Convolutional Neural Networks,UCNN),对 CNN 不同层提取的图像特征进行重建,从而可以知道输入图像中的哪些信息被保留在所提取的特征中[32]。尽管这种方法也能对全连接层进行可视化,也只是显示全连接层保留了哪些信息,而未对这些信息的相关性及重要性进行分析[41]。

      ​ 周伯雷等人[42]提出的类别激活映射(Class Activation Mapping,CAM)可视化方法,采用 NIN 和 GoogLeNet 中所用到的全局平均池化(Global Average Pooling,GAP),将卷积神经网络最后的全连接层换成全卷积层,并将输出层的权重反向投影至卷积层特征。这一结构的改进能有效定位图像中有助于分类任务的关键区域。从定位的角度来讲,CAM 方法还能起到目标检测的作用,而且不需要给出目标的边框就能大概定位出图像中的目标位置。尽管CAM已经达到了很不错的可视化效果,但要可视化一个通用的CNN模型,就需要用 GAP 层取代最后的全连接层,这就需要修改原模型的结构,导致重新训练该模型带来大量的工作,限制了 CAM 的使用场景。2016 年,R.Selvaraju 等人[43]

      在 CAM 的基础上提出了 Grad-CAM。CAM 通过替换全连接层为 GAP 层,重新训练得到权重,而 Grad-CAM 另辟蹊径,用梯度的全局平均来计算每对特征图对应的权重,最后求一个加权和。Grad-CAM 与 CAM 的主要区别在于求权重的过程。

      Deep Visualization:可视化并理解CNN

      https://blog.csdn.net/zchang81/article/details/78095378

      谷歌的新CNN特征可视化方法,构造出一个华丽繁复的新世界

      https://www.leiphone.com/news/201711/aNw8ZjqMuqvygzlz.html

      CNN可视化理解的最新综述

      http://m.elecfans.com/article/686276.html

      CNN模型的可视化

      http://www.cctime.com/html/2018-4-12/1373705.htm

      CNN特征可视化报告

      https://wenku.baidu.com/view/86311603f011f18583d049649b6648d7c1c708ed.html

      Visualizing and Understanding Convolutional Networks https://arxiv.org/pdf/1311.2901.pdf

      ​ 深度可视化技术己经成为了深度学习中一个学术研究热点,但仍然处于探索阶段。本文的主要研究对象是深度神经网络中数以千计的卷积滤波器。深度神经网络中不同的滤波器会从输入图像中提取不同特征表示。己有的研究表明低层的卷积核提取了图像的低级语义特性(如边缘、角点),高层的卷积滤波器提取了图像的高层语义特性(如图像类别)。但是,由于深度神经网络会以逐层复合的方式从输入数据中提取特征,我们仍然无法像Sobel算子提取的图像边缘结果图一样直观地观察到深度神经网络中的卷积滤波器从输入图像中提取到的特征表示。

      第一章 卷积神经网络

      https://www.toutiao.com/a6725276071358366215/?tt_from=weixin&utm_campaign=client_share&wxshare_count=1&timestamp=1566823385&app=news_article&utm_source=weixin&utm_medium=toutiao_android&req_id=20190826204304110249203143263D4EED&group_id=6725276071358366215

      「深度学习系列」CNN模型的可视化

      这个网站有cvpr今年的可解释性的文献集合,还挺多的http://openaccess.thecvf.com/CVPR2019_workshops/CVPR2019_Explainable_AI.py、

      一个很好的可视化网站:http://shixialiu.com/publications/cnnvis/demo/

      1.1 网络结构

      1.2 训练过程

      1.3 网络搭建

      1.4 优化算法

      第二章 CNN可视化概述

      2.5 窥探黑盒-卷积神经网络的可视化**

      https://blog.csdn.net/shenziheng1/article/details/85058430

      目前卷积深度表示的可视化/解释方法

      中间激活态/特征图可视化。

      也就是对卷积神经网络的中间输出特征图进行可视化,这有助于理解卷积神经网络连续的层如何对输入的数据进行展开变化,也有注意了解卷及神经网络每个过滤器的含义。 更深入的, 笔者曾经讲中间激活态结合‘注意力机制’进行联合学习,确实显著提高了算法的精度。

      空间滤波器组可视化。

      卷积神经网络学习的实质可以简单理解为学习一系列空间滤波器组的参数。可视化滤波器组有助于理解视觉模式/视觉概念。 更深入的,笔者曾经思考过,如何才能引导dropout趋向各项同性空间滤波器。因为从视觉感知对信息的捕捉效果来看,更倾向于捕捉高频成分,诸如边缘特征、纹理等。

      原始图像中各组分贡献热力图。

      我们都知道,卷积神经网络是基于感受野以及感受野再次组合进行特征提取的。但是我们需要了解图像中各个部分对于目标识别的贡献如何?这里将会介绍一种hotmap的形式,判断图像中各个成分对识别结果的贡献度概率。

      作者:沈子恒 来源:CSDN 原文:https://blog.csdn.net/shenziheng1/article/details/85058430 版权声明:本文为博主原创文章,转载请附上博文链接!

      2.1 背景介绍

      ​ 在当前深度学习的领域,有一个非常不好的风气:一切以经验论,好用就行,不问为什么,很少深究问题背后的深层次原因。从长远来看,这样做就埋下了隐患。举个例子,在1980年左右的时候,美国五角大楼启动了一个项目:用神经网络模型来识别坦克(当时还没有深度学习的概念),他们采集了100张隐藏在树丛中的坦克照片,以及另100张仅有树丛的照片。一组顶尖的研究人员训练了一个神经网络模型来识别这两种不同的场景,这个神经网络模型效果拔群,在测试集上的准确率尽然达到了100%!于是这帮研究人员很高兴的把他们的研究成果带到了某个学术会议上,会议上有个哥们提出了质疑:你们的训练数据是怎么采集的?后来进一步调查发现,原来那100张有坦克的照片都是在阴天拍摄的,而另100张没有坦克的照片是在晴天拍摄的……也就是说,五角大楼花了那么多 的经费,最后就得到了一个用来区分阴天和晴天的分类模型。 当然这个故事应该是虚构的,不过它很形象的说明了什么叫“数据泄露”,这在以前的Kaggle比赛中也曾经出现过。大家不妨思考下,假如我们手里现在有一家医院所有医生和护士的照片,我们希望训练出一个图片分类模型,能够准确的区分出医生和护士。当模型训练完成之后,准确率达到了99%,你认为这个模型可靠不可靠呢?大家可以自己考虑下这个问题。

      ​ 好在学术界的一直有人关注着这个问题,并引申出一个很重要的分支,就是模型的可解释性问题。那么本文从就从近几年来的研究成果出发,谈谈如何让看似黑盒的CNN模型“说话”,对它的分类结果给出一个解释。注意,本文所说的“解释”,与我们日常说的“解释”内涵不一样:例如我们给孩子一张猫的图片,让他解释为什么这是一只猫,孩子会说因为它有尖耳朵、胡须等。而我们让CNN模型解释为什么将这张图片的分类结果为猫,只是让它标出是通过图片的哪些像素作出判断的。(严格来说,这样不能说明模型是否真正学到了我们人类所理解的“特征”,因为模型所学习到的特征本来就和人类的认知有很大区别。何况,即使只标注出是通过哪些像素作出判断就已经有很高价值了,如果标注出的像素集中在地面上,而模型的分类结果是猫,显然这个模型是有问题的)

      作者:丽宝儿 来源:CSDN 原文:https://blog.csdn.net/heruili/article/details/90214280 版权声明:本文为博主原创文章,转载请附上博文链接!

      2.2 反卷积和导向反向传播

      ​ 关于CNN模型的可解释问题,很早就有人开始研究了,姑且称之为CNN可视化吧。比较经典的有两个方法,反卷积(Deconvolution)和导向反向传播(Guided-backpropagation),通过它们,我们能够一定程度上“看到”CNN模型中较深的卷积层所学习到的一些特征。当然这两个方法也衍生出了其他很多用途,以反卷积为例,它在图像语义分割中有着非常重要的作用。

      2.2.1 反向传播

      2.2.2 反卷积

      2.2.3 导向反向传播

      2.2.4 反卷积、导向反向传播和反向传播的区别

      ​ 从本质上说,反卷积和导向反向传播的基础都是反向传播,其实说白了就是对输入进行求导,三者唯一的区别在于反向传播过程中经过ReLU层时对梯度的不同处理策略。

      作者:丽宝儿 来源:CSDN 原文:https://blog.csdn.net/heruili/article/details/90214280 版权声明:本文为博主原创文章,转载请附上博文链接!

      第三章 基于反卷积的特征可视化

      使用反卷积(Deconvnet)可视化CNN卷积层,查看各层学到的内容

      https://blog.csdn.net/sean2100/article/details/83663212

      ​ 为了解释卷积神经网络为什么work,我们就需要解释CNN的每一层学习到了什么东西。为了理解网络中间的每一层,提取到特征,paper通过反卷积的方法,进行可视化。反卷积网络可以看成是卷积网络的逆过程。反卷积网络在文献《Adaptive deconvolutional networks for mid and high level feature learning》中被提出,是用于无监督学习的。然而本文的反卷积过程并不具备学习的能力,仅仅是用于可视化一个已经训练好的卷积网络模型,没有学习训练的过程。

      ​ 反卷积可视化以各层得到的特征图作为输入,进行反卷积,得到反卷积结果,用以验证显示各层提取到的特征图。举个例子:假如你想要查看Alexnet 的conv5提取到了什么东西,我们就用conv5的特征图后面接一个反卷积网络,然后通过:反池化、反激活、反卷积,这样的一个过程,把本来一张1313大小的特征图(conv5大小为1313),放大回去,最后得到一张与原始输入图片一样大小的图片(227*227)。

      3.1 反池化过程

      我们知道,池化是不可逆的过程,然而我们可以通过记录池化过程中,最大激活值得坐标位置。然后在反池化的时候,只把池化过程中最大激活值所在的位置坐标的值激活,其它的值置为0,当然这个过程只是一种近似,因为我们在池化的过程中,除了最大值所在的位置,其它的值也是不为0的。刚好最近几天看到文献:《Stacked What-Where Auto-encoders》,里面有个反卷积示意图画的比较好,所有就截下图,用这篇文献的示意图进行讲解:

      以上面的图片为例,上面的图片中左边表示pooling过程,右边表示unpooling过程。假设我们pooling块的大小是33,采用max pooling后,我们可以得到一个输出神经元其激活值为9,pooling是一个下采样的过程,本来是33大小,经过pooling后,就变成了11大小的图片了。而upooling刚好与pooling过程相反,它是一个上采样的过程,是pooling的一个反向运算,当我们由一个神经元要扩展到33个神经元的时候,我们需要借助于pooling过程中,记录下最大值所在的位置坐标(0,1),然后在unpooling过程的时候,就把(0,1)这个像素点的位置填上去,其它的神经元激活值全部为0。再来一个例子:

      在max pooling的时候,我们不仅要得到最大值,同时还要记录下最大值得坐标(-1,-1),然后再unpooling的时候,就直接把(-1-1)这个点的值填上去,其它的激活值全部为0。

      3.2 反激活

      我们在Alexnet中,relu函数是用于保证每层输出的激活值都是正数,因此对于反向过程,我们同样需要保证每层的特征图为正值,也就是说这个反激活过程和激活过程没有什么差别,都是直接采用relu函数。

      3.3 反卷积

      对于反卷积过程,采用卷积过程转置后的滤波器(参数一样,只不过把参数矩阵水平和垂直方向翻转了一下),反卷积实际上应该叫卷积转置。 最后可视化网络结构如下:

      网络的整个过程,从右边开始:输入图片-》卷积-》Relu-》最大池化-》得到结果特征图-》反池化-》Relu-》反卷积。到了这边,可以说我们的算法已经学习完毕了,其它部分是文献要解释理解CNN部分,可学可不学。

      总的来说算法主要有两个关键点:1、反池化 2、反卷积,这两个源码的实现方法,需要好好理解。

      3.4 特征可视化结果

      特征可视化:一旦我们的网络训练完毕了,我们就可以进行可视化,查看学习到了什么东西。但是要怎么看?怎么理解,又是一回事了。我们利用上面的反卷积网络,对每一层的特征图进行查看。

      总的来说,通过CNN学习后,我们学习到的特征,是具有辨别性的特征,比如要我们区分人脸和狗头,那么通过CNN学习后,背景部位的激活度基本很少,我们通过可视化就可以看到我们提取到的特征忽视了背景,而是把关键的信息给提取出来了。从layer 1、layer 2学习到的特征基本上是颜色、边缘等低层特征;layer 3则开始稍微变得复杂,学习到的是纹理特征,比如上面的一些网格纹理;layer 4学习到的则是比较有区别性的特征,比如狗头;layer 5学习到的则是完整的,具有辨别性关键特征。

      3.5 特征学习的过程

      作者给我们显示了,在网络训练过程中,每一层学习到的特征是怎么变化的,上面每一整张图片是网络的某一层特征图,然后每一行有8个小图片,分别表示网络epochs次数为:1、2、5、10、20、30、40、64的特征图:

      结果:(1)仔细看每一层,在迭代的过程中的变化,出现了sudden jumps;(2)从层与层之间做比较,我们可以看到,低层在训练的过程中基本没啥变化,比较容易收敛,高层的特征学习则变化很大。这解释了低层网络的从训练开始,基本上没有太大的变化,因为梯度弥散嘛。(3)从高层网络conv5的变化过程,我们可以看到,刚开始几次的迭代,基本变化不是很大,但是到了40~50的迭代的时候,变化很大,因此我们以后在训练网络的时候,不要着急看结果,看结果需要保证网络收敛。

      第四章 基于类别激活映射的特征可视化

      4.1 GAP

      让我们小小地绕行一下,先介绍下**全局平均池化(global average pooling,GAP)**这一概念。为了避免全连接层的过拟合问题,网中网(Network in Network)提出了GAP层。GAP层,顾名思义,就是对整个特征映射应用平均池化,换句话说,是一种极端激进的平均池化。 作者:论智链接:https://www.zhihu.com/question/274926848/answer/473562723来源:知乎著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

      4.2 CAM

      从另一方面来说,GAP层的输出,可以认为是“简要概括”了之前卷积层的特征映射。在网中网架构中,GAP后面接softmax激活,ResNet-50中,GAP层后面接一个带softmax激活的全连接层。softmax激活是为了保证输出分类的概率之和为1,对于热图来说,我们并不需要这一约束。所以可以把softmax拿掉。拿掉softmax的全连接层,其实就是线性回归。结果发现,这样一处理,效果挺不错的: 作者:论智链接:https://www.zhihu.com/question/274926848/answer/473562723来源:知乎著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

      4.3 Grad-CAM

      但是CAM要发挥作用,前提是网络架构里面有GAP层,但并不是所有模型都配GAP层的。另外,线性回归的训练是额外的工作。为了克服CAM的这些缺陷,Selvaraju等提出了Grad-CAM。其基本思路是对应于某个分类的特征映射的权重可以表达为梯度,这样就不用额外训练线性回归(或者说线性层)。然后全局平均池化其实是一个简单的运算,并不一定需要专门使用一个网络层。

      作者:论智 链接:https://www.zhihu.com/question/274926848/answer/473562723 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

      基于局部梯度的神经网络可视化解释

      https://www.jianshu.com/p/53062ee77e62

      4.4 Grad-CAM++

      为了得到更好的效果(特别是在某一分类的物体在图像中不止一个的情况下),Chattopadhyay等又进一步提出了Grad-CAM++,主要的变动是在对应于某个分类的特征映射的权重表示中加入了ReLU和权重梯度

      4.5 CAM、Grad-CAM、Grad-CAM++架构对比

      https://blog.csdn.net/weixin_39875161/article/details/90553266

      4.6 LIME

      http://bindog.github.io/blog/2018/02/11/model-explanation-2/

      4.1 CAM

      CAM方法获取显著图:基于pytorch的实现https://blog.csdn.net/zsx1713366249/article/details/87902476

      4.2 Grad-CAM

      凭什么相信你,我的CNN模型?

      http://bindog.github.io/blog/2018/02/10/model-explanation/

      4.3 Grad-CAM

      2.2.2.2 卷积神经网络可视化——Grad CAM Python实现

      https://blog.csdn.net/ZWX2445205419/article/details/86521829

      2.2.3 请问注意力机制中生成的类似热力图或者柱状图是如何生成的?

      https://www.zhihu.com/question/274926848/answer/473562723

      代码

      GitHub上有不少Grad-CAM(++)的实现,你可以根据情况自行选择。例如:

      当然,你也可以根据Grad-CAM++论文自行实现。

      2.2.3.5 Guided Grad-CAM(导向反向传播和Grad-CAM的结合)

      1)问题:虽然Grad-CAM可以很好的类别判别能力,也可以将相关区域定位出来,但是其不具备像素空间梯度可视化(比如导向反向传播和反卷积这种细粒度重要性可视化)的方法  2)解决问题:   2.1)首先对图像使用插值法进行上采样   2.2)然后将导向反向传播和Grad-CAM结合起来,实现可视化

      第五章 用优化方法形成可视化

      谷歌的新CNN特征可视化方法,构造出一个华丽繁复的新世界

      https://www.leiphone.com/news/201711/aNw8ZjqMuqvygzlz.html

      雷锋网 AI 科技评论按:深度神经网络解释性不好的问题一直是所有研究人员和商业应用方案上方悬着的一团乌云,现代CNN网络固然有强大的特征抽取能力,但没有完善的理论可以描述这个抽取过程的本质,人类也很难理解网络学到的表征。

      当然了,研究人员们从来都不会放弃尝试。IMCL 2017的最佳论文奖就颁给了 Pang Wei Koh 和 Percy Liang的「Understanding Black-box Predictions via Influence Functions」,探究训练数据对模型训练过程的影响(现场演讲全文点这里);近期引发全面关注的 Geoffery Hinton的胶囊论文也通过多维激活向量带来了更好的解释性,不同的维度表征着不同的属性(虽然解释性的提高算不上是他的原意;论文全文翻译看这里)。

      近日,来自谷歌大脑和谷歌研究院的一篇技术文章又从一个新的角度拓展了人类对神经网络的理解,得到的可视化结果也非常亮眼、非常魔性,比如下面这样,文中的结果也在Twitter上引发了许多关注和讨论。

      这表达的是什么?这又是怎么来的呢?雷锋网 AI 科技评论把研究内容详细介绍如下。

      5.1 用优化方法形成可视化

      作者们的目标是可视化呈现让网络激活的那些特征,也就是回答“模型都在图像中找什么特征”这个问题。他们的思路是新生成一些会让网络激活的图像,而不是看那些数据集中已有的能让网络激活的图像,因为已有图像中的特征很可能只是“有相关性”,在分析的时候可能只不过是“人类从许多特征中选出了自己认为重要的”,而下面的优化方法就能真正找到图像特征和网络行为中的因果性。

      总体来说,神经网络是关于输入可微的。如果要找到引发网络某个行为的输入,不管这个行为只是单个神经元的激活还是最终的分类器输出,都可以借助导数迭代地更新输入,最终确认输入图像和选定特征之间的因果关系。(实际执行中当然还有一些技巧,见下文“特征可视化的实现过程”节)

      从随机噪音开始,迭代优化一张图像让它激活指定的某一个神经元(以4a层的神经元11为例)

      作者们基于带有 Inception 模块的 GoogLeNet展开了研究,这是一个2014年的模型 (https://arxiv.org/pdf/1409.4842.pdf ),当年也以6.67%的前5位错误率拿下了 ILSVRC 2014图像分类比赛的冠军。模型结构示意图如下;训练数据集是 ImageNet。

      GoogLeNet 结构示意图。共有9个Inception模块;3a模块前有两组前后连接的卷积层和最大池化层;3b和4a、4e和5a之间各还有一个最大池化层。

      5.2 优化目标

      有了思路和网络之后就要考虑以网络的哪部分结构作为输入优化的目标;即便对于在数据集中找样本的方法也需要考虑这个。这里就有很多种选择,是单个神经元、某个通道、某一层、softmax前的类别值还是softmax之后的概率。不同的选择自然会带来不同的可视化结果,如下图

      以不同的网络结构为目标可以找到不同的输入图像。这里 n 为层序号,x,y 为空间位置, z 为通道序号,k 为类别序号。

      要理解网络中的单个特征,比如特定位置的某个神经元、或者一整个通道,就可以找让这个特征产生很高的值的样本。文中多数的图像都是以通道作为目标生成的。

      要理解网络中的完整一层,就可以用 DeepDream的目标,找到整个层觉得“有兴趣”的图像。

      要从分类器的阶段出发找到输入样本的话,会遇到两个选择,优化softmax前的类别值还是优化softmax后的类别概率。softmax前的类别值其实可以看作每个类别出现的证据确凿程度,softmax后的类别概率就是在给定的证据确凿程度之上的似然值。不过不幸的是,增大softmax后的某一类类别概率的最简单的办法不是让增加这一类的概率,而是降低别的类的概率。所以根据作者们的实验,以softmax前的类别值作为优化目标可以带来更高的图像质量。

      5.3 可视化结果一:不同的层优化得到不同的图像

      3a层

      第一个Inception层就已经显示出了一些有意思的纹理。由于每个神经元只有一个很小的感受野,所以整个通道的可视化结果就像是小块纹理反复拼贴的结果。

      3b层

      纹理变得复杂了一些,但还都是比较局部的特征

      4a层

      4a层跟在了一个最大池化层之后,所以可以看到复杂性大幅度增加。图像中开始出现更复杂的模式,甚至有物体的一部分。

      4b层

      谷歌的新CNN特征可视化方法,构造出一个华丽繁复的新世界

      可以明显看到物体的某些部分了,检测台球的例子中就能清楚看到球的样子。这时的可视化结果也开始带有一些环境信息,比如树的例子中就能看到树背后的蓝天和树脚下的地面。

      4c层

      谷歌的新CNN特征可视化方法,构造出一个华丽繁复的新世界

      这一层的结果已经足够复杂了,只看几个神经元的优化结果可以比看整个通道更有帮助。有一些神经元只关注拴着的小狗,有的只关注轮子,也有很多其它的有意思的神经元。这也是作者们眼中最有收获的一层。

      4d层

      谷歌的新CNN特征可视化方法,构造出一个华丽繁复的新世界

      这一层中有更复杂的概念,比如第一张图里的某种动物的口鼻部分。另一方面,也能看到一些神经元同时对多个没什么关系的概念产生响应。这时需要通过优化结果的多样性和数据集中的样本帮助理解神经元的行为。

      4e层

      谷歌的新CNN特征可视化方法,构造出一个华丽繁复的新世界

      在这一层,许多神经元已经可以分辨不同的动物种类,或者对多种不同的概念产生响应。不过它们视觉上还是很相似,就会产生对圆盘天线和墨西哥宽边帽都产生反应的滑稽情况。这里也能看得到关注纹理的检测器,不过这时候它们通常对更复杂的纹理感兴趣,比如冰激凌、面包和花椰菜。这里的第一个例子对应的神经元正如大家所想的那样对可以乌龟壳产生反应,不过好玩的是它同样也会对乐器有反应。

      5a层

      谷歌的新CNN特征可视化方法,构造出一个华丽繁复的新世界

      这里的可视化结果已经很难解释了,不过它们针对的语义概念都还是比较特定的

      5b层

      谷歌的新CNN特征可视化方法,构造出一个华丽繁复的新世界

      这层的可视化结果基本都是找不到任何规律的拼贴组合。有可能还能认得出某些东西,但基本都需要多样性的优化结果和数据集中的样本帮忙。这时候能激活神经元的似乎并不是有什么特定语义含义的结构。

      5.4 可视化结果二:样本的多样性

      其实得到可视性结果之后就需要回答一个问题:这些结果就是全部的答案了吗?由于过程中存在一定的随机性和激活的多重性,所以即便这些样本没什么错误,但它们也只展示了特征内涵的某一些方面。

      不同激活程度的样本

      在这里,作者们也拿数据集中的真实图像样本和生成的样本做了比较。真实图像样本不仅可以展现出哪些样本可以极高程度地激活神经元,也能在各种变化的输入中看到神经元分别激活到了哪些程度。如下图

      谷歌的新CNN特征可视化方法,构造出一个华丽繁复的新世界

      谷歌的新CNN特征可视化方法,构造出一个华丽繁复的新世界

      谷歌的新CNN特征可视化方法,构造出一个华丽繁复的新世界

      可以看到,对真实图像样本来说,多个不同的样本都可以有很高的激活程度。

      多样化样本

      作者们也根据相似性损失或者图像风格转换的方法产生了多样化的样本。如下图

      谷歌的新CNN特征可视化方法,构造出一个华丽繁复的新世界

      多样化的特征可视化结果可以更清晰地看到是哪些结构能够激活神经元,而且可以和数据集中的照片样本做对比,确认研究员们的猜想的正确性(这反过来说就是上文中理解每层网络的优化结果时有时需要依靠多样化的样本和数据集中的样本)。

      谷歌的新CNN特征可视化方法,构造出一个华丽繁复的新世界

      比如这张图中,单独看第一排第一张简单的优化结果,我们很容易会认为神经元激活需要的是“狗头的顶部”这样的特征,因为优化结果中只能看到眼睛和向下弯曲的边缘。在看过第二排的多样化样本之后,就会发现有些样本里没有包含眼睛,有些里包含的是向上弯曲的边缘。这样,我们就需要扩大我们的期待范围,神经元的激活靠的可能主要是皮毛的纹理。带着这个结论再去看看数据集中的样本的话,很大程度上是相符的;可以看到有一张勺子的照片也让神经元激活了,因为它的纹理和颜色都和狗的皮毛很相似。

      对更高级别的神经元来说,多种不同类别的物体都可以激活它,优化得到的结果里也就会包含这各种不同的物体。比如下面的图里展示的就是能对多种不同的球类都产生响应的情况。

      谷歌的新CNN特征可视化方法,构造出一个华丽繁复的新世界

      这种简单的产生多样化样本的方法有几个问题:首先,产生互有区别的样本的压力会在图像中增加无关的瑕疵;而且这个优化过程也会让样本之间以不自然的方式产生区别。比如对于上面这张球的可视化结果,我们人类的期待是看到不同的样本中出现不同种类的球,但实际上更像是在不同的样本中出现了各有不同的特征。

      多样性方面的研究也揭露了另一个更基础的问题:上方的结果中展示的都还算是总体上比较相关、比较连续的,也有一些神经元感兴趣的特征是一组奇怪的组合。比如下面图中的情况,这个神经元对两种动物的面容感兴趣,另外还有汽车车身。

      谷歌的新CNN特征可视化方法,构造出一个华丽繁复的新世界

      类似这样的例子表明,想要理解神经网络中的表义过程时,神经元可能不一定是合适的研究对象。

      5.5 可视化结果三:神经元间的互动

      如果神经元不是理解神经网络的正确方式,那什么才是呢?作者们也尝试了神经元的组合。实际操作经验中,我们也认为是一组神经元的组合共同表征了一张图像。单个神经元就可以看作激活空间中的单个基础维度,目前也没发现证据证明它们之间有主次之分。

      作者们尝试了给神经元做加减法,比如把表示“黑白”的神经元加上一个“马赛克”神经元,优化结果就是同一种马赛克的黑白版本。这让人想起了Word2Vec中词嵌入的语义加减法,或者生成式模型中隐空间的加减法。

      联合优化两个神经元,可以得到这样的结果。

      谷歌的新CNN特征可视化方法,构造出一个华丽繁复的新世界

      谷歌的新CNN特征可视化方法,构造出一个华丽繁复的新世界

      也可以在两个神经元之间取插值,便于更好理解神经元间的互动。这也和生成式模型的隐空间插值相似。

      谷歌的新CNN特征可视化方法,构造出一个华丽繁复的新世界

      谷歌的新CNN特征可视化方法,构造出一个华丽繁复的新世界

      不过这些也仅仅是神经元间互动关系的一点点皮毛。实际上作者们也根本不知道如何在特征空间中选出有意义的方向,甚至都不知道到底有没有什么方向是带有具体的含义的。除了找到方向之外,不同反向之间如何互动也还存在疑问,比如刚才的差值图展示出了寥寥几个神经元之间的互动关系,但实际情况是往往有数百个神经元、数百个方向之间互相影响。

      5.6 特征可视化的实现过程

      如前文所说,作者们此次使用的优化方法的思路很简单,但想要真的产生符合人类观察习惯的图像就需要很多的技巧和尝试了。直接对图像进行优化可能会产生一种神经网络的光学幻觉 —— 人眼看来是一副全是噪声、带有看不出意义的高频图样的图像,但网络却会有强烈的响应。即便仔细调整学习率,还是会得到明显的噪声。(下图学习率0.05)

      谷歌的新CNN特征可视化方法,构造出一个华丽繁复的新世界

      这些图样就像是作弊图形,用现实生活中不存在的方式激活了神经元。如果优化的步骤足够多,最终得到的东西是神经元确实有响应,但人眼看来全都是高频图样的图像。这种图样似乎和对抗性样本的现象之间有紧密的关系。(雷锋网(公众号:雷锋网) AI 科技评论编译也有同感,关于对抗性样本的更早文章可以看这里

      作者们也不清楚这些高频图样的具体产生原因,他们猜想可能和带有步幅的卷积和最大池化操作有关系,两者都可以在梯度中产生高频率的图样。

      谷歌的新CNN特征可视化方法,构造出一个华丽繁复的新世界

      通过反向传播过程作者们发现,每次带有步幅的卷积或者最大池化都会在梯度维度中产生棋盘般的图样

      这些高频图样说明,虽然基于优化方法的可视化方法不再受限于真实样本,有着极高的自由性,它却也是一把双刃剑。如果不对图像做任何限制,最后得到的就是对抗性样本。这个现象确实很有意思,但是作者们为了达到可视化的目标,就需要想办法克服这个现象。

      5.7 不同规范化方案的对比

      在特征可视化的研究中,高频噪音一直以来都是主要的难点和重点攻关方向。如果想要得到有用的可视化结果,就需要通过某些先验知识、规范化或者添加限制来产生更自然的图像结构。

      实际上,如果看看特征可视化方面最著名的论文,它们最主要的观点之一通常都是使用某种规范化方法。不同的研究者们尝试了许多不同的方法。

      文章作者们根据对模型的规范化强度把所有这些方法看作一个连续的分布。在分布的一端,是完全不做规范化,得到的结果就是对抗性样本;在另一端则是在现有数据集中做搜索,那么会出现的问题在开头也就讲过了。在两者之间就有主要的三大类规范化方法可供选择。

      谷歌的新CNN特征可视化方法,构造出一个华丽繁复的新世界

      频率惩罚直接针对的就是高频噪音。它可以显式地惩罚相邻像素间出现的高变化,或者在每步图像优化之后增加模糊,隐式地惩罚了高频噪音。然而不幸的是,这些方法同时也会限制合理的高频特征,比如噪音周围的边缘。如果增加一个双边过滤器,把边缘保留下来的话可以得到一些改善。如下图。

      谷歌的新CNN特征可视化方法,构造出一个华丽繁复的新世界

      变换健壮性会尝试寻找那些经过小的变换以后仍然能让优化目标激活的样本。对于图像的例子来说,细微的一点点变化都可以起到明显的作用,尤其是配合使用一个更通用的高频规范器之后。具体来说,这就代表着可以随机对图像做抖动、宣传或者缩放,然后把它应用到优化步骤中。如下图。

      谷歌的新CNN特征可视化方法,构造出一个华丽繁复的新世界

      先验知识。作者们一开始使用的规范化方法都只用到了非常简单的启发式方法来保持样本的合理性。更自然的做法是从真实数据学出一个模型,让这个模型迫使生成的样本变得合理。如果有一个强力的模型,得到的效果就会跟搜索整个数据集类似。这种方法可以得到最真实的可视化结果,但是就很难判断结果中的哪些部分来自研究的模型本身的可视化,哪些部分来自后来学到的模型中的先验知识。

      有一类做法大家都很熟悉了,就是学习一个生成器,让它的输出位于现有数据样本的隐空间中,然后在这个隐空间中做优化。比如GAN或者VAE。也有个替代方案是学习一种先验知识,通过它控制概率梯度;这样就可以让先验知识和优化目标共同优化。为先验知识和类别的可能性做优化是,就同步形成了一个限制在这个特定类别数据下的生成式模型。

      5.8 预处理与参数化

      前面介绍的几种方法都降低了梯度中的高频成分,而不是直接去除可视化效果中的高频;它们仍然允许高频梯度形成,只不过随后去减弱它。

      有没有办法不让梯度产生高频呢?这里就有一个强大的梯度变换工具:优化中的“预处理”。可以把它看作同一个优化目标的最速下降法,但是要在这个空间的另一个参数化形式下进行,或者在另一种距离下进行。这会改变最快速的那个下降方向,以及改变每个方向中的优化速度有多快,但它并不会改变最小值。如果有许多局部极小值,它还可以拉伸、缩小它们的范围大小,改变优化过程会掉入哪些、不掉入哪些。最终的结果就是,如果用了正确的预处理方法,就可以让优化问题大大简化。

      那么带有这些好处的预处理器如何选择呢?首先很容易想到的就是让数据去相关以及白化的方法。对图像来说,这就意味着以Fourier变换做梯度下降,同时要缩放频率的大小这样它们可以都具有同样的能量。

      不同的距离衡量方法也会改变最速下降的方向。L2范数梯度就和L∞度量或者去相关空间下的方向很不一样。

      谷歌的新CNN特征可视化方法,构造出一个华丽繁复的新世界

      所有这些方向都是同一个优化目标下的可选下降方向,但是视觉上看来它们的区别非常大。可以看到在去相关空间中做优化能够减少高频成分的出现,用L∞则会增加高频。

      选用去相关的下降方向带来的可视化结果也很不一样。由于超参数的不同很难做客观的比较,但是得到的结果看起来要好很多,而且形成得也要快得多。这篇文章中的多数图片就都是用去相关空间的下降和变换健壮性方法一起生成的(除特殊标明的外)。

      谷歌的新CNN特征可视化方法,构造出一个华丽繁复的新世界

      谷歌的新CNN特征可视化方法,构造出一个华丽繁复的新世界

      谷歌的新CNN特征可视化方法,构造出一个华丽繁复的新世界

      那么,是不是不同的方法其实都能下降到同一个点上,是不是只不过正常的梯度下降慢一点、预处理方法仅仅加速了这个下降过程呢?还是说预处理方法其实也规范化(改变)了最终达到的局部极小值点?目前还很难说得清。一方面,梯度下降似乎能一直让优化过程进行下去,只要增加优化过程的步数 —— 它往往并没有真的收敛,只是在非常非常慢地移动。另一方面,如果关掉所有其它的规范化方法的话,预处理方法似乎也确实能减少高频图案的出现。

      5.9 结论

      文章作者们提出了一种新的方法创造令人眼前一亮的可视化结果,在呈现了丰富的可视化结果同时,也讨论了其中的重大难点和如何尝试解决它们。

      在尝试提高神经网络可解释性的漫漫旅途中,特征可视化是最有潜力、得到了最多研究的方向之一。不过单独来看,特征可视化也永远都无法带来完全让人满意的解释。作者们把它看作这个方向的基础研究之一,虽然现在还有许多未能解释的问题,但我们也共同希望在未来更多工具的帮助下,人们能够真正地理解深度学习系统。

      第六章 理解与可视化卷积神经网络

      [12.1 可视化卷积神经网络学习到的东西](https://blog.csdn.net/vvcrm01/article/details/82110877#12.1 可视化卷积神经网络学习到的东西)

      12.1.1可视化激活和第一层权重

      12.1.2 找到对神经元有最大激活的图像

      [12.1.3 用 t-SNE 嵌入代码](https://blog.csdn.net/vvcrm01/article/details/82110877#12.1.3 用 t-SNE 嵌入代码)

      [12.1.4 遮挡部分图像](https://blog.csdn.net/vvcrm01/article/details/82110877#12.1.4 遮挡部分图像)

      [12.1.5 可视化数据梯度及其他文献](https://blog.csdn.net/vvcrm01/article/details/82110877#12.1.5 可视化数据梯度及其他文献)

      [12.1.6 基于CNN代码重构原始图像](https://blog.csdn.net/vvcrm01/article/details/82110877#12.1.6 基于CNN代码重构原始图像)

      [12.1.7 保存了多少空间信息?](https://blog.csdn.net/vvcrm01/article/details/82110877#12.1.7 保存了多少空间信息?)

      [12.1.8 根据图像属性绘制性能](https://blog.csdn.net/vvcrm01/article/details/82110877#12.1.8 根据图像属性绘制性能)

      [12.2 玩弄 ConvNets](https://blog.csdn.net/vvcrm01/article/details/82110877#12.2 玩弄 ConvNets)

      [12.3 将ConvNets 的结果与人类标签比较](https://blog.csdn.net/vvcrm01/article/details/82110877#12.3 将ConvNets 的结果与人类标签比较)

      第七章 可视化工具

      https://blog.csdn.net/dcxhun3/article/details/77746550

      5.11.4 常见的网络可视化方法

      ​ Tensorflow,Pytorch等每一个主流的深度学习框架都提供了相对应的可视化模板,那有没有一种方法更加具有通用性呢?下面介绍常见的网络可视化方法:

      (1)Netron。

      Netron支持主流各种框架的模型结构可视化工作,github链接:https://github.com/lutzroeder/Netron 。

      (2)Netscope。

      Netscope在线可视化链接:http://ethereon.github.io/netscope/#/editor。

      (2)ConvNetDraw。

      ConvNetDraw的github链接:https://github.com/cbovar/ConvNetDraw。

      (3)Draw_convnet。

      Draw_convnet的github链接:https://github.com/gwding/draw_convnet。

      (4)PlotNeuralNet。

      PlotNeuralNet的github链接:https://github.com/HarisIqbal88/PlotNeuralNet。

      (5)NN-SVG。

      NN-SVG的github链接:https://github.com/zfrenchee/NN-SVG。

      (6)Python + Graphviz。

      针对节点较多的网络,用python编写一个简单的dot脚本生成工具(MakeNN),可以很方便的输入参数生成nn结构图。

      (7)Graphviz - dot。

      Graphviz的官方链接:https://www.graphviz.org/。

      (8)NetworkX。

      NetworkX的github链接:https://github.com/networkx。

      (9)DAFT。

      daft官网链接:http://daft-pgm.org/。

      第三章 可视化组件

      AlexNet进行了可视化

      介绍三种可视化方法

      卷积核输出的可视化

      卷积核输出的可视化(Visualizing intermediate convnet outputs (intermediate activations),即可视化卷积核经过激活之后的结果。能够看到图像经过卷积之后结果,帮助理解卷积核的作用

      卷积核的可视化

      卷积核的可视化(Visualizing convnets filters),帮助我们理解卷积核是如何感受图像的

      热度图可视化

      热度图可视化(Visualizing heatmaps of class activation in an image),通过热度图,了解图像分类问题中图像哪些部分起到了关键作用,同时可以定位图像中物体的位置。

      作者:芥末的无奈 来源:CSDN 原文:https://blog.csdn.net/weiwei9363/article/details/79112872 版权声明:本文为博主原创文章,转载请附上博文链接!

      第八章 可视化教程

      8.1 基于DeepStream的CNN的可视化理解

      https://blog.csdn.net/sparkexpert/article/details/74529094

      8.2 Tensorflow实现卷积特征的可视化

      简单卷积神经网络的tensorboard可视化*

      https://blog.csdn.net/happyhorizion/article/details/77894048

      https://blog.csdn.net/u014281392/article/details/74316028

      8.3 基于MatConvNet框架的CNN卷积层与特征图可视化

      https://blog.csdn.net/jsgaobiao/article/details/80361494

      程序下载链接:https://download.csdn.net/download/jsgaobiao/10422273 VGG-f模型链接:http://www.vlfeat.org/matconvnet/models/imagenet-vgg-f.mat

       【题目】 编程实现可视化卷积神经网络的特征图,并探究图像变换(平移,旋转,缩放等)对特征图的影响。选择AlexNet等经典CNN网络的Pre-trained模型,可视化每个卷积层的特征图(网络输入图片自行选择)。其中,第一层全部可视化,其余层选取部分特征图进行可视化。然后对图像进行变换,观察图像变换后特征图的变化。

       【方法概述】 本次实验使用了VGG-f作为预先加载的模型,通过MATLAB中的load方法将imagenet-vgg-f中的参数加载进程序。 imagenet-vgg-f是一个21层的卷积神经网络,其参数在ImageNet数据集上进行了训练。它的网络结构包括了5层卷积层、3层全连接层,输出的类别可达1000种。网络结构图太长了放在文章最后。

      实验中共有6个输入图像,分别是原图input.jpg以及对它进行平移、缩放、旋转、水平翻转、垂直翻转后的图像

      首先将输入图像进行归一化操作,也就是将图片resize到网络的标准输入大小224*224,并且将图片的每个像素与均值图片的每个像素相减,再输入网络。 接下来,可视化卷积核的时候,将网络第一层卷积核的参数net.layers{1}.weights{1}提取出来,并使用vl_imarraysc函数进行可视化。第一层卷积核的3个通道在可视化的过程中就被当作RGB三个通道。 对于feature map的可视化任务,需要先使用vl_simplenn将图片输入神经网络并获取其输出结果。我们需要可视化的是每个卷积层后经过ReLU的结果,每个输入图像对应5个特征图。

       【结果分析】 由于卷积核的参数是预训练得到的,与输入图片无关,所以只展现一幅图就够了。如下图所示,第一层卷积核学到了图片中一些基础性的特征,比如各种方向的边缘和角点。

      下面展示的是原始图片输入后,5个卷积层的可视化结果。需要说明的是,第二层之后的特征图数量较多,因此每层只选取了64个进行可视化。另外,特征图是单通道的灰度图片,为了可视化的效果更好,我将灰度值映射到了“蓝-黄”的颜色区间内,进行了伪彩色的处理,得到了如下的可视化结果。

      其中,第一层特征图的细节比较清晰和输入图片较为相似,提取出了输入图片的边缘(包括刺猬身上的刺)。第2、3、4层特征图的分辨率较低,已经难以看出输入图片的特征,但是可以发现有些特征图对背刺区域激活显著,有些特征图对刺猬的外轮廓、背景等区域激活显著。可以猜测,它们提取了图片中比边缘和角点更高层的语义信息。最后一层特征图中有少量对背刺区域激活显著,少量几乎没有被激活。可以猜测,刺猬的背刺特征是网络判断其类别的显著特征,因此被分类为刺猬的图片在最后一个特征层的背刺区域激活最为明显。

       【对比分析】 由于篇幅限制,这里只放置较小的略缩图,高清图片可以运行程序自行查看。

      我们先对比最清晰的第一层特征图的可视化结果。 可以看出除了缩放的图片以外,其他特征图都随着输入图片的变化而变化:平移的图片作为输入,特征图也产生了相对的平移;翻转、旋转都有类似的效果。只有缩放的输入图片并不影响特征图的表现,其原因应该是VGG-f采用固定大小的输入数据,因此不论图片是否经过缩放,在输入VGG-f之前都会被归一化为同样的大小,所以直观上看并不影响特征图的表现。但是由于分辨率的不同,经过resize之后的图片可能会有像素级别的细微差异,人眼不容易分辨出来。

      从另一方面来说,虽然特征图对于输入图片的变换产生了相同的变换,但是特征图中的激活区域并没有显著的变化。这说明VGG-f在图片分类的任务中,对输入图片的大小、旋转、翻转、平移等变化是不敏感的,并不会显著影响其分类结果的准确性。也说明了CNN网络具有一定程度的旋转/平移不变性。

      与第一层特征图类似,其他层的特征图也产生了类似的表现,即除了缩放的图片以外,其他作用于输入图片的变换均体现在了特征图上。由于篇幅所限,这里不再单独放出。运行程序即可得到结果。

      附上程序下载链接:https://download.csdn.net/download/jsgaobiao/10422273

      [VGG-f网络结构图]

      作者:jsgaobiao 来源:CSDN 原文:https://blog.csdn.net/jsgaobiao/article/details/80361494 版权声明:本文为博主原创文章,转载请附上博文链接!

      8.4 Caffe 特征图可视化

      https://blog.csdn.net/u012938704/article/details/52767695

      8.5 基于Keras的CNN可视化

      https://blog.csdn.net/weiwei9363/article/details/79112872

      1. deep-learning-with-python-notebooks
      2. 5.4-visualizing-what-convnets-learn.ipynb

      In [1]:

      import keras
      keras.__version__
      
      Using TensorFlow backend.
      

      Out[1]:

      '2.0.8'
      

      Visualizing what convnets learn

      This notebook contains the code sample found in Chapter 5, Section 4 of Deep Learning with Python. Note that the original text features far more content, in particular further explanations and figures: in this notebook, you will only find source code and related comments.


      It is often said that deep learning models are "black boxes", learning representations that are difficult to extract and present in a human-readable form. While this is partially true for certain types of deep learning models, it is definitely not true for convnets. The representations learned by convnets are highly amenable to visualization, in large part because they are representations of visual concepts. Since 2013, a wide array of techniques have been developed for visualizing and interpreting these representations. We won't survey all of them, but we will cover three of the most accessible and useful ones:

      • Visualizing intermediate convnet outputs ("intermediate activations"). This is useful to understand how successive convnet layers transform their input, and to get a first idea of the meaning of individual convnet filters.
      • Visualizing convnets filters. This is useful to understand precisely what visual pattern or concept each filter in a convnet is receptive to.
      • Visualizing heatmaps of class activation in an image. This is useful to understand which part of an image where identified as belonging to a given class, and thus allows to localize objects in images.

      For the first method -- activation visualization -- we will use the small convnet that we trained from scratch on the cat vs. dog classification problem two sections ago. For the next two methods, we will use the VGG16 model that we introduced in the previous section.

      Visualizing intermediate activations

      Visualizing intermediate activations consists in displaying the feature maps that are output by various convolution and pooling layers in a network, given a certain input (the output of a layer is often called its "activation", the output of the activation function). This gives a view into how an input is decomposed unto the different filters learned by the network. These feature maps we want to visualize have 3 dimensions: width, height, and depth (channels). Each channel encodes relatively independent features, so the proper way to visualize these feature maps is by independently plotting the contents of every channel, as a 2D image. Let's start by loading the model that we saved in section 5.2:

      In [2]:

      from keras.models import load_model
      
      model = load_model('cats_and_dogs_small_2.h5')
      model.summary()  # As a reminder.
      
      _________________________________________________________________
      Layer (type)                 Output Shape              Param #   
      =================================================================
      conv2d_5 (Conv2D)            (None, 148, 148, 32)      896       
      _________________________________________________________________
      max_pooling2d_5 (MaxPooling2 (None, 74, 74, 32)        0         
      _________________________________________________________________
      conv2d_6 (Conv2D)            (None, 72, 72, 64)        18496     
      _________________________________________________________________
      max_pooling2d_6 (MaxPooling2 (None, 36, 36, 64)        0         
      _________________________________________________________________
      conv2d_7 (Conv2D)            (None, 34, 34, 128)       73856     
      _________________________________________________________________
      max_pooling2d_7 (MaxPooling2 (None, 17, 17, 128)       0         
      _________________________________________________________________
      conv2d_8 (Conv2D)            (None, 15, 15, 128)       147584    
      _________________________________________________________________
      max_pooling2d_8 (MaxPooling2 (None, 7, 7, 128)         0         
      _________________________________________________________________
      flatten_2 (Flatten)          (None, 6272)              0         
      _________________________________________________________________
      dropout_1 (Dropout)          (None, 6272)              0         
      _________________________________________________________________
      dense_3 (Dense)              (None, 512)               3211776   
      _________________________________________________________________
      dense_4 (Dense)              (None, 1)                 513       
      =================================================================
      Total params: 3,453,121
      Trainable params: 3,453,121
      Non-trainable params: 0
      _________________________________________________________________
      

      This will be the input image we will use -- a picture of a cat, not part of images that the network was trained on:

      In [3]:

      img_path = '/Users/fchollet/Downloads/cats_and_dogs_small/test/cats/cat.1700.jpg'
      
      # We preprocess the image into a 4D tensor
      from keras.preprocessing import image
      import numpy as np
      
      img = image.load_img(img_path, target_size=(150, 150))
      img_tensor = image.img_to_array(img)
      img_tensor = np.expand_dims(img_tensor, axis=0)
      # Remember that the model was trained on inputs
      # that were preprocessed in the following way:
      img_tensor /= 255.
      
      # Its shape is (1, 150, 150, 3)
      print(img_tensor.shape)
      
      (1, 150, 150, 3)
      

      Let's display our picture:

      In [4]:

      import matplotlib.pyplot as plt
      
      plt.imshow(img_tensor[0])
      plt.show()
      

      img

      In order to extract the feature maps we want to look at, we will create a Keras model that takes batches of images as input, and outputs the activations of all convolution and pooling layers. To do this, we will use the Keras class Model. A Model is instantiated using two arguments: an input tensor (or list of input tensors), and an output tensor (or list of output tensors). The resulting class is a Keras model, just like the Sequential models that you are familiar with, mapping the specified inputs to the specified outputs. What sets the Model class apart is that it allows for models with multiple outputs, unlike Sequential. For more information about the Model class, see Chapter 7, Section 1.

      In [5]:

      from keras import models
      
      # Extracts the outputs of the top 8 layers:
      layer_outputs = [layer.output for layer in model.layers[:8]]
      # Creates a model that will return these outputs, given the model input:
      activation_model = models.Model(inputs=model.input, outputs=layer_outputs)
      

      When fed an image input, this model returns the values of the layer activations in the original model. This is the first time you encounter a multi-output model in this book: until now the models you have seen only had exactly one input and one output. In the general case, a model could have any number of inputs and outputs. This one has one input and 8 outputs, one output per layer activation.

      In [6]:

      # This will return a list of 5 Numpy arrays:
      # one array per layer activation
      activations = activation_model.predict(img_tensor)
      

      For instance, this is the activation of the first convolution layer for our cat image input:

      In [7]:

      first_layer_activation = activations[0]
      print(first_layer_activation.shape)
      
      (1, 148, 148, 32)
      

      It's a 148x148 feature map with 32 channels. Let's try visualizing the 3rd channel:

      In [8]:

      import matplotlib.pyplot as plt
      
      plt.matshow(first_layer_activation[0, :, :, 3], cmap='viridis')
      plt.show()
      

      img

      This channel appears to encode a diagonal edge detector. Let's try the 30th channel -- but note that your own channels may vary, since the specific filters learned by convolution layers are not deterministic.

      In [9]:

      plt.matshow(first_layer_activation[0, :, :, 30], cmap='viridis')
      plt.show()
      

      img

      This one looks like a "bright green dot" detector, useful to encode cat eyes. At this point, let's go and plot a complete visualization of all the activations in the network. We'll extract and plot every channel in each of our 8 activation maps, and we will stack the results in one big image tensor, with channels stacked side by side.

      In [10]:

      import keras
      
      # These are the names of the layers, so can have them as part of our plot
      layer_names = []
      for layer in model.layers[:8]:
          layer_names.append(layer.name)
      
      images_per_row = 16
      
      # Now let's display our feature maps
      for layer_name, layer_activation in zip(layer_names, activations):
          # This is the number of features in the feature map
          n_features = layer_activation.shape[-1]
      
          # The feature map has shape (1, size, size, n_features)
          size = layer_activation.shape[1]
      
          # We will tile the activation channels in this matrix
          n_cols = n_features // images_per_row
          display_grid = np.zeros((size * n_cols, images_per_row * size))
      
          # We'll tile each filter into this big horizontal grid
          for col in range(n_cols):
              for row in range(images_per_row):
                  channel_image = layer_activation[0,
                                                   :, :,
                                                   col * images_per_row + row]
                  # Post-process the feature to make it visually palatable
                  channel_image -= channel_image.mean()
                  channel_image /= channel_image.std()
                  channel_image *= 64
                  channel_image += 128
                  channel_image = np.clip(channel_image, 0, 255).astype('uint8')
                  display_grid[col * size : (col + 1) * size,
                               row * size : (row + 1) * size] = channel_image
      
          # Display the grid
          scale = 1. / size
          plt.figure(figsize=(scale * display_grid.shape[1],
                              scale * display_grid.shape[0]))
          plt.title(layer_name)
          plt.grid(False)
          plt.imshow(display_grid, aspect='auto', cmap='viridis')
          
      plt.show()
      

      视频识别怎样理解?其实,我们可以将其可视化!

      综述:

      本文主要描述的是为视频识别设计的深层网络的显著图(saliency maps)。从早前的论文《卷积神经网络的可视化》(European conference on computer vision. Springer, Cham, 2014)、《可识别定位的深度特征学习》(In CVPR, 2016),以及《Grad-cam:何出此言?基于梯度定位的深度网络视觉解释》(arXiv preprint arXiv:1610.02391 (2016). In ICCV 2017)可以看出,显著图能够有助于可视化模型之所以产生给定预测的原因,发现数据中的假象,并指向一个更好的架构。

      什么是可解释性?

      http://www.sohu.com/a/215753405_465975

      我们应该把可解释性看作人类模仿性(human simulatability)。如果人类可以在合适时间内采用输入数据和模型参数,经过每个计算步,作出预测,则该模型具备模仿性(Lipton 2016)。

      这是一个严格但权威的定义。以医院生态系统为例:给定一个模仿性模型,医生可以轻松检查模型的每一步是否违背其专业知识,甚至推断数据中的公平性和系统偏差等。这可以帮助从业者利用正向反馈循环改进模型。

      树正则化 --斯坦福完全可解释深度神经网络:你需要用决策树搞点事

      其论文《Beyond Sparsity: Tree Regularization of Deep Models for Interpretability》已被 AAAI 2018 接收。

      很幸运,学界人士也提出了很多对深度学习的理解。以下是几个近期论文示例:

      http://www.sohu.com/a/215753405_465975

      • Grad-Cam(Selvaraju et. al. 2017):使用最后卷积层的梯度生成热力图,突出显示输入图像中的重要像素用于分类。
      • LIME(Ribeiro et. al. 2016):使用稀疏线性模型(可轻松识别重要特征)逼近 DNN 的预测。
      • 特征可视化(Olah 2017):对于带有随机噪声的图像,优化像素来激活训练的 DNN 中的特定神经元,进而可视化神经元学到的内容。
      • Loss Landscape(Li et. al. 2017):可视化 DNN 尝试最小化的非凸损失函数,查看架构/参数如何影响损失情况。

      参考资料

      参考文献

      ....

      未完待续!

       
    • 相关阅读:
      HTML基础 meta refresh 网页定时刷新
      HTML基础 meta name author 添加网页作者的信息
      HTML基础 mate refresh 5秒钟后,页面自动跳转
      HTML基础 marquee div块实现循环跑马灯的效果
      微服务jar包启动脚本
      怎么实现将word中的公式导入(或粘贴)到在线编辑中
      怎么实现将word中的公式导入(或粘贴)到网页编辑中
      Nginx实现浏览器端大文件分块上传
      javascript实现浏览器端大文件分块上传
      js实现浏览器端大文件分块上传
    • 原文地址:https://www.cnblogs.com/cx2016/p/12004025.html
    Copyright © 2020-2023  润新知