本文试图对CNN到底做了什么,给出一些分析解释。通过观察卷积层的输出构成的灰度图,试图寻找这个卷积在物理上有什么作用。
训练数据是一些验证码图片,用了四个卷积层和两个全连接层的模型,在训练集上训练到98%的准确率,验证集80%。具体代码可参考我前面的这篇博文《CNN识别图形验证码》。图片似乎只有*才能看到,不好意思。
可视化结果分别从以下几个角度做分析:
1 看每个卷积层经过激活函数(relu)后的输出图像
第一个卷积层的结果(相对比较容易懂):
为了方便人眼观察,对每一幅图的像素值都做了一个放大,做法是除以这幅图的最大像素值然后乘以255。灰度图中越亮的部分,就说明原来的值越大。注意,这样的做法导致,不同的图中比较像素点的相对亮度是没有意义的。
原图:
可以观察,不同的filter可以提取到不同的特征:
比如这个filter可以把所有要识别的目标提取出来,过滤掉背景颜色和噪音。
这两个filter把所有非背景部分提出来,但一个关注上半部分,一个关注下半部分。
这个filter对这幅图片“不感冒”。
这个filter只提取噪音。
这两个filter,一个分别只提取右斜的笔画,一个只提取左斜的笔画。
这个filter把轮廓线提取出来。
conv2(开始不那么好解释了)
分别关注字符的左边部分和右边部分。
提取出背景部分,提取出的背景并不完全一样。
注意最右边,很亮的一条,本来应该是背景的,却在提取内容的filter中给了很高的关注。
最下边,黑色的一条,本来应该是背景的,却在提取背景的filter中,没有被提取出来。
类似的奇怪现象:
提取轮廓。
分别关注上半部分和下半部分。
提取出需要识别的字符部分
总结,第一层的filter不提取背景,而第二层开始提取,有趣的现象。
conv3
也会提取背景:
内容,之前能看清轮廓的字符,现在都缩小到了只有一个小光点:
出现只提取单个或几个,但不是全部字符的filter,但不清楚提取的到底是什么特征:
上一层中,边界上的奇怪现象,依然存在:
conv4
第四层基本上是第三层的延续,但提取的特征更加抽象:
2 比较不同的输入,每个filter的结果
能理解的filter,比如做边界提取,都可以看出对不同的输入也做的是同样的事情。到后面层,filter提取出的特征都成了光点之后,就不是很明白了。不同输入提取结果不一样。
3 对预测错误的图片进行分析
预测结果:U T U o v i
把L看成了U
从第一层提取出的特征可以看出,特征就提取错了,把L的一横当做噪音给隐去了,又把斜着的那条噪音当做了字符部分。(我觉得提取出来的更像V而不是U)
但这个提取噪音的filter,也确实把斜着的那条噪音提取出来了,不知道为什么同时分给了内容和噪音两个部分。
预测结果: T l F X C u
把r看成了T
预测结果:B l W n P i
实际结果:B k W n P L ,人也很难看出来。
机器是怎么看呢?
提取出来的内容,其实效果也很差。
但是,看这张背景图,效果就好很多了。
预测结果:e I D n w w
实际结果:e j D k w m
错了两个,特征提取效果确实很差,没有训练好
4 用随机初始化的模型得到的结果
基本什么都没学到,并没有focus到需要的地方。
值得注意的是,随机初始化也可以得到这种去掉噪音的图片(左),可以和训练好的模型类似的图片(右)对比。
不过总体而言,随机初始化的结果,和训练好的模型的结果,相差还是非常大的,说明训练过的模型确实学到了东西。
5 跑网站(江苏)上爬取下来的图片,检查用分布不同的数据训练的模型,是否也有好的效果
原图:
可以看出除了和训练数据噪音类型不同,还是有很多相同之处。
虽然效果不是特别好,但还是能看出提取了一些特征。
也有效果很差的。
总的来说,在新的没见过的类型的数据集上,filter提取特征的效果,比在和训练集分布相同的数据集上,效果要差很多。不过比随机初始化还是好很多的。因此考虑说,对于一个分布不完全一致的数据集,并不一定要从头开始训练,而是可以利用在类似数据集上训练好的模型参数,做初始化。这样的预训练,也许可以减少所需要的打好标签的新数据的数目。
想了解更详细的内容,可以找我要数据。ps,karpathy做的这个CNN可视化演示很漂亮
http://cs.stanford.edu/people/karpathy/convnetjs/demo/cifar10.html,值得参考。