前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >到底是什么特征影响着CNN的性能?

到底是什么特征影响着CNN的性能?

作者头像
AI科技大本营
发布2019-05-06 10:44:16
5450
发布2019-05-06 10:44:16
举报

作者 | 刘畅

编辑 | Jane 出品 | AI科技大本营(ID:rgznai100)

开门见山。最近阅读了一篇论文,加上看了一些之前的工作。记录一下,CNN 到底学到了什么东西,或者换句话讲。到底是什么样的特征在影响着CNN 的性能?

先放论文: IMAGENET-TRAINED CNNS ARE BIASED TOWARDS TEXTURE; INCREASING SHAPE BIAS IMPROVES ACCURACY AND ROBUSTNESS 论文地址: https://openreview.net/pdf?id=Bygh9j09KX

JeremyRifkin 在书《The end of Work》中写道,“时至今日,当科学家们探讨人工智能时,他们通常是在讲一门能执行人们所希望机器表现的智能艺术”。这是我比较喜欢的关于人工智能的定义。因为它避免了大谈特谈如今的人工智能技术离真正的智能化有多远。而是享受当下。不过,作为一名研究人员,我觉得揭开大脑的运作原理和创造真正的智能机器是非常重要的。目前深度学习主要做的研究是关于从数据中学到规则并将其自动化的一个过程。这已经带来了非常多的好处,举一个简单的例子。在医学领域引入深度学习技术,可以将许多诊断过程全自动化,因此可以让贫穷地区或国家的人们享受到顶级的治疗。

开篇完毕,现在进入正题。尽管深度学习技术的到来给人们的生活带来了更多的便利。但是神经网络看待和解释世界的方式仍然是一个黑盒子。因此我们需要尝试更好的理解它,以便我们对深度学习网络做出进一步的改进,以及尝试去解释某些深度学习行为。有两种主要的方法可以尝试理解神经网络。一种是在数据集中查找导致特征图有高激活响应值的图片,另一种是在随机的一张图片中,通过优化像素值来生成模式。接下来,通过一些例子来展示一下,CNN 到底学到了什么?

特征可视化

这本书《Deep Learning with Python》里面讲了如何生成模式。包括滤波器是如何响应模式(纹理)等。接下来我们先观察一下这些模式。以 VGG16 为例。

第7层卷积(64,128)

滤波器12,16,86,110(从左到右,从上到下)

第14层卷积(128,256)

滤波器1, 6,31,32,54, 77(从左到右,从上到下)

第20层卷积(256,256)

滤波器3,34,39,55,62,105(从左到右,从上到下)

第30层卷积(512,512)

滤波器54,62,67,92,123,141(从左到右,从上到下)

第40层卷积(512,512)——网络顶部

256,261,265,277,286,462(从左到右,从上到下)

这些得到的中间结果看着非常漂亮。方法就是在网络中最大化某个激活值就可以得到这些结果。看一下第 40 层的几张图。已经有了明显的形状。比如羽毛、铁链等。接下来我们分析一下这些结果。

模式识别

我们先从下面这张图片开始吧。这张图片看着像是拱门。于是去数据集里面找来了一张拱门的图片,也就是右图。

接下来我们来检验一下,是不是由这张图来确定的图片的分类。首先记住,这张图是最后一层的第 286 个滤波器。如何检验呢?我们只需要将这张图片输入进网络,并绘制第 40 层的平均激活响应,如下图。

可以看到在特征图第 286 的地方,出现了强烈的飙升。显然它就是检测拱形结构的滤波器。但是注意,这样的形状结构可能对应着几个不同的类别。

那我们再看一个例子吧。左边这个看着像是鸡头(最后一层,第 256 个)。因此找了右边这一张图片来测试。同样的测试方法。

我们来看一看特征响应图。

好像似乎也印证了我的想法,可能是某种形状导致了最后的输出类别。也就是说,影响 CNN 效果的其实是形状特征(猜想)。

不过让我们再关注一个例子,用同样的方法。输入一张鸟类的图。

滤波器172,288,437,495(从左到右,从上到下)

我们发现了多个高响应的特征图。上面的特征图有像是鸟腿、眼睛和喙的东西?但是下面的特征图,看不出来是什么,可能与图像的背景有关,或者一些只有网络能理解的东西。这部分现在仍然是黑匣子。也许之前的猜想是错的。

接下来放一下代码(PyTorch):

 1generate_image.py
 2class FilterVisualizer():
 3    def __init__(self, size=56, upscaling_steps=12, upscaling_factor=1.2):
 4        self.size, self.upscaling_steps, self.upscaling_factor = size, upscaling_steps, upscaling_factor
 5        self.model = vgg16(pre=True).cuda().eval()
 6        set_trainable(self.model, False)
 7
 8    def visualize(self, layer, filter, lr=0.1, opt_steps=20, blur=None):
 9        sz = self.size
10        img = np.uint8(np.random.uniform(150, 180, (sz, sz, 3)))/255  # generate random image
11        activations = SaveFeatures(list(self.model.children())[layer])  # register hook
12
13        for _ in range(self.upscaling_steps):  # scale the image up upscaling_steps times
14            train_tfms, val_tfms = tfms_from_model(vgg16, sz)
15            img_var = V(val_tfms(img)[None], requires_grad=True)  # convert image to Variable that requires grad
16            optimizer = torch.optim.Adam([img_var], lr=lr, weight_decay=1e-6)
17            for n in range(opt_steps):  # optimize pixel values for opt_steps times
18                optimizer.zero_grad()
19                self.model(img_var)
20                loss = -activations.features[0, filter].mean()
21                loss.backward()
22                optimizer.step()
23            img = val_tfms.denorm(img_var.data.cpu().numpy()[0].transpose(1,2,0))
24            self.output = img
25            sz = int(self.upscaling_factor * sz)  # calculate new image size
26            img = cv2.resize(img, (sz, sz), interpolation = cv2.INTER_CUBIC)  # scale image up
27            if blur is not None: img = cv2.blur(img,(blur,blur))  # blur image to reduce high frequency patterns
28        self.save(layer, filter)
29        activations.close()
30
31    def save(self, layer, filter):
32        plt.imsave("layer_"+str(layer)+"_filter_"+str(filter)+".jpg", np.clip(self.output, 0, 1))
33
34
35pytorch_hook.py
36
37class  SaveFeatures():
38    def  __init__(self,module):
39        self .hook = module.register_forward_hook(self .hook_fn)
40    def  hook_fn(self,module,input,output):
41        self .features = torch.tensor(output,requires_grad = True).cuda()
42    def  close(self):
43        self .hook.remove()
44
45
46filter_visualizer.py
47
48layer = 40
49filter = 265
50FV = FilterVisualizer(size=56, upscaling_steps=12, upscaling_factor=1.2)
51FV.visualize(layer, filter, blur=5)
52

你以为到这里就完了吗?还没到这篇文章的重点内容,新鲜出炉的 2019 ICLR 的论文:《Imagenet-trained CNNs are biased towards texture; Increasing shape bias improves accuracy and robustness》

看标题,就知道。我们之前的猜想是错误的!CNN 学到的应该是纹理特征。真让人头疼!

作者以一个问题入手,一只披着象皮的猫,神经网络会把它识别为大象还是猫?最后根据实验结果得出结论。神经网络应该是根据物体的纹理特征来进行识别,而并非我们以为的形状特征。也就是说我们常了解的一些可视化技术如 Deconv 都是具有误导性的,它们的结果仅仅只是图像的重建部分,而与网络如何做出最后的决策关系不大。

其实接触过图像风格迁移技术的技术人员应该都非常清楚,深度学习模型在里面提取的图像的绘画风格就是纹理特征。贴上一张经典图片,生成的是一张具有梵高《星月夜》图画风格的建筑图片。

在论文里面,作者为了更清楚的了解,图像识别到底是基于形状还是基于纹理。做了以下的实验。使用三张生成的图片,分别是带有大象纹理的猫 , 带有钟表纹理的汽车 和 带有水瓶纹理的熊

作者通过实验,采用了多个神经网络(AlexNet、VGG-16、GoogLeNet、ResNet-50、ResNet-152、DenseNet-121、SqueezeNet1_1)进行输出结果。为了对照,还召集了大约 100 名人类来做对照实验。这个实验结果就是一只带有象皮纹理的猫被深度神经网络判断为大象,但对人类来说仍然是猫。带有时钟纹理的汽车被深度神经网络判断为时钟,带有水瓶纹理的熊被深度神经网络判断为水瓶。显然!该实验支持了这一说法,即目前用于物体识别的深度学习技术主要依赖纹理,而不是物体形状。

当然,作者还做了更多的对比实验。得出了一些具有启发性的结论。比如对于只包含纹理图片的数据集,神经网络能取得特别高的准确率。采用原图和灰度图,神经网络都可以取得非常高的准确率,而对于只包含轮廓和只包含边缘的图片,神经网络的预测准确率则显著降低。

更多的实验细节,可以查看论文。总结一下,有几点结论还是很有启发性的:

第一、回答了影响CNN识别性能的是形状还是纹理的问题。

第二、如何针对性的引导神经网络训练或者学习想要它学习的特征。(有意的抑制某个特征)

原文链接: https://blog.csdn.net/u012395979/article/details/86651808

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-01-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 AI科技大本营 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档