热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

听六小桨讲AI|第2期:卷积的批量计算及应用案例

点击左上方蓝字关注我们本栏目由百度飞桨RD们联手精心打造,对深度学习的知识点进行由浅入深的剖析和讲解。大家可视它为深度学习百科(面试秘籍也是可以哒&#x

点击左上方蓝字关注我们

本栏目由百度飞桨RD们联手精心打造,对深度学习的知识点进行由浅入深的剖析和讲解。大家可视它为深度学习百科(面试秘籍也是可以哒),当然也可收藏为深度学习查询手册~

大家好,六小桨第2期和大家见面啦,我是助教唐僧!就在上期,我们被杠了!居然有人质疑我们的算术不好,因为明明只有5个主桨人,哪来的六小桨……但是难道助教就不算人嘛?掩面哭泣~好吧,戏有点多了。

在上期中,主桨人见见为大家讲解了卷积的基本概念和计算。但在实际应用中,我们要处理的问题要复杂很多,因此,本期主桨人见见带来的是内容是:卷积的批量计算及应用案例

卷积的批量计算

一张彩色图片有RGB三个通道,因此在对彩色图片进行处理时,需要处理多输入通道的场景,相应的输出特征图往往也会具有多个通道,而且在神经网络的计算中常常是把一个批次的样本放在一起计算,所以卷积算子需要具有批量处理多输入和多输出通道数据的功能。

多输入通道场景


当输入数据有多个通道时,对应的卷积核也应该有相同的通道数。假设输入图片的通道数为,输入数据的形状是

  1. 对每个通道分别设计一个2维数组作为卷积核,卷积核数组的形状是

  2. 对任一通道,分别用大小为的卷积核在大小为的二维数组上做卷积。

  3. 将这个通道的计算结果相加,得到的是一个形状为的二维数组。

应用示例

上面的例子中,卷积核通常是2维数组,但实际上一张图片往往含有RGB三个通道,要计算卷积的输出结果,卷积核的形式也会发生变化。假设输入图片的通道数为3,输入数据的形状是,计算过程如 图1 所示。

  1. 对每个通道分别设计一个2维数组作为卷积核,卷积核数组的形状是

  2. 对任一通道,分别用大小为的卷积核在大小为的二维数组上做卷积。

  3. 将这3个通道的计算结果相加,得到的是一个形状为的二维数组。

图1 多输入通道计算过程

多输出通道场景


如果我们希望检测多种类型的特征,我们可以使用多个卷积核进行计算。所以一般来说,卷积操作的输出特征图也会具有多个通道,这时我们需要设计个维度为的卷积核,卷积核数组的维度是

  1. 对任一输出通道,分别使用上面描述的形状为的卷积核对输入图片做卷积。

  2. 将这个形状为的二维数组拼接在一起,形成维度为的三维数组。

应用示例

假设输入图片的通道数为3,我们希望检测2种类型的特征,因此需要输出数据的通道数为2,这时我们需要设计2个维度为的卷积核,卷积核数组的维度是,计算过程如 图2 所示。

  1. 对任一输出通道,分别使用上面描述的形状为的卷积核对输入图片做卷积。

  2. 将这个形状为的二维数组拼接在一起,形成维度为的三维数组。

图2 多输出通道计算过程

批量操作


在卷积神经网络的计算中,通常将多个样本放在一起形成一个mini-batch进行批量操作,即输入数据的维度是。由于会对每张图片使用同样的卷积核进行卷积操作,卷积核的维度是,那么,输出特征图的维度就是

应用示例

假设我们输入数据的维度是,卷积核的维度与上面多输出通道的情况一样,仍然是,输出特征图的维度是。计算过程如 图3 所示。

图3 批量操作


1 x 1 卷积

1 x 1 卷积,与标准卷积完全一样,唯一的特殊点在于卷积核的尺寸是1 x 1 ,也就是不考虑输入数据局部信息之间的关系,而把关注点放在不同通道间。当输入矩阵的尺寸为3 x 3 ,通道数也为3时,使用4个1 x 1卷积核进行卷积计算(多输出通道场景),最终就会得到与输入矩阵尺寸相同,通道数为4的输出矩阵,如 图4 所示。

图4  1 x 1卷积结构示意图

1 x 1 卷积的作用

1. 实现信息的跨通道交互与整合。考虑到卷积运算的输入输出都是3个维度(宽、高、通道),所以1 x 1 卷积实际上就是对每个像素点,在不同的通道上进行线性组合,从而整合不同通道的信息。‍‍‍‍‍‍

2. 对卷积核通道数进行降维和升维,减少参数量。经过1 x 1 卷积后的输出保留了输入数据的原有平面结构,通过调控通道数,从而完成升维或降维的作用。

3. 利用1 x 1 卷积后的非线性激活函数,在保持特征图尺寸不变的前提下,大幅增加非线性因素。

应用示例

  • 1 x 1 卷积在GoogLeNet[1]中的应用

GoogLeNet是2014年ImageNet比赛的冠军,它的主要特点是网络不仅有深度,还在横向上具有“宽度”。由于图像信息在空间尺寸上的巨大差异,如何选择合适的卷积核来提取特征就显得比较困难了。空间分布范围更广的图像信息适合用较大的卷积核来提取其特征;而空间分布范围较小的图像信息则适合用较小的卷积核来提取其特征。为了解决这个问题,GoogLeNet提出了一种被称为Inception模块的方案。如 图5 所示:

图5 Inception模块结构示意图

图5 (a)是Inception模块的设计思想,使用3个不同大小的卷积核对输入图片进行卷积操作,并附加最大池化,将这4个操作的输出沿着通道这一维度进行拼接,构成的输出特征图将会包含经过不同大小的卷积核提取出来的特征,从而达到捕捉不同尺度信息的效果。Inception模块采用多通路(multi-path)的设计形式,每个支路使用不同大小的卷积核,最终输出特征图的通道数是每个支路输出通道数的总和,这将会导致输出通道数变得很大,尤其是使用多个Inception模块串联操作的时候,模型参数量会变得非常大。

为了减小参数量,Inception模块使用了图5(b)中的设计方式,在3 x 3 和5 x 5 的卷积层之前,增加1 x 1的卷积层来控制输出通道数;在最大池化层后面增加1 x 1卷积层减小输出通道数。我们这里可以简单计算一下Inception模块中使用1 x 1 卷积前后参数量的变化,这里以GoogleNet中的Inception 5(a)模块为例,输入通道数=192,1 x 1 卷积的输出通道数=64,3 x 3 卷积的输出通道数=128,5 x 5 卷积的输出通道数=32,则图5(a)中的结构所需的参数量为:

1 x 1 x 192 x 64 + 3 x 3 x 192 x 128 + 5 x 5 x 192 x 32 = 387072

图5(b)中在3 x 3 卷积前增加了通道数=96的1 x 1卷积,在5 x 5 卷积前增加了通道数=16的 1 x 1 卷积,同时在max pooling后增加了通道数=32的 1 x 1 卷积,参数量变为:

1 x 1 x 192 x 64 + 1 x 1 x 192 x 96 +1 x 1 x 192 x 16 +3 x 3 x 96 x 128 +5 x 5 x 16 x 32 + 1 x 1 x 192 x 32 = 163328

可见,1 x 1卷积可以在不改变模型表达能力的前提下,大大减少所使用的参数量。

  • 1 x 1 卷积在ResNet[2]中的应用

随着深度学习的不断发展,模型的层数越来越多,网络结构也越来越复杂。但是增加网络的层数之后,训练误差往往不降反升。由此,Kaiming He等人提出了残差网络ResNet来解决上述问题。ResNet是2015年ImageNet比赛的冠军,将识别错误率降低到了3.6%,这个结果甚至超出了正常人眼识别的精度。在ResNet中,提出了一个非常经典的结构—残差块(Residual block)。

残差块具体设计方案如 图6 所示。不同规模的残差网络中使用的残差块也并不相同,对于小规模的网络,残差块如图6(a)所示,但是对于稍大的模型,使用图6(a)的结构会导致参数量非常大,因此从ResNet50以后,都是使用图6(b)的结构。图6(b)中的这种设计方案也常称作瓶颈结构(BottleNeck)。1 x 1的卷积核可以非常方便的调整中间层的通道数,在进入3 x 3的卷积层之前减少通道数(256->64),经过该卷积层后再恢复通道数(64->256),可以显著减少网络的参数量。这个结构(256->64->256)像一个中间细,两头粗的瓶颈,所以被称为“BottleNeck”。

我们这里可以简单计算一下残差块中使用1 x 1 卷积前后参数量的变化,为了保持统一,我们令图6中的两个结构的输入输出通道数均为256,则图6 (a)中的结构所需的参数量为:

3 x 3 x 256 x 256 x 2 = 1179648

而图6(b)中采用了1 x 1 卷积后,参数量为:

1 x 1 x 256 x 64 + 3 x 3 x 64 x 64 + 1 x 1 x 64 x256 = 69632

同样,1 x 1卷积大大减少所使用的参数量。

图6 残差块结构示意图

‍‍‍‍‍‍‍‍‍‍‍‍‍‍

卷积应用案例

案例1:简单的黑白边界检测

下面是使用卷积算子Conv2D完成一个图像边界检测的任务。如 图7 所示,图像左边为光亮部分,右边为黑暗部分,需要检测出光亮跟黑暗的分界处。

图7 输入图像

图8 卷积核

具体代码如下所示,结果输出在下方的图案中,如 图9 所示。

import matplotlib.pyplot as plt
import numpy as np
import paddle
from paddle.nn import Conv2D
from paddle.nn.initializer import Assign
%matplotlib inline# 创建初始化权重参数w
w = np.array([1, 0, -1], dtype='float32')
# 将权重参数调整成维度为[cout, cin, kh, kw]的四维张量
w = w.reshape([1, 1, 1, 3])
# 创建卷积算子,设置输出通道数,卷积核大小,和初始化权重参数
# kernel_size = [1, 3]表示kh = 1, kw=3
# 创建卷积算子的时候,通过参数属性weight_attr指定参数初始化方式
# 这里的初始化方式时,从numpy.ndarray初始化卷积参数
conv = Conv2D(in_channels=1, out_channels=1, kernel_size=[1, 3],weight_attr=paddle.ParamAttr(initializer=Assign(value=w)))# 创建输入图片,图片左边的像素点取值为1,右边的像素点取值为0
img = np.ones([50,50], dtype='float32')
img[:, 30:] = 0.
# 将图片形状调整为[N, C, H, W]的形式
x = img.reshape([1,1,50,50])
# 将numpy.ndarray转化成paddle中的tensor
x = paddle.to_tensor(x)
# 使用卷积算子作用在输入图片上
y = conv(x)
# 将输出tensor转化为numpy.ndarray
out = y.numpy()
f = plt.subplot(121)
f.set_title('input image', fontsize=15)
plt.imshow(img, cmap='gray')
f = plt.subplot(122)
f.set_title('output featuremap', fontsize=15)
# 卷积算子Conv2D输出数据形状为[N, C, H, W]形式
# 此处N, C=1,输出数据形状为[1, 1, H, W],是4维数组
# 但是画图函数plt.imshow画灰度图时,只接受2维数组
# 通过numpy.squeeze函数将大小为1的维度消除
plt.imshow(out.squeeze(), cmap='gray')
plt.show()
# 查看卷积层的权重参数名字和数值
print(conv.weight)
# 参看卷积层的偏置参数名字和数值
print(conv.bias)

图9 输出图像

案例2:图像中物体边缘检测(图像锐化)

上面展示的是人为构造的简单图片,使用卷积网络检测图片明暗分界处的示例。对于真实的图片,我们也可以使用合适的卷积核来检测物体的边缘轮廓。如 图10所示。

图10 输入图像

图11 卷积核

观察输出特征图跟原图之间的对应关系,如下代码所示,输出图像如图12所示。

import matplotlib.pyplot as plt
from PIL import Image
import numpy as np
import paddle
from paddle.nn import Conv2D
from paddle.nn.initializer import Assign
img = Image.open('./img/example1.jpg')# 设置卷积核参数
w = np.array([[-1,-1,-1], [-1,8,-1], [-1,-1,-1]], dtype='float32')/8
w = w.reshape([1, 1, 3, 3])
# 由于输入通道数是3,将卷积核的形状从[1,1,3,3]调整为[1,3,3,3]
w = np.repeat(w, 3, axis=1)
# 创建卷积算子,输出通道数为1,卷积核大小为3x3,
# 并使用上面的设置好的数值作为卷积核权重的初始化参数
conv = Conv2D(in_channels=3, out_channels=1, kernel_size=[3, 3], weight_attr=paddle.ParamAttr(initializer=Assign(value=w)))# 将读入的图片转化为float32类型的numpy.ndarray
x = np.array(img).astype('float32')
# 图片读入成ndarry时,形状是[H, W, 3],
# 将通道这一维度调整到最前面
x = np.transpose(x, (2,0,1))
# 将数据形状调整为[N, C, H, W]格式
x = x.reshape(1, 3, img.height, img.width)
x = paddle.to_tensor(x)
y = conv(x)
out = y.numpy()
plt.figure(figsize=(20, 10))
f = plt.subplot(121)
f.set_title('input image', fontsize=15)
plt.imshow(img)
f = plt.subplot(122)
f.set_title('output feature map', fontsize=15)
plt.imshow(out.squeeze(), cmap='gray')
plt.show()

图12 输出图像

案例3:图像均值模糊

对一张输入图像,如图13所示,我们尝试使用卷积算子实现图像均值模糊任务。

图13 输入图像

图14 卷积核


实现代码如下所示,输出图像如图15所示。

import paddle
import matplotlib.pyplot as plt
from PIL import Image
import numpy as np
from paddle.nn import Conv2D
from paddle.nn.initializer import Assign
# 读入图片并转成numpy.ndarray
# 换成灰度图
img = Image.open('./img/example2.jpg').convert('L')
img = np.array(img)# 创建初始化参数
w = np.ones([1, 1, 5, 5], dtype = 'float32')/25
conv = Conv2D(in_channels=1, out_channels=1, kernel_size=[5, 5], weight_attr=paddle.ParamAttr(initializer=Assign(value=w)))
x = img.astype('float32')
x = x.reshape(1,1,img.shape[0], img.shape[1])
x = paddle.to_tensor(x)
y = conv(x)
out = y.numpy()plt.figure(figsize=(20, 12))
f = plt.subplot(121)
f.set_title('input image')
plt.imshow(img, cmap='gray')f = plt.subplot(122)
f.set_title('output feature map')
out = out.squeeze()
plt.imshow(out, cmap='gray')plt.show()

图15 输出图像

本期内容详细介绍了深度学习中卷积的批量多通道计算以及1x1卷积,最后介绍了卷积的应用案例。下一期将由主桨人步步高为大家带来优化器的讲解,感兴趣的记得关注『听六小桨讲AI』系列内容,下期见~~

如果您有话对『六小桨』说,欢迎在文章下留言:)

参考文献

[1] Going deeper with convolutions

[2] Deep Residual Learning for Image Recognition

回顾往期:

听六小桨讲AI | 第1期:卷积概念及计算

如在使用过程中有问题,可加入官方QQ群进行交流:778260830。

如果您想详细了解更多飞桨的相关内容,请参阅以下文档。

·飞桨官网地址·

https://www.paddlepaddle.org.cn/

·飞桨开源框架项目地址·

GitHub: https://github.com/PaddlePaddle/Paddle 

Gitee: https://gitee.com/paddlepaddle/Paddle

????长按上方二维码立即star!????

飞桨(PaddlePaddle)以百度多年的深度学习技术研究和业务应用为基础,是中国首个开源开放、技术领先、功能完备的产业级深度学习平台,包括飞桨开源平台和飞桨企业版。飞桨开源平台包含核心框架、基础模型库、端到端开发套件与工具组件,持续开源核心能力,为产业、学术、科研创新提供基础底座。飞桨企业版基于飞桨开源平台,针对企业级需求增强了相应特性,包含零门槛AI开发平台EasyDL和全功能AI开发平台BML。EasyDL主要面向中小企业,提供零门槛、预置丰富网络和模型、便捷高效的开发平台;BML是为大型企业提供的功能全面、可灵活定制和被深度集成的开发平台。

???? 近期直播 ????

END


推荐阅读
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • 微软头条实习生分享深度学习自学指南
    本文介绍了一位微软头条实习生自学深度学习的经验分享,包括学习资源推荐、重要基础知识的学习要点等。作者强调了学好Python和数学基础的重要性,并提供了一些建议。 ... [详细]
  • 本文介绍了在Python3中如何使用选择文件对话框的格式打开和保存图片的方法。通过使用tkinter库中的filedialog模块的asksaveasfilename和askopenfilename函数,可以方便地选择要打开或保存的图片文件,并进行相关操作。具体的代码示例和操作步骤也被提供。 ... [详细]
  • 生成式对抗网络模型综述摘要生成式对抗网络模型(GAN)是基于深度学习的一种强大的生成模型,可以应用于计算机视觉、自然语言处理、半监督学习等重要领域。生成式对抗网络 ... [详细]
  • 本文介绍了在开发Android新闻App时,搭建本地服务器的步骤。通过使用XAMPP软件,可以一键式搭建起开发环境,包括Apache、MySQL、PHP、PERL。在本地服务器上新建数据库和表,并设置相应的属性。最后,给出了创建new表的SQL语句。这个教程适合初学者参考。 ... [详细]
  • 本文介绍了设计师伊振华受邀参与沈阳市智慧城市运行管理中心项目的整体设计,并以数字赋能和创新驱动高质量发展的理念,建设了集成、智慧、高效的一体化城市综合管理平台,促进了城市的数字化转型。该中心被称为当代城市的智能心脏,为沈阳市的智慧城市建设做出了重要贡献。 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • [译]技术公司十年经验的职场生涯回顾
    本文是一位在技术公司工作十年的职场人士对自己职业生涯的总结回顾。她的职业规划与众不同,令人深思又有趣。其中涉及到的内容有机器学习、创新创业以及引用了女性主义者在TED演讲中的部分讲义。文章表达了对职业生涯的愿望和希望,认为人类有能力不断改善自己。 ... [详细]
  • baresip android编译、运行教程1语音通话
    本文介绍了如何在安卓平台上编译和运行baresip android,包括下载相关的sdk和ndk,修改ndk路径和输出目录,以及创建一个c++的安卓工程并将目录考到cpp下。详细步骤可参考给出的链接和文档。 ... [详细]
  • 本文介绍了开关稳压器设计中PCB布局布线的重要性,并提供了相应的准则。开关稳压器作为一种高效的电源,逐渐取代了线性稳压器。开关模式电源的工作原理是通过一定的开启时间和关闭时间来实现电压转换。开关频率并不是影响系统的最大因素,而开关转换的速度才是关键。在系统噪声方面,开关频率或其谐波可能会对系统产生影响。严格遵守PCB布局布线的准则,可以将开关模式电源的相关问题降到最小。 ... [详细]
  • 关于我们EMQ是一家全球领先的开源物联网基础设施软件供应商,服务新产业周期的IoT&5G、边缘计算与云计算市场,交付全球领先的开源物联网消息服务器和流处理数据 ... [详细]
  • 本文介绍了P1651题目的描述和要求,以及计算能搭建的塔的最大高度的方法。通过动态规划和状压技术,将问题转化为求解差值的问题,并定义了相应的状态。最终得出了计算最大高度的解法。 ... [详细]
  • 推荐系统遇上深度学习(十七)详解推荐系统中的常用评测指标
    原创:石晓文小小挖掘机2018-06-18笔者是一个痴迷于挖掘数据中的价值的学习人,希望在平日的工作学习中,挖掘数据的价值, ... [详细]
  • 【MicroServices】【Arduino】装修甲醛检测,ArduinoDart甲醛、PM2.5、温湿度、光照传感器等,数据记录于SD卡,Python数据显示,UI5前台,微服务后台……
    这篇文章介绍了一个基于Arduino的装修甲醛检测项目,使用了ArduinoDart甲醛、PM2.5、温湿度、光照传感器等硬件,并将数据记录于SD卡,使用Python进行数据显示,使用UI5进行前台设计,使用微服务进行后台开发。该项目还在不断更新中,有兴趣的可以关注作者的博客和GitHub。 ... [详细]
  • CF:3D City Model(小思维)问题解析和代码实现
    本文通过解析CF:3D City Model问题,介绍了问题的背景和要求,并给出了相应的代码实现。该问题涉及到在一个矩形的网格上建造城市的情景,每个网格单元可以作为建筑的基础,建筑由多个立方体叠加而成。文章详细讲解了问题的解决思路,并给出了相应的代码实现供读者参考。 ... [详细]
author-avatar
天天火火红红
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有