7 Matching Annotations
  1. Sep 2018
    1. 卷积层(strides!=(1,1))输出形状推算

      \(width_{output} = \frac{width_{img} - width_{kernel} + width_{padding}}{width_{strides}} + 1\)

    2. 注意 keras 处理 CNN 的形状

      在 keras 中 fit 给 CNN 的数据集的形状必须是:

      theano: (-1, channel, height, width)

      tensorflow: (-1, height, width, channel)

      如果不是必须reshape到这个形状,第一层卷积层的声明一般为:

      model.add( Conv2D(kernelNum, (kernelHeight, kernelWidth), input_shape=(dataPointChannel, dataPointHeight, dataPointWidth), data_format='channels_first'))

      切记,切记

    3. 什么样的情形可以使用 CNN

      记忆: 小抠样

      记忆:small, regions, subsampling

      • 某些pattern远小于整张图片

      这个是说 filter 一般采取小于整张图片的形状

      • 同样的pattern出现在图片的不同位置

      这个是说 filter 会逐行逐列移动扫描整张图片

      • subsampling 没有什么影响

      这个是说 pooling 是切割图片为多块,每块只取一格(1 pixel)

      关于 subsampling

      这里的意思是说,对于 featuremap 如果池化层 size = 2*2 , maxpooling 会只去最大的一个值(averagePooling 会取平均,但也只是一个值)而忽略其他值。这件事情的物理意义是:featuremap 是由 filter 扫描整张图片得到的,某个pattern(pattern较大,stride较小时)可能被多次扫描到并体现在 featuremap 中类似于 \([0,1,2,5,2,1,0]\),直接丢弃这种长尾效应对判定该某个pattern的位置以及匹配程度是没有任何影响的,他完全可以被最大的那个 5 hold住。

      长尾效应的取舍

      围棋(连续型pattern) vs. 图像识别(离散型pattern)

      图像识别就是这种最大值可以完全hold位置以及匹配程度信息的任务。可是对于其他任务比如围棋,他的核心任务虽然也是识别某个模式,但长尾效应尾部是有作用的。

      在图像识别中被识别的模式是独立的或者叫离散的 --- 一个圆的是形状是眼睛,3/4个圆就不是眼睛了。在围棋中 \([0,1,2,5,2,1,0]\) 那些\(0,1,2\)对判断当前棋子所处的状态是有影响的,甚至他可能更重视长尾效应中的

      结论

      所以,对于是否使用 maxpooling 层要根据你的具体任务来做具体对待:

      • 当任务识别的pattern‘’比较离散”---目标仅仅是寻找和定位pattern,别无其他 适合加上 maxpooling,让模型更专注,也让模型参数更少。

      • 当任务识别的pattern“比较连续”---长尾效应之尾会影响任务目标 最好不加 maxpooling,这样模型可以保存更多现场信息,让结果更精确。

      像围棋这种任务,显然就不能使用纯粹的CNN(包含 maxpooling),所以 alpha-go 中没有使用 maxpooling.

    4. 从可视化某个filter or neuron的激活度到deepdream

      google 的 deepdream 的核心思想就是借用最大化某个filter or neuron.不同的是 deepdream 不是单纯“最大化某filter or neuron的输出”,而是针对某让该层神经元原本输出大的更大,原本输出小的更小。,亦即,

      CNN of deepdream exaggerates what it sees

      assume output of k-th hidden layer is

      \(output_k = [3.9, -1.5, 2.3, ...]\)

      正的扩大,负的缩小

      \([3.9\Uparrow, -1.5\Downarrow, 2.3\Uparrow, ...]\)

      成为

      \(output_k' = [10, -5, 8, ...]\)

      以其为目标,找到 \(x^\star\)

      \(x^\star = argmin_x(output_k - output_k')\)

      从 deepdream 到 deepstyle

      之前都是只考虑了输出这件事,不论是 filter or neuron 还是某一层 hidden layer 我们关注的都是输出。现在如果我们把filter 和 filter 之间的 correlation 纳入考虑范畴。就可以实现风格迁移,这就是 deepstyle 的核心思想。

      1. 一个训练好的 CNN,输入某张图片,获取某一层 hidden layer 的输出(取内容);

      2. 一个训练好的 CNN,输入某张图片,获取某一层 hidden layer 的correlation(取风格);

      目标是:找到一个 \(x\),他经过CNN得到的相同层 hidden layer 的内容像步骤1中的;风格像步骤2中的。

    5. 如何展示某个 filter 学到了什么

      也就是什么样的图片可以让 filter 被激活(度高)

      定义: 核的激活度

      Degree of the activation of k-th filter, 核激活度表示这个 filter 被激活的程度, 他等于该filter输出的 featuremap 矩阵的所有元素的和(一个 filter 只会生成dim=1的featuremap)。

      \(k-th\ filter\ is\ a\ matrix : A^k\)

      assum \(A^k\) is a 11 * 11 matrix

      \(element\ of\ A^k: a_{ij}^k\)

      \(degree\ of\ activation\ of\ k-th\ filter: a^k = \sum_{i=1}^{11}\sum_{j=1}^{11}a_{ij}^k\)

      我们的目标是:找一张img,他可以让这个filter被激活度最大

      \(img^\star = argmax_{img}a^k\) , 亦即

      \(x^\star = argmax_{x}a^k\)

      我们使用 Gradient Ascent 去更新 \(x\) 使得某个filter的被激活度 \(a^k\) 最大。

      如何展示某个 neuron 学到了什么

      也就是什么样的屠屏可以让 neuron 被激活。

      定义:神经元的激活度

      某个神经元的激活度,很简单,就是这个神经元的输出。

      第 j 个神经元的输出记做 \(a^j\)

      我们的目标是: 找一张img, 他可以让这个neuron的输出最大

      \(img^\star = argmax_{img}a^j\) , 亦即

      \(x^\star = argmax_{x}a^j\)

      同上,也使用 Grandient Ascent.

      如何展示某个输出层 neuron 学到了什么

      其他同上

      \(img^\star = argmax_{img}a^j\) , 亦即

      \(x^\star = argmax_{x}y^j\)

      由于是输出层神经元,如果我们在做手写数字识别mnist的话,那么输出层神经元应该有10个(对应数字 0~9),我们是否可以据此产生图片了?类似生成模型。

      但结果并不如人意料,机器学出的东西与人类理解的东西有非常大的不同。我们确实可以通过这种GradientAscent的方法找到10张图片,他们也确实可以被模型正确分类到10个类别中,但这10张图片却无法被人类识别。

      话腐朽为‘数字’

      但我们依然可以对这些数字做一些处理(对 \(x^\start\) 做一些限制 --- 加一些 constraints),让他看起来像是数字:

      \(x^\star = argmax_{x}y^j\)

      change to:

      \(x^\star = argmax_{x}(y^i - \sum_{i,j}|x_{ij}|)\)

      类比 L1-regularization of GD on w:

      \(||\Theta||_1 = |w_1| + |w_2| + ...... + |w_N|\)

      \(L^{'}(\Theta) = L(\Theta) + \lambda ||\Theta||_1\)

      \(w^\star = argmin_wL'(\Theta))\)

      \(w^\star = argmin_{w}(L + \sum_{i=1}^{dim}|w_{i}|)\)

      加上这个限制的意思是,人类可以识别的数字图片(灰度图)应该是大部分为0,小部分为正,并且为正的部分应该相连。

      我们给原始的 \(argmax\) 公式加入 \(L1\) 正则项,让这个 x 可以尽量的稀疏(这是 L1 的特点),也就是大部分 x 的元素是 0,少量为1.

    6. keras 中卷积层的形状问题

      model.add( Convolution2D(25, 3, 3, input_shape=(1,28,28)) )
      model.add( MaxPooling2D((2,2)) )
      

      我们平时表示RGB彩图时,习惯将 通道 维度放在最后: (高,宽,通),opencv/pil/numpy/scikit 处理图片都是采用这种方式,但在 tensorflow/keras 中使用的是 (通,高,宽) 的表达方式。所以:

      Convolution2D(25,3,3, input_shape=(1,28,28))

      1. 表示卷积层有 25size=3*3 的 filter
      2. 输入图片是灰度图像(channel_dim=1), 图片 size=28*28

      对比 Dense Layer:

      Dense(input_shape=(1,28,28), units=800, activation='relu')

      可以看出,

      卷积层只是说明了本层权重的一些信息(filter就是权重) ,而神经元数目则交给系统自动推算; 全连接层则直接指明了本层神经元的数目

      卷积层和池化层形状推算

      Convolution2D(25,3,3, input_shape=(1,28,28))

      会输出一个形状为 (25, (28-3+1), (28-3+1)) 的 feature map。

      卷积层输出形状推算公式为:

      • i --- 本层
      • i-1 --- 前一层

      \(Convol:\) \(feature \ map \ size =(filterNumber_i, imgHeight_{i-1} - filterHeight_i + 1, imgWidth_{i-1} - filterWidth_i + 1)\)

      MaxPooling2D((2,2))

      会输出一个形状为 (25, 13, 13) 的 feature map.

      池化层输出形状推算公式为:

      • i --- 本层
      • i-1 --- 前一层

      \(Pooling:\) \(feature\ map\ size= (filterNumber_{i-1}, imgHeight_{i-1}//poolHeight_i, imgWidth_{i-1} // poolWidth_i)\)

      // 的意思是 celing division, 5//2=2

      卷积层和池化层参数量推算

      卷积层参数量推算公式:

      • i --- 本层
      • i-1 --- 前一层

      \(Convol_{paraNum}=filterNumber_{i-1} * filterNumber_i * filterHeight_i * filterWidth_i\)

      model.add(Convolution2D(25,3,3,input_shape=(1,28,28)))
      model.add(MaxPooling2D((2,2)))
      model.add(Convolution2D(50,3,3))
      

      第一个卷积层的总参数量为: 1 25 3 * 3

      第二个卷积层的总参数量为: 25 50 3 * 3

    1. @mingrutar - Correction: config = tf.ConfigProto() config.gpu_options.allow_growth = True session = tf.Session(config=config)

      当运行 keras 进行模型训练时,如果遇到以下错误:

      failed to create cublas handle: CUBLAS_STATUS_ALLOC_FAILED

      可以添加这样的语句,如此之后可以正常运行了。