深度学习中的数学与技巧(1):BN之利用随机前馈神经网络生成图像观察网络复杂度
2016-10-19 15:28
337 查看
一、前言
当然,要近似出来的函数的复杂度肯定不能超过神经网络的表达能力,不然就会产生欠拟合的现象。而一个网络能承载的函数复杂度通常与隐层节点个数和深度有关。
本篇文章通过一种可视化的方法,来直观地表示出一个神经网络得表达能力。
二、算法
值得注意的是,神经网络所拟合的函数,是关于输入的连续函数。如果输入是图像的2维坐标,输出是3维的RGB颜色的话,那颜色就是坐标的连续函数,这一点是图像是否美观的一个很重要的标准。如果我们随机生成神经网络的权重,通过生成的图像的复杂程度,就能够大致看出一个网络能够表达出多么复杂的函数。以下是生成图像的代码(基于DeepLearnToolBox,地址:https://github.com/happynear/DeepLearnToolbox):
layers = randi(10,1,10)+10;%隐层节点数,从[10 20]随机采样 nn = nnsetup([2 layers 3]);%构建网络 nn.activation_function = 'sigm';%隐层激活函数 nn.output = 'sigm';%输出层激活函数 nn.useBatchNormalization = 0;%是否使用Batch Normalization output_h = 600;%高 output_w = 800;%宽 [I,J] = ind2sub([output_h,output_w],(1:output_h*output_w)');%得到坐标 I = (I - output_h / 2) / output_h * 2;%归一化一下 J = (J - output_w / 2) / output_w * 2; nn = nnff(nn,[I J],zeros(size(I,1),3));%前馈神经网络 output = nn.a{length(nn.a)}; output = zscore(output);%做一下归一化,如果输出层激活函数为sigm,此步可省略。 output = reshape(output,[output_h,output_w,3]); imshow(uint8(output*100+128));%显示图像这里有三个地方可以设置,隐层节点数,神经网络中使用的激活函数,是否采用Batch Normalization。关于Batch Normalization,请参考我之前的一篇博客(链接)
这里加入Batch Normalization是基于如下考虑:由于我们并不是使用一个训练好的神经网络,即使对输入做了归一化,这个网络的权重可能还是不适合我们使用的这种输入形式,不仅是梯度会产生弥散现象,前馈神经网络的中也会有类似的现象发生,导致网络过早饱和。在每层都做一次归一化,可以最大程度上减小该现象的发生。
三、结果
ReLU+Batch Normalization:
ReLU,无Batch Normalization:
Sigmoid+Batch Normalization:
Sigmoid,无Batch Normalization:
以上图像均为10个隐层的神经网络生成,不同层数生成的图像请读者自行运行代码并观察。
可以看到:
1、ReLU+Batch Normalization所表达的函数最为复杂。
2、Sigmoid+Batch Normalization生成的图像有较多的相同颜色的区域,相对来说不如ReLU的表达能力强,有些甚至不如ReLU无BN条件下生成的图像复杂。
3、使用Sigmoid函数而不采用Batch Normalization算法时,函数图像都较为简单,通过观察每层的输出可以看到,最后几层的节点响应值几乎相等,此时网络实际上已经退化成一个简单的无隐层网络。
生成的图像可以通过以下链接下载:
http://pan.baidu.com/s/1hqtkoug
四、后记
由于隔壁教研室的老师办了个深度学习的Call for Paper,所以我又把这个博客拿出来想做更深入的研究。我之前在想,如果继续把Leaky Relu、MaxOut等结构拿来跑一下,然后再把这个扩展一下,变成CNN的形式(这个算法可以看作是一个2channel的线性图像,经过多个1x1conv之后,输出3channel的图像),把VGG、Inception、NIN等结构拿来跑跑,妥妥的是一篇好文章啊。。 然而在码了一堆代码之后,发现了一个重大bug,我在Batch Normalization层中,只考虑了scale的影响,而忘记了另一个关键因素:shift,这一项其实对网络所表达的函数具有更大影响。
请注意到上方Sigmoid+Batch Normalization生成的图像中,所有的线条似乎都指向了图像的中点。这是因为如果设置shift=0的话,由于Sigmoid关于(0,0.5)奇对称,所以在BN之后,所表达的函数必定为奇函数。多个奇函数的嵌套可能是奇函数也可能是偶函数,但都具备了某种对称性,大大限制了神经网络的发挥。所以shift也必须进行赋值来打破这种对称性。
在对shift进行随机赋值之后,Sigmoid+BN生成的图像就变成了这个样子(隐藏层数5):
从这张图上我们已经很难说它和ReLU生成的图像的复杂度有多大的区别了,因此这个方法仅仅只能生成好看的图像而已,然而这并没有什么卵用。
进一步分析,实际上在原图中有大量的复杂图像的可能性都被收缩到中间那一个小点中了,比如把shift的随机范围调小一点,就会生成中间很复杂,而周围仍呈放射状的图形(隐藏层数8):
相关文章推荐
- 利用随机前馈神经网络生成图像观察网络复杂度
- 【深度学习:CNN】利用随机前馈神经网络生成图像观察网络复杂度
- 深度学习-CAFFE利用CIFAR10网络模型训练自己的图像数据获得模型-2生成图像库的均值文件
- 随机生成10个100以内的整数,把数据从小到大排序,而且算法复杂度只能是1(利用数组的索引也可...
- 深度学习-CAFFE利用CIFAR10网络模型训练自己的图像数据获得模型-4应用生成模型进行预测
- 利用Math.random做背景图像随机切换
- 优捷信达与瑞士科学家探讨 利用数学算法挖掘网络谣言源头
- 利用PHP应用图像处理生成验证码
- 一个非常好用的数学函数图像生成工具
- 利用随机类生成数组,并用冒泡排序以及选择排序对不同数组的元素进行从小到大的排序
- 图像处理Matlab(二)——生成随机点
- 利用Math.random做背景图像随机切换【前端开发技能必备系列】
- 二分法的应用----------利用随机类生成数组,并用二分法对数组的元素进行查找以及插入操作
- Python&OpenCV - 随机生成图像 与 图像的转维(reshape)
- 验证码无缓存随机生成,利用session随时验证。
- 利用ASP.NET一般处理程序动态生成Web图像(转)
- 两种方法利用Java生成唯一ID,取当前时间与字母随机组合,并发少的情况足以胜任
- ASP.NET技巧:利用模版生成html页
- CodeSmith实用技巧(五):利用继承生成可变化的代码
- [网络收集]读取XML 利用TreeView控件动态生成无限级树