mirror of
https://github.com/chenzomi12/aisystem.git
synced 2025-10-20 12:53:45 +08:00
fotmat for 04Inference/05Kernel/03Im2col.md
This commit is contained in:
49
00Others/Editors.md
Normal file
49
00Others/Editors.md
Normal file
@ -0,0 +1,49 @@
|
||||
# 编辑和作者
|
||||
|
||||
## 章节编辑
|
||||
|
||||
本书由超过30位人工智能系统领域的学术专家和开发人员共同完成。以下为各个章节编辑:
|
||||
|
||||
项目README: [@luomai](https://github.com/luomai)
|
||||
|
||||
序言:[@luomai](https://github.com/luomai)
|
||||
|
||||
导论:[@luomai](https://github.com/luomai)
|
||||
|
||||
编程接口:[@Laicheng0830](https://github.com/Laicheng0830)
|
||||
|
||||
计算图:[@hanjr92](https://github.com/hanjr92)
|
||||
|
||||
进阶篇序言:[@ganzhiliang](https://github.com/ganzhiliang)
|
||||
|
||||
编译器前端和IR: [@LiangZhibo](https://github.com/LiangZhibo)
|
||||
|
||||
编译器后端和运行时: [@chujinjin101](https://github.com/chujinjin101)
|
||||
|
||||
硬件加速器:[@anyrenwei](https://github.com/anyrenwei)
|
||||
|
||||
数据处理框架: [@eedalong](https://github.com/eedalong)
|
||||
|
||||
模型部署: [@AssassinG](https://github.com/AssassinGQ)
|
||||
|
||||
分布式训练系统: [@luomai](https://github.com/luomai)
|
||||
|
||||
拓展篇序言:[@luomai](https://github.com/luomai)
|
||||
|
||||
深度学习推荐系统:[@future-xy](https://github.com/future-xy)
|
||||
|
||||
联邦学习系统:[@chengtianwu](https://github.com/chengtianwu)
|
||||
|
||||
强化学习系统:[@quantumiracle](https://github.com/quantumiracle)
|
||||
|
||||
可解释性AI系统:[@HaoyangLee](https://github.com/HaoyangLee)
|
||||
|
||||
机器人系统:[@Jack](https://github.com/Jiankai-Sun)
|
||||
|
||||
附录:机器学习介绍:[@Hao](https://github.com/zsdonghao)
|
||||
|
||||
## 加入我们
|
||||
|
||||
我们创建了OpenMLSys微信群来讨论书籍的写作和拓展。如果希望加入我们,可以扫以下二维码(加的时候请介绍自己,并说明希望参与书籍的哪方面工作):
|
||||
|
||||

|
35
00Others/Install.md
Normal file
35
00Others/Install.md
Normal file
@ -0,0 +1,35 @@
|
||||
## 环境安装
|
||||
机器学习系统书籍部署在GitHub是依赖于d2lbook工具实现的。因此我们首先要安装d2lbook。
|
||||
```bash
|
||||
git clone https://github.com/openmlsys/d2l-book.git
|
||||
cd d2l-book
|
||||
python setup.py install
|
||||
```
|
||||
使用d2lbook构建HTML需要安装`pandoc`, 可以使用`conda install pandoc` (如果是MacOS可以用Homebrew), apt源中pandoc发布版本较低,表格转换格式可能有误,请尽量使用较新版本的pandoc。
|
||||
构建PDF时如果有SVG图片需要安装LibRsvg来转换SVG图片,安装`librsvg`可以通过`apt-get install librsvg`(如果是MacOS可以用Homebrew)。
|
||||
当然构建PDF必须要有LaTeX,如安装[Tex Live](https://www.tug.org/texlive/).
|
||||
|
||||
## 编译HTML版本
|
||||
在编译前先下载[openmlsys-zh](https://github.com/openmlsys/openmlsys-zh) , 所有的编译命令都在这个文件目录内执行。
|
||||
```bash
|
||||
git clone https://github.com/openmlsys/openmlsys-zh.git
|
||||
cd openmlsys-zh
|
||||
```
|
||||
使用d2lbook工具编译HTML。 请尽量使用build_html.sh脚本进行编译,保证首页正确合并到书籍中去。
|
||||
```
|
||||
sh build_html.sh
|
||||
```
|
||||
|
||||
生成的html会在`_build/html`。
|
||||
|
||||
此时我们将编译好的html整个文件夹下的内容拷贝至openmlsys.github.io的docs发布。
|
||||
|
||||
需要注意的是docs目录下的.nojekyll不要删除了,不然网页会没有渲染。
|
||||
|
||||
## 样式规范
|
||||
|
||||
贡献请遵照本教程的[样式规范](style.md)。
|
||||
|
||||
## 中英文术语对照
|
||||
|
||||
翻译请参照[中英文术语对照](terminology.md)。
|
@ -8,7 +8,7 @@
|
||||
|
||||
## 卷积的数学原理
|
||||
|
||||
在通常形式中,卷积是对两个实变函数的一种数学运算。在泛函分析中,卷积、旋积或褶积 (Convolution) 是通过两个函数 $$f$$ 和$$ g$$ 生成第三个函数的一种数学运算,其本质是一种特殊的积分变换,表征函数$$ f$$ 与$$ g$$ 经过翻转和平移的重叠部分函数值乘积对重叠长度的积分。
|
||||
在通常形式中,卷积是对两个实变函数的一种数学运算。在泛函分析中,卷积、旋积或褶积 (Convolution) 是通过两个函数 $f$ 和 $g$ 生成第三个函数的一种数学运算,其本质是一种特殊的积分变换,表征函数 $f$ 与 $g$ 经过翻转和平移的重叠部分函数值乘积对重叠长度的积分。
|
||||
|
||||
卷积神经网络(Convolution Neural Networks, CNN)的概念拓展自信号处理领域的卷积。信号处理的卷积定义为:
|
||||
|
||||
@ -16,7 +16,7 @@ $$
|
||||
(f*g)(t)\triangleq\int_{\mathbb{R}^{n}}f(\tau)g(t-\tau)d\tau
|
||||
$$
|
||||
|
||||
可以证明,关于几乎所有的实数 x,随着 x 的不同取值,积分定义了一个新函数 $$ℎ(x)$$,称为函数 $$f $$与 $$g $$的卷积,记为:
|
||||
可以证明,关于几乎所有的实数 x,随着 x 的不同取值,积分定义了一个新函数 $ℎ(x)$,称为函数 $f$ 与 $g$ 的卷积,记为:
|
||||
|
||||
$$
|
||||
h(x)=(f*g)(x)
|
||||
@ -28,7 +28,7 @@ $$
|
||||
(f*g)(n)\triangleq\sum_{\mathbb{Z}^{n}}f(m)g(n-m)
|
||||
$$
|
||||
|
||||
### ”怎么卷“和“怎么积”
|
||||
### 通俗理解
|
||||
|
||||
卷积计算在直觉上不易理解,其可视化后如下图所示。图中红色滑块在移动过程中与蓝色方块的积绘制成的三角图案即为卷积结果在各点上的取值:
|
||||
|
||||
@ -36,7 +36,7 @@ $$
|
||||
|
||||
更具体来说,解释卷积需要清楚“怎么卷”和”怎么积“两个步骤。
|
||||
|
||||
#### “卷”的过程
|
||||
1. “卷”的过程
|
||||
|
||||
根据上述介绍中卷积的定义:
|
||||
|
||||
@ -50,56 +50,57 @@ $$
|
||||
x=\tau,y=t-\tau
|
||||
$$
|
||||
|
||||
则有$$x+y=t$$成立。
|
||||
则有 $x+y=t$ 成立。
|
||||
|
||||
换言之,在卷积的过程中,函数$$f(x)$$与$$g(y)$$中$$x,y$$取值受线性函数$$x+y=t$$的约束。若令$$t=10$$,则$$x,y$$的取值序列有如下图所示的对应关系。直观上$$x,y$$的取值有一种翻转对应的感觉。
|
||||
换言之,在卷积的过程中,函数 $f(x)$ 与 $g(y)$ 中 $x,y$ 取值受线性函数 $x+y=t$ 的约束。若令 $t=10$,则 $x,y$ 的取值序列有如下图所示的对应关系。直观上 $x,y$ 的取值有一种翻转对应的感觉。
|
||||
|
||||

|
||||
|
||||
#### ”积“的过程
|
||||
2. ”积“的过程
|
||||
|
||||
当$$t$$的取值变化时,$$x,y$$的取值约束在下图所示的斜率为-1 的直线簇中。
|
||||
当 $t$ 的取值变化时,$x,y$ 的取值约束在下图所示的斜率为 -1 的直线簇中。
|
||||
|
||||
定义:
|
||||
|
||||
定义
|
||||
$$
|
||||
g(y)=f(x)=\begin{cases}0,x<0.5\\1,-0.5\leqslant x \leqslant0.5\\0,x>0.5\end{cases}
|
||||
$$
|
||||
|
||||
下图(左)中$$t$$的取值从上到下分别为-1,-0.5,0,0.5,1,令$$y=t-\tau,x=\tau$$,左图中的红线为$$g(t-\tau)$$的函数图像,蓝线为$$f(\tau)$$的函数图像。黄色区域为不同 t 的取值条件下参与卷积的有效区间,黑色直线最右端的点的取值为卷积结果。
|
||||
下图(左)中 $t$ 的取值从上到下分别为-1,-0.5,0,0.5,1,令 $y=t-\tau,x=\tau$,左图中的红线为 $g(t-\tau)$ 的函数图像,蓝线为 $f(\tau)$ 的函数图像。黄色区域为不同 t 的取值条件下参与卷积的有效区间,黑色直线最右端的点的取值为卷积结果。
|
||||
|
||||

|
||||
|
||||
总结来说,积分的本质为可理解为求和的极限,卷积中“积”的过程即为相应的函数相乘和求积分的过程。
|
||||
|
||||
### 一个例子
|
||||
### 具体例子
|
||||
|
||||
以信号处理的系统响应函数为例:
|
||||
|
||||
定义输入信号是 $$f(t)$$ ,随时间变化其数值保持不变。系统响应函数是$$ g(t) $$,图中的响应函数是随时间指数下降的,它的物理意义是说:如果在$$ t=t_{1} $$的时刻有一个输入,那么随着时间的流逝,这个输入将不断衰减。
|
||||
定义输入信号是 $f(t)$ ,随时间变化其数值保持不变。系统响应函数是 $g(t)$,图中的响应函数是随时间指数下降的,它的物理意义是说:如果在 $t=t_{1}$ 的时刻有一个输入,那么随着时间的流逝,这个输入将不断衰减。
|
||||
|
||||

|
||||
|
||||
由于信号 $$f(t)$$是连续输入的,也就是说,每个时刻都有新的信号进来。同时,该时刻前面的输入对后面仍有影响,该影响以$$ g(t) $$的形式衰减。如下图所示,在$$t_{2}$$时刻,系统的输入既包括$$t_{2}$$时刻的新信号,也包括$$t_{1}$$时刻衰减后的响应(黄色框中的红色虚线点)。所以可以推知,系统最终输出的是所有之前输入信号的累积效果。
|
||||
由于信号 $f(t)$ 是连续输入的,也就是说,每个时刻都有新的信号进来。同时,该时刻前面的输入对后面仍有影响,该影响以 $g(t)$ 的形式衰减。如下图所示,在 $t_{2}$ 时刻,系统的输入既包括 $t_{2}$ 时刻的新信号,也包括 $t_{1}$ 时刻衰减后的响应(黄色框中的红色虚线点)。所以可以推知,系统最终输出的是所有之前输入信号的累积效果。
|
||||
|
||||

|
||||
|
||||
如下图(左)所示,由于信号的响应随时间衰减,我们假定每个时刻的新信号产生的响应的影响范围为 5 个等距时间段$$T$$,即在$$t_{0}$$产生的新信号的响应影响至$$t_{5}$$时刻。那么在$$T=t_{5}$$时刻,输出结果跟图中绿色框的区域整体有关。
|
||||
如下图(左)所示,由于信号的响应随时间衰减,我们假定每个时刻的新信号产生的响应的影响范围为 5 个等距时间段 $T$,即在 $t_{0}$ 产生的新信号的响应影响至 $t_{5}$ 时刻。那么在 $T=t_{5}$ 时刻,输出结果跟图中绿色框的区域整体有关。
|
||||
|
||||

|
||||
|
||||
其中,$$f(t_{5})$$因为是刚输入的,所以其输出结果应该是$$f(t_{5})g(t_{0})$$,而时刻$$t_{4}$$的输入$$f(t_{4})$$,只经过了 1 个时间单位的衰减,所以产生的输出应该是$$ f(t_{4})g(t_{1})$$,如此类推,即图中虚线所描述的关系。这些对应点相乘然后累加,就是$$T=t_{5}$$时刻的输出信号值,这个结果也是$$f$$和$$g$$两个函数在$$T=t_{5}$$时刻的卷积值。
|
||||
其中,$f(t_{5})$ 因为是刚输入的,所以其输出结果应该是 $f(t_{5})g(t_{0})$,而时刻$t_{4}$ 的输入 $f(t_{4})$,只经过了 1 个时间单位的衰减,所以产生的输出应该是 $f(t_{4})g(t_{1})$,如此类推,即图中虚线所描述的关系。这些对应点相乘然后累加,就是 $T=t_{5}$ 时刻的输出信号值,这个结果也是 $f$ 和$g$ 两个函数在 $T=t_{5}$ 时刻的卷积值。
|
||||
|
||||
从上图来看$$f$$和$$g$$这种对应关系并不直观,因此对$$g$$关于$$y$$轴对称变换一下,变为$$g(-t_{i})$$,变换后$$f$$和$$g$$的对应关系如下图所示。
|
||||
从上图来看 $f$ 和 $g$ 这种对应关系并不直观,因此对 $g$ 关于 $y$ 轴对称变换一下,变为 $g(-t_{i})$,变换后 $f$ 和 $g$ 的对应关系如下图所示。
|
||||
|
||||

|
||||
|
||||
进一步,将$$g(-t_{i})$$图像右移$$T$$个时间单位,得到$$g(T-t_{i})$$:
|
||||
进一步,将 $g(-t_{i})$ 图像右移 $T$ 个时间单位,得到 $g(T-t_{i})$:
|
||||
|
||||

|
||||
|
||||
这样我们就得到了$$f*g(T)=\int f(t)g(T-t)dt$$的直观的图示表达。
|
||||
这样我们就得到了 $f*g(T)=\int f(t)g(T-t)dt$ 的直观的图示表达。
|
||||
|
||||
一般来讲,当我们用计算机处理数据时,时间会被离散化,传感器会定期地反馈数据。所以在上述例子中,假设传感器每秒反馈一次测量结果是比较现实的。这样,时刻$$t_{i}$$只能取整数值,如果假设$$g$$和$$f$$都定义在整数时刻$$t_{i}$$上,就可以定义上述条件下离散形式的卷积:
|
||||
一般来讲,当我们用计算机处理数据时,时间会被离散化,传感器会定期地反馈数据。所以在上述例子中,假设传感器每秒反馈一次测量结果是比较现实的。这样,时刻 $t_{i}$ 只能取整数值,如果假设 $g$ 和 $f$ 都定义在整数时刻 $t_{i}$ 上,就可以定义上述条件下离散形式的卷积:
|
||||
|
||||
$$
|
||||
g(T)=(f*g)(T)=\sum_{i=0}^{i=T} f(t_{i})g(T-t_{i})
|
||||
@ -107,33 +108,34 @@ $$
|
||||
|
||||
### 卷积的性质
|
||||
|
||||
1. 交换律:$$ f * g = g * f $$
|
||||
2. 结合律:$$(f * g) * h = f * (g * h)$$
|
||||
3. 分配律:$$f * (g + h) = f * g + f * h$$
|
||||
4. 单位响应:存在一个函数 $$\delta$$,使得 $$f * \delta = f$$,其中 $$\delta$$ 是狄拉克$$δ$$函数(连续)或单位脉冲函数(离散)。
|
||||
1. 交换律:$f * g = g * f$
|
||||
2. 结合律:$(f * g) * h = f * (g * h)$
|
||||
3. 分配律:$f * (g + h) = f * g + f * h$
|
||||
4. 单位响应:存在一个函数 $\delta$,使得 $f * \delta = f$,其中 $\delta$ 是狄拉克 $δ$ 函数(连续)或单位脉冲函数(离散)。
|
||||
|
||||
### 卷积的物理意义
|
||||
### 卷积物理意义
|
||||
|
||||
卷积的物理意义取决于它所应用的具体领域。在不同的领域中,卷积可以代表不同的物理过程。
|
||||
|
||||
#### 信号处理
|
||||
在信号处理领域,卷积的物理意义通常与系统的响应有关。假设我们有一个输入信号 $$f(t)$$(例如,一个音频信号)和一个系统对该信号的响应 $$g(t)$$(系统的输出)。系统的响应 $$g(t)$$ 可以是理想的,也可以是实际测量得到的。
|
||||
1. 信号处理
|
||||
|
||||
当输入信号$$ f(t)$$通过系统时,系统的输出 $$h(t)$$ 可以通过卷积 $$f∗g $$来计算。这里的卷积表示系统对输入信号的累积响应。具体来说,$$h(t)$$ 在任意时刻 $$t$$ 的值是输入信号 $$f(t)$$ 与系统响应 $$g(t)$$ 在过去所有时刻的加权叠加。权重由系统响应 $$g$$ 决定,反映了系统对不同时刻输入信号的“记忆”。
|
||||
在信号处理领域,卷积的物理意义通常与系统的响应有关。假设我们有一个输入信号 $f(t)$(例如,一个音频信号)和一个系统对该信号的响应 $g(t)$(系统的输出)。系统的响应 $g(t)$ 可以是理想的,也可以是实际测量得到的。
|
||||
|
||||
例如,如果一个系统对输入信号的响应是滞后的,那么输出信号 $$h(t)$$ 将是输入信号 $$f(t)$$ 的平滑版本,其中$$ g(t)$$决定了平滑的程度。
|
||||
当输入信号$f(t)$ 通过系统时,系统的输出 $h(t)$ 可以通过卷积 $f∗g$ 来计算。这里的卷积表示系统对输入信号的累积响应。具体来说,$h(t)$ 在任意时刻 $t$ 的值是输入信号 $f(t)$ 与系统响应 $g(t)$ 在过去所有时刻的加权叠加。权重由系统响应 $g$ 决定,反映了系统对不同时刻输入信号的“记忆”。
|
||||
|
||||
#### 图像处理
|
||||
例如,如果一个系统对输入信号的响应是滞后的,那么输出信号 $h(t)$ 将是输入信号 $f(t)$ 的平滑版本,其中$g(t)$ 决定了平滑的程度。
|
||||
|
||||
在图像处理中,卷积通常用于滤波和特征提取。在这种情况下,图像可以被视为二维信号 $$f(x,y)$$,其中 $$x$$ 和 $$y $$分别是图像的水平和垂直坐标。卷积核 $$g(x,y) $$是一个小的权重矩阵,它在图像上滑动,计算每个像素点的加权平均值。
|
||||
2. 图像处理
|
||||
|
||||
这个过程的物理意义是将图像的每个像素点与其周围的像素点进行比较,通过加权平均来确定这个像素点的新值。卷积核$$ g$$ 的设计决定了这种比较的方式,例如,边缘检测卷积核会突出显示图像中强度变化明显的区域,从而检测出边缘。
|
||||
在图像处理中,卷积通常用于滤波和特征提取。在这种情况下,图像可以被视为二维信号 $f(x,y)$,其中 $x$ 和 $y$分别是图像的水平和垂直坐标。卷积核 $g(x,y)$ 是一个小的权重矩阵,它在图像上滑动,计算每个像素点的加权平均值。
|
||||
|
||||
#### 概率论
|
||||
这个过程的物理意义是将图像的每个像素点与其周围的像素点进行比较,通过加权平均来确定这个像素点的新值。卷积核 $g$ 的设计决定了这种比较的方式,例如,边缘检测卷积核会突出显示图像中强度变化明显的区域,从而检测出边缘。
|
||||
|
||||
3. 概率论
|
||||
|
||||
在概率论中,两个独立随机变量的联合概率密度函数的卷积给出了它们的和的概率密度函数。这背后的物理意义是,如果你有两个随机过程,它们分别产生随时间变化的概率密度函数,那么这两个过程叠加后的新过程的概率密度函数可以通过卷积原来的两个概率密度函数来得到。
|
||||
|
||||
#### 其他物理系统
|
||||
4. 其他物理系统
|
||||
|
||||
在其他物理系统中,卷积可以表示扩散过程、波的传播、材料的混合等。在这些情况下,卷积描述了一个物理量(如温度、压力、浓度等)随时间和空间的分布变化,它是通过系统中各个部分之间的相互作用和传播效应累积而成的。
|
||||
|
||||
@ -142,6 +144,7 @@ $$
|
||||
### 离散卷积
|
||||
|
||||
从上文信号分析的部分中,我们得到离散形式的卷积公式:
|
||||
|
||||
$$
|
||||
(f*g)(n)\triangleq\sum_{\mathbb{Z}^{n}}f(m)g(n-m)
|
||||
$$
|
||||
@ -156,9 +159,7 @@ $$
|
||||
S(i,j)=(I^{*}K)(i,j)=\sum_{m}\sum_{n}I(m,n)K(i-m,j-n)
|
||||
$$
|
||||
|
||||
其中:S 为卷积的输出,I 为卷积输入,K 为卷积核的尺寸。
|
||||
|
||||
卷积是可交换的,我们可等价地写作:
|
||||
其中:S 为卷积的输出,I 为卷积输入,K 为卷积核的尺寸。因为卷积是可交换的,我们可等价地写作:
|
||||
|
||||
$$
|
||||
S(i,j)=(K^{*}I)(i,j)=\sum_{m}\sum_{n}I(i-m,j-n)K(m,n)
|
||||
@ -166,15 +167,15 @@ $$
|
||||
|
||||
对于二维的情况,卷积对应着一个双重分块循环矩阵。除了元素相等方面的限制之外,卷积通常对应着一个非常稀疏的矩阵。这是因为核的大小通常远小于输入图像的大小。任何一个使用矩阵乘法但是并不依赖于矩阵结构的特殊性质的神经网络算法,都适用于卷积计算,并且不需要对神经网络做出大的修改。
|
||||
|
||||
在卷积网络的术语中,卷积的第一个参数(函数$$f$$)通常叫做输入(input),第二个参数(函数$$g$$)叫做核函数(kernel function)。输出有时被称为特征映射(feature map)。在机器学习的应用中,输入通常是多维数组的数据,而核通常是由学习算法优化得到的多维数组的参数。我们把这些多维数组叫做张量。因为在输入与核中的每一个元素都必须明确地分开存储,我们通常假设在存储了数值的有限点集以外,这些函数的值都为 0。这意味着在实际操作中,我们可以通过对有限个数组元素的求和来实现无限求和。
|
||||
在卷积网络的术语中,卷积的第一个参数 $f$ 通常叫做输入(input),第二个参数 $g$ 叫做核函数(kernel function)。输出有时被称为特征映射(feature map)。在机器学习的应用中,输入通常是多维数组的数据,而核通常是由学习算法优化得到的多维数组的参数。我们把这些多维数组叫做张量。因为在输入与核中的每一个元素都必须明确地分开存储,我们通常假设在存储了数值的有限点集以外,这些函数的值都为 0。这意味着在实际操作中,我们可以通过对有限个数组元素的求和来实现无限求和。
|
||||
|
||||
## CNN 中卷积计算
|
||||
## CNN 卷积计算
|
||||
|
||||
当我们在神经网络的上下文中讨论卷积时,通常不是特指数学文献中所使用的那种标准的离散卷积运算。当提到神经网络中的卷积时,通常是指由多个并行卷积组成的计算。这是因为,虽然具有单个核的卷积可以作用在多个空间位置上,但它只能提取一种类型的特征。通常,我们希望网络的每一层能够在多个位置提取多种类型的特征。当处理图像时,我们通常把卷积的输入输出看作 3 维的张量$$[C,W,H]=[[·]_{W×H},[·]_{W×H},[·]_{W×H}]$$,其中一个索引$$C$$用于表明不同的通道(比如 RGB 三通道$$[R_{m×n},G_{m×n},B_{m×n}]$$),另外两个索引$$W,H$$标明在每个通道的空间坐标。软件实现通常使用批处理模式,所以实际上会使用 4 维的张量$$[N,C,W,H]$$,第 4 维索引$$N$$用于标明批处理中的不同实例。
|
||||
当我们在神经网络的上下文中讨论卷积时,通常不是特指数学文献中所使用的那种标准的离散卷积运算。当提到神经网络中的卷积时,通常是指由多个并行卷积组成的计算。这是因为,虽然具有单个核的卷积可以作用在多个空间位置上,但它只能提取一种类型的特征。通常,我们希望网络的每一层能够在多个位置提取多种类型的特征。当处理图像时,我们通常把卷积的输入输出看作 3 维的张量 $[C,W,H]=[[·]_{W×H},[·]_{W×H},[·]_{W×H}]$,其中一个索引 $C$ 用于表明不同的通道(比如 RGB 三通道 $[R_{m×n},G_{m×n},B_{m×n}]$),另外两个索引 $W,H$ 标明在每个通道的空间坐标。软件实现通常使用批处理模式,所以实际上会使用 4 维的张量 $[N,C,W,H]$,第 4 维索引 $N$ 用于标明批处理中的不同实例。
|
||||
|
||||
卷积神经网络(Convolutional Neural Networks,CNN)主要由卷积层、池化层和全连接层三个部分构成。其中,卷积层是卷积神经网络的核心部分,它通过对输入图像进行卷积操作来提取图像的特征。卷积层的输入通常是一个多通道的(例如多通道图像),每个通道代表一个特征,卷积层的输出也是多通道的,其中每个通道表示一个不同的特征。池化层用于降低特征图的空间分辨率,并增强模型对输入图像的平移不变性和鲁棒性。全连接层通常用于将卷积层和池化层提取的特征进行分类或回归。它的输入是一维向量,其输出的维度与任务的分类数或回归值的维度相同。
|
||||
卷积神经网络主要由卷积层、池化层和全连接层三个部分构成。其中,卷积层是卷积神经网络的核心部分,它通过对输入图像进行卷积操作来提取图像的特征。卷积层的输入通常是一个多通道的(例如多通道图像),每个通道代表一个特征,卷积层的输出也是多通道的,其中每个通道表示一个不同的特征。池化层用于降低特征图的空间分辨率,并增强模型对输入图像的平移不变性和鲁棒性。全连接层通常用于将卷积层和池化层提取的特征进行分类或回归。它的输入是一维向量,其输出的维度与任务的分类数或回归值的维度相同。
|
||||
|
||||
如下图所示, 神经网络中的卷积计算过程可描述为:$$3 * 3$$ 的卷积核在$$ 8 * 8 $$的图像上进行滑动,每次滑动时,都把卷积核和对应位置的元素进行相乘再求和。青色区域为其感受野。
|
||||
如下图所示, 神经网络中的卷积计算过程可描述为:$3 * 3$ 的卷积核在$8 * 8$ 的图像上进行滑动,每次滑动时,都把卷积核和对应位置的元素进行相乘再求和。青色区域为其感受野。
|
||||
|
||||

|
||||
|
||||
@ -184,32 +185,33 @@ $$
|
||||
|
||||
**填充(Padding)**:防止图像边缘信息丢失,在输入图像的周围添加额外的行/列,通常用“0”来进行填充。其作用为使卷积后图像分辨率不变,方便计算特征图尺寸的变化,弥补边界。
|
||||
|
||||
填充背后的数学原理是这样的,如果我们有一个$$n×n$$的图像,用$$k×k$$的卷积核做卷积,那么输出的大小就是$$(n-k+1)×(n-k+1)$$。这样的话会有两个缺点,第一个缺点是每次做卷积操作,图像就会缩小,在经过多层卷积后,得到的图像就会非常小;第二个缺点是在角落或者边缘区域的像素点在输出中采用较少,卷积核遍历时只经过一次,而其他区域的像素点可能会计算多次。针对以上两个问题,我们采用的方法就是填充。假设填充的行/列数为$$p$$,因为我们在周围都填充了一个像素点,输出也就变成了$$(n+2p-k+1)×(n+2p-k+1)$$。
|
||||
填充背后的数学原理是这样的,如果我们有一个 $n×n$ 的图像,用 $k×k$ 的卷积核做卷积,那么输出的大小就是 $(n-k+1)×(n-k+1)$。这样的话会有两个缺点,第一个缺点是每次做卷积操作,图像就会缩小,在经过多层卷积后,得到的图像就会非常小;第二个缺点是在角落或者边缘区域的像素点在输出中采用较少,卷积核遍历时只经过一次,而其他区域的像素点可能会计算多次。针对以上两个问题,我们采用的方法就是填充。假设填充的行/列数为 $p$,因为我们在周围都填充了一个像素点,输出也就变成了 $(n+2p-k+1)×(n+2p-k+1)$。
|
||||
|
||||
Padding 通常有 3 种方法:Valid 方式、Same 方式和自定义 Padding
|
||||
Padding 通常有 3 种方法:Valid 方式、Same 方式和自定义 Padding。
|
||||
|
||||
**Valid 方式**:
|
||||
|
||||
Valid 意为不填充,这样的话,输入为$$n×n$$的图像,用$$k×k$$的卷积核卷积,最终得到$$(n-k+1)×(n-k+1)$$的输出。
|
||||
Valid 意为不填充,这样的话,输入为 $n×n$ 的图像,用 $k×k$ 的卷积核卷积,最终得到 $(n-k+1)×(n-k+1)$ 的输出。
|
||||
|
||||
**Same 方式**:
|
||||
|
||||
Same 意为填充后输出大小和输入大小一致。根据原始输入计算得到的输出尺寸$$n-k+1$$,填充$$p$$行/列后,公式变为$$n+2p-k+1$$。令$$n+2p-k+1=n$$,使得输出和输入大小相等,解得$$p=(k-1)/2$$。这就产生了两种情况。若$$k$$为奇数,可以直接根据公式计算得到$$p$$;若$$k$$为偶数,则只能进行不对称填充(比如左边填充多一点,右边填充少一点)以保证输出尺寸不变。
|
||||
Same 意为填充后输出大小和输入大小一致。根据原始输入计算得到的输出尺寸 $n-k+1$,填充 $p$ 行/列后,公式变为 $n+2p-k+1$。令 $n+2p-k+1=n$,使得输出和输入大小相等,解得 $p=(k-1)/2$。这就产生了两种情况。若 $k$ 为奇数,可以直接根据公式计算得到 $p$;若 $k$ 为偶数,则只能进行不对称填充(比如左边填充多一点,右边填充少一点)以保证输出尺寸不变。
|
||||
|
||||
**自定义方式**:
|
||||
|
||||
自定义意为填充自定义的行/列数。定义$$w$$为图的宽,$$h$$为图的高,其生成的特征图大小的计算公式为:
|
||||
自定义意为填充自定义的行/列数。定义 $w$ 为图的宽,$h$ 为图的高,其生成的特征图大小的计算公式为:
|
||||
|
||||
$$
|
||||
F_{out}^{h}=\left[\frac{F_{in_h}-k_{h}+2 p_{h} }s\right]+1
|
||||
$$
|
||||
|
||||
$$
|
||||
F_{out}^{w}=\left[\frac{F_{in_w}-k_{w}+2 p_{w} }s\right]+1
|
||||
$$
|
||||
|
||||
**步长(Stride)**:步长是指卷积核在每一次卷积操作中滑动的距离。步长的大小可以影响输出数据的大小,也可以影响特征提取能力和计算复杂度。当步长增大时,输出数据的尺寸会减小,特征提取能力会变弱,但计算速度会加快。
|
||||
|
||||
我们可以把 Stride 的过程看作对全卷积函数输出的下采样,如果想在输出的每个方向上每隔$$s$$个像素进行采样,或者说在图像中卷积核的滑动距离为$$s$$,那么这个过程可用公式描述为:
|
||||
我们可以把 Stride 的过程看作对全卷积函数输出的下采样,如果想在输出的每个方向上每隔 $s$ 个像素进行采样,或者说在图像中卷积核的滑动距离为 $s$,那么这个过程可用公式描述为:
|
||||
|
||||
$$
|
||||
S(i,j)=(K^{*}I)(i,j)=\sum_{m}\sum_{n}I((i-1)×s+m,(j-1)×s+n)K(m,n)
|
||||
@ -223,7 +225,7 @@ $$
|
||||
|
||||
其中:S 为卷积的输出,I 为卷积输入,K 为卷积核的尺寸。
|
||||
|
||||
### 简单的卷积过程
|
||||
### 朴素卷积过程
|
||||
|
||||
为了更好地理解后续的示例,现将卷积神经网络 CNN 的每层的相关参数定义为:
|
||||
|
||||
@ -235,11 +237,11 @@ $$
|
||||
> P:图像边扩充大小;
|
||||
> S:滑动步长。
|
||||
|
||||
定义$$P=0,S=1$$,以$$ N=6$$个卷积核对一张$$W=5,H=5,C=1$$的图片进行卷积的过程为例,其经过的步骤为:
|
||||
定义 $P=0,S=1$,以 $N=6$ 个卷积核对一张 $W=5,H=5,C=1$ 的图片进行卷积的过程为例,其经过的步骤为:
|
||||
|
||||
1. 一个卷积核覆盖的$$ K×K=3×3 $$的区域,对应位置的数据相乘后相加。
|
||||
1. 一个卷积核覆盖的 $K×K=3×3$ 的区域,对应位置的数据相乘后相加。
|
||||
|
||||
2. 每个卷积核均对 1 所述区域做乘加操作,并在不同通道(Channel)对应位置相加(本例中每个卷积核的通道数$$C=1$$),得到的结果为特征图上相应位置的数值。
|
||||
2. 每个卷积核均对 1 所述区域做乘加操作,并在不同通道(Channel)对应位置相加(本例中每个卷积核的通道数$C=1$),得到的结果为特征图上相应位置的数值。
|
||||
|
||||
$$
|
||||
f_{out}(i,j)=\sum_{C=0}^{1}\sum_{m=0}^{3}\sum_{n=0}^{3}I(i+m,j+n)K(m,n,C)
|
||||
@ -249,7 +251,7 @@ $$
|
||||
|
||||

|
||||
|
||||
3. 每个卷积核在图像上从左到右,从上到下滑动,依次计算特征图中的每一个像素点。根据特征图大小的计算公式,可知$$W_{f_{out}}=H_{f_{out}}=3$$;本例中有$$N=6$$个卷积核,输出 6 张特征图。
|
||||
3. 每个卷积核在图像上从左到右,从上到下滑动,依次计算特征图中的每一个像素点。根据特征图大小的计算公式,可知 $W_{f_{out}}=H_{f_{out}}=3$;本例中有 $N=6$ 个卷积核,输出 6 张特征图。
|
||||
|
||||
$$
|
||||
f_{out}^{l}(i,j)
|
||||
@ -261,30 +263,31 @@ $$
|
||||
|
||||

|
||||
|
||||
每滑动一次,计算得到第$$ l $$个特征图上的一个像素点,如上图所示。其滑动的总次数即为特征图的像素点数量。
|
||||
每滑动一次,计算得到第 $l$ 个特征图上的一个像素点,如上图所示。其滑动的总次数即为特征图的像素点数量。
|
||||
|
||||
若有多个通道(假设$$C=3$$),则每个通道的$$(i.j)$$位置的值对应相加得到最终结果:
|
||||
若有多个通道(假设 $C=3$),则每个通道的 $(i.j)$ 位置的值对应相加得到最终结果:
|
||||
|
||||
$$
|
||||
f_{out}^{l}(i,j)=f_{out}^{l}(i,j)_{C1}+f_{out}^{l}(i,j)_{C2}+f_{out}^{l}(i,j)_{C3}
|
||||
$$
|
||||
|
||||
在卷积神经网络的层与层之间进行计算的时候,在 1,2 步骤之后,往往需要加偏置量$$b$$ ,以打破卷积神经网络的平移不变性,增强神经网络的拟合能力:
|
||||
在卷积神经网络的层与层之间进行计算的时候,在 1,2 步骤之后,往往需要加偏置量$b$ ,以打破卷积神经网络的平移不变性,增强神经网络的拟合能力:
|
||||
|
||||
$$
|
||||
f_{out}^{l}(i,j)=f_{out}^{l}(i,j)_{C1}+f_{out}^{l}(i,j)_{C2}+f_{out}^{l}(i,j)_{C3}+b
|
||||
$$
|
||||
|
||||

|
||||
|
||||
在卷积操作中卷积核是可学习的参数,其参数的更新由梯度下降算法确定。经过上面的介绍,可知每层卷积的参数量为$$C×K×K×N$$。卷积层的参数较少,这也是由卷积层的**局部连接**和**共享权重**特性所决定。
|
||||
在卷积操作中卷积核是可学习的参数,其参数的更新由梯度下降算法确定。经过上面的介绍,可知每层卷积的参数量为 $C×K×K×N$。卷积层的参数较少,这也是由卷积层的**局部连接**和**共享权重**特性所决定。
|
||||
|
||||
**局部连接**:每个神经元仅与输入神经元的一块区域连接,这块局部区域称作感受野(receptive field)。在图像卷积操作中,即神经元在空间维度(spatial dimension,即在图像平面滑动区域)是局部连接,但在深度(通道方面的计算)上是全部连接。这种局部连接保证了学习后的卷积核能够对于局部的输入特征有最强的响应。
|
||||
|
||||
**权重共享**:计算同一个输出特征图时采用的卷积核是共享的,即一个卷积核在输入图像上滑动,产生一张特征图。该特征图的每个像素点都是由上述卷积核在输入图像上滑动卷积计算产生。这样可以很大程度上减少参数。在卷积层,通常采用多个卷积核提取不同特征,单个卷积核的不同通道之间权重不共享(比如 RGB 有三通道,每个通道的权重参数相互独立)。另外,偏置参数对同一个卷积核的各个参数共享。
|
||||
|
||||
### 在内存中的计算复杂度分析
|
||||
### 计算复杂度分析
|
||||
|
||||
#### 时间复杂度
|
||||
1. 时间复杂度
|
||||
|
||||
CNN 的时间复杂度主要取决于卷积层的计算量。对于单个卷积层,其时间复杂度可以表示为
|
||||
|
||||
@ -292,17 +295,18 @@ $$
|
||||
O(f_{in}^{2}× C_{in}× C_{out} × K^{2})
|
||||
$$
|
||||
|
||||
其中$$f_{in}$$是输入特征图的尺寸,$$C_{in}$$和$$C_{out}$$分别是输入和输出通道数,$$K$$是卷积核的边长。这个公式表明,时间复杂度由与输入特征图的大小、输入通道数、输出通道数以及卷积核的大小完全确定。
|
||||
其中 $f_{in}$ 是输入特征图的尺寸,$C_{in}$ 和 $C_{out}$ 分别是输入和输出通道数,$K$ 是卷积核的边长。这个公式表明,时间复杂度由与输入特征图的大小、输入通道数、输出通道数以及卷积核的大小完全确定。
|
||||
|
||||
对于整个 CNN,时间复杂度是所有卷积层时间复杂度的累加。因此,减少卷积层的数量或降低每个卷积层的计算量都可以有效降低 CNN 的时间复杂度。例如,可以通过使用更小的卷积核、减少卷积层的通道数或采用更高效的卷积算法来优化 CNN 的性能。
|
||||
|
||||
在本章的后续小节会为大家介绍卷积的优化算法。
|
||||
|
||||
#### 空间复杂度
|
||||
2. 空间复杂度
|
||||
|
||||
空间复杂度(访存量),严格来讲包括两部分:总参数量 + 各层输出特征图。
|
||||
|
||||
- 参数量:模型所有带参数的层的权重参数总量(即模型体积,下式第一个求和表达式,其中$$C_{l}$$为本层的输出通道数,对于第$$l$$个卷积层来说,本层的$$C_{in}$$就是上一层的输出通道数$$C_{l-1}$$,$$D$$为总的卷积层数)
|
||||
- 参数量:模型所有带参数的层的权重参数总量(即模型体积,下式第一个求和表达式,其中 $C_{l}$ 为本层的输出通道数,对于第 $l$ 个卷积层来说,本层的 $C_{in}$ 就是上一层的输出通道数 $C_{l-1}$,$D$ 为总的卷积层数)
|
||||
|
||||
- 特征图:模型在实时运行过程中每层所计算出的输出特征图大小(下式第二个求和表达式)
|
||||
|
||||
$$
|
||||
@ -373,8 +377,7 @@ def conv(inputs, kernel, stride, mode="SAME"):
|
||||
|
||||
### Tensor 运算
|
||||
|
||||
|
||||
张量(英文 Tensor)是标量、矢量、矩阵等概念的总称与拓展,是机器学习领域的基础数据结构。程序中的张量是一个多维数组的数据结构。
|
||||
张量(Tensor)是标量、矢量、矩阵等概念的总称与拓展,是机器学习领域的基础数据结构。程序中的张量是一个多维数组的数据结构。
|
||||
|
||||
```
|
||||
#define MAX_DIM 6
|
||||
@ -453,12 +456,6 @@ for (int oh = 0; oh < OH; oh++) {
|
||||
|
||||
本篇介绍了卷积计算的数学原理及其在 CNN 的应用过程。可以观察到,当卷积核在图像上滑动的时候,可训练参数量较少,但产生的连接计算量庞大,且部分参数在不同连接中进行了重复计算,造成了算力资源的浪费。为解决此问题,诸多研究者了各种各样的卷积优化算法,该部分将于后续文章进行详细介绍。
|
||||
|
||||
## 参考文献
|
||||
|
||||
- [Lecun Y , Bottou L .Gradient-based learning applied to document recognition[J].Proceedings of the IEEE, 1998, 86(11):2278-2324.DOI:10.1109/5.726791.](https://ieeexplore.ieee.org/document/726791)
|
||||
- [Fukushima, Kunihiko and Sei Miyake. “Neocognitron: A Self-Organizing Neural Network Model for a Mechanism of Visual Pattern Recognition.” (1982).](https://www.semanticscholar.org/paper/Neocognitron%3A-A-Self-Organizing-Neural-Network-for-Fukushima-Miyake/9b2541b8d8ca872149b4dabd2ccdc0cacc46ebf5)
|
||||
- [ Bouvrie J .Notes on Convolutional Neural Networks[J].neural nets, 2006.](https://www.semanticscholar.org/paper/Notes-on-Convolutional-Neural-Networks-Bouvrie/2a4393aa1bc3cb7fe2deecc88720bfb84dabb263)
|
||||
- [Krizhevsky A , Sutskever I , Hinton G .ImageNet Classification with Deep Convolutional Neural Networks[J].Advances in neural information processing systems, 2012, 25(2).DOI:10.1145/3065386.](https://dl.acm.org/doi/10.1145/3065386)
|
||||
|
||||
## 本节视频
|
||||
|
||||
@ -466,3 +463,10 @@ for (int oh = 0; oh < OH; oh++) {
|
||||
<iframe src="https://www.bilibili.com/video/BV1No4y1e7KX/?spm_id_from=333.337.search-card.all.click&vd_source=096daa038c279ccda6e4f8c5eea82de7" width="100%" height="500" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe>
|
||||
</html>
|
||||
|
||||
## 参考文献
|
||||
|
||||
- [Lecun Y , Bottou L .Gradient-based learning applied to document recognition[J].Proceedings of the IEEE, 1998, 86(11):2278-2324.DOI:10.1109/5.726791.](https://ieeexplore.ieee.org/document/726791)
|
||||
- [Fukushima, Kunihiko and Sei Miyake. “Neocognitron: A Self-Organizing Neural Network Model for a Mechanism of Visual Pattern Recognition.” (1982).](https://www.semanticscholar.org/paper/Neocognitron%3A-A-Self-Organizing-Neural-Network-for-Fukushima-Miyake/9b2541b8d8ca872149b4dabd2ccdc0cacc46ebf5)
|
||||
- [ Bouvrie J .Notes on Convolutional Neural Networks[J].neural nets, 2006.](https://www.semanticscholar.org/paper/Notes-on-Convolutional-Neural-Networks-Bouvrie/2a4393aa1bc3cb7fe2deecc88720bfb84dabb263)
|
||||
- [Krizhevsky A , Sutskever I , Hinton G .ImageNet Classification with Deep Convolutional Neural Networks[J].Advances in neural information processing systems, 2012, 25(2).DOI:10.1145/3065386.](https://dl.acm.org/doi/10.1145/3065386)
|
||||
|
||||
|
@ -1,18 +1,19 @@
|
||||
# Im2Col算法
|
||||
|
||||
作为早期的深度学习框架,Caffe 中卷积的实现采用的是基于 Im2col 的方法,至今仍是卷积重要的优化方法之一。
|
||||
作为早期的深度学习框架,Caffe 中卷积的实现采用的是基于 Im2Col 的方法,至今仍是卷积重要的优化方法之一。
|
||||
|
||||
从上一节的介绍中可以看到,在CNN中卷积直接计算的定义中,卷积核在输入图片上滑动,对应位置的元素相乘后相加求和,滑窗的大小由卷积核决定。由于滑动操作时的窗口的数据横向是连续的,但是不同行在内存中是不连续的,在计算时有可能需要多次访问内存。由于多次访问内存直接增加了数据传输时间,从而进一步影响了卷积计算速度,这样就造成了整体效率低等问题。
|
||||
|
||||
Im2col 是计算机视觉领域中将图片转换成矩阵的矩阵列(column)的计算过程。Img2col 的作用就是将卷积通过矩阵乘法来计算,从而能在计算过程中将需要计算的特征子矩阵存放在连续的内存中,有利于一次将所需要计算的数据直接按照需要的格式取出进行计算,这样便减少了内存访问的次数,从而减小了计算的整体时间。
|
||||
Im2Col 是计算机视觉领域中将图片转换成矩阵的矩阵列(column)的计算过程。Img2col 的作用就是将卷积通过矩阵乘法来计算,从而能在计算过程中将需要计算的特征子矩阵存放在连续的内存中,有利于一次将所需要计算的数据直接按照需要的格式取出进行计算,这样便减少了内存访问的次数,从而减小了计算的整体时间。
|
||||
|
||||
在深度学习框架发展的早期,Caffe 使用 Im2col 方法将三维张量转换为二维矩阵,从而充分利用已经优化好的 GEMM 库来为各个平台加速卷积计算。最后,再将矩阵乘得到的二维矩阵结果使用 Col2im 将转换为三维矩阵输出。其处理流程如下图所示。
|
||||
在深度学习框架发展的早期,Caffe 使用 Im2Col 方法将三维张量转换为二维矩阵,从而充分利用已经优化好的 GEMM 库来为各个平台加速卷积计算。最后,再将矩阵乘得到的二维矩阵结果使用 Col2im 将转换为三维矩阵输出。其处理流程如下图所示。
|
||||
|
||||

|
||||

|
||||
|
||||
## 数学原理
|
||||
|
||||
Im2col算法的优化策略为用空间换时间,用连续的行向量的存储空间作为代价优化潜在的内存访问消耗的时间。其实施过程依据的是线性代数中最基本的矩阵运算的原理,根据上一节的特征图计算公式可得:
|
||||
Im2Col算法的优化策略为用空间换时间,用连续的行向量的存储空间作为代价优化潜在的内存访问消耗的时间。其实施过程依据的是线性代数中最基本的矩阵运算的原理,根据上一节的特征图计算公式可得:
|
||||
|
||||
$$
|
||||
\begin{aligned}
|
||||
f_{out}(i,j)&=\sum_{C=0}^{k_{C}}\sum_{m=0}^{3}\sum_{n=0}^{3}I(i+m,j+n)K(m,n,C)\\
|
||||
@ -22,161 +23,177 @@ f_{out}(i,j)&=\sum_{C=0}^{k_{C}}\sum_{m=0}^{3}\sum_{n=0}^{3}I(i+m,j+n)K(m,n,C)\\
|
||||
&= [K(0,0,0),…,K(2,2,k_{C})]_{1×9×k_{C}}[I(i+0,j+0),…,I(i+2,j+2)]_{1×9×k_{C}}^{T}\\
|
||||
\end{aligned}
|
||||
$$
|
||||
|
||||
根据上述式子可知,每个窗口下对应的卷积计算和两个一维向量的点乘计算是等价的。由此可以推知,在未改变直接卷积计算的参数量和连接数的情况下,这种将每个窗口中的特征子矩阵展开成一维的行向量后再进行矩阵乘计算的思路,能够通过减少计算过程中的访存需求,优化整体的计算时间。
|
||||
|
||||

|
||||

|
||||
|
||||
Im2col算法就是在这样的基础上进行设计的。其将卷积通过矩阵乘法来计算,最后调用高性能的 Matmul (矩阵乘法)进行计算。该方法适应性强,支持各种卷积参数的优化,在通道数稍大的卷积中性能基本与 Matmul 持平,并且可以与其他优化方法形成互补。
|
||||
Im2Col算法就是在这样的基础上进行设计的。其将卷积通过矩阵乘法来计算,最后调用高性能的 Matmul (矩阵乘法)进行计算。该方法适应性强,支持各种卷积参数的优化,在通道数稍大的卷积中性能基本与 Matmul 持平,并且可以与其他优化方法形成互补。
|
||||
|
||||
## 算法过程
|
||||
|
||||
>除非特别说明,本文默认采用的内存布局形式为 NHWC 。其他的内存布局和具体的转换后的矩阵形状或许略有差异,但不影响算法本身的描述。
|
||||
> 除非特别说明,本文默认采用的内存布局形式为 NHWC。其他的内存布局和具体的转换后的矩阵形状或许略有差异,但不影响算法本身的描述。
|
||||
|
||||
Im2col+Matmul 方法主要包括两个步骤:
|
||||
1) 使用 Im2col 将输入矩阵展开一个大矩阵,矩阵每一列表示卷积核需要的一个输入数据,按行向量方式存储。
|
||||
Im2Col+Matmul 方法主要包括两个步骤:
|
||||
|
||||

|
||||
1. 使用 Im2Col 将输入矩阵展开一个大矩阵,矩阵每一列表示卷积核需要的一个输入数据,按行向量方式存储。
|
||||
|
||||
2) 使用上面转换的矩阵进行 Matmul 运算,得到的数据就是最终卷积计算的结果。
|
||||

|
||||
|
||||

|
||||
2. 使用上面转换的矩阵进行 Matmul 运算,得到的数据就是最终卷积计算的结果。
|
||||
|
||||
### 卷积通用过程
|
||||

|
||||
|
||||
一般图像的三通道卷积,其输入为3维张量$$(H, W, 3)$$,其中$$H$$,$$W$$为输入图像的高和宽,3为图像的通道数;卷积核为4维张量$$(N, C, KH, KW)$$,其中$$N$$为卷积核的个数,$$KH$$,$$KW$$为卷积核的高和宽,$$C$$为卷积核的通道数,卷积核的通道数应与输入图像的通道数一致;输出为3维张量$$(N, H, W)$$,其中$$H$$,$$W$$为输入图像的高和宽,$$N$$为输出图像的通道数,输出图的通道数应与卷积核个数一致。此段中$$H,W$$只是代指,并不表示数值通用,输出图像的宽高具体数值需要按照公式另行计算。其卷积的一般计算方式为:
|
||||
### 卷积过程
|
||||
|
||||

|
||||
一般图像的三通道卷积,其输入为3维张量 $(H, W, 3)$,其中 $H$,$W$ 为输入图像的高和宽,3为图像的通道数;卷积核为4维张量 $(N, C, KH, KW)$,其中 $N$ 为卷积核的个数,$KH$,$KW$ 为卷积核的高和宽,$C$ 为卷积核的通道数,卷积核的通道数应与输入图像的通道数一致;输出为3维张量 $(N, H, W)$,其中 $H$,$W$ 为输入图像的高和宽,$N$ 为输出图像的通道数,输出图的通道数应与卷积核个数一致。此段中 $H,W$ 只是代指,并不表示数值通用,输出图像的宽高具体数值需要按照公式另行计算。其卷积的一般计算方式为:
|
||||
|
||||
在神经网络中,卷积默认采用数据排布方式为$$NHWC$$,意为(样本数,高,宽,通道数)。输入图像/特征图为4维张量$$(N,IH,IW,IC)$$,其中$$N$$为输入图像的个数,也可以理解为单次训练的样本数,$$IH$$,$$IW$$为输入图像的高和宽,$$IC$$为通道数;卷积核为4维张量$$(OC,KH,KW,IC)$$,卷积核的通道数应与输入图像的通道数一致,所以均为$$IC$$,这里的$$OC$$应与下图中卷积核个数N在数值上对应相等,表示卷积核的个数,其遵循一个卷积核计算得到一张特征图这样一一对应的规则。注意图中的N与输入图像的个数$$N$$并不相关,数值也不一致,图中的N表示卷积核个数。输出为4维张量$$(N,OH,OW,OC)$$,这里的$$N$$等价于前述输入图像的个数,$$OC$$表示输出特征图的个数,也就是每个样本卷积后的输出的通道数。卷积的一般计算方式为:
|
||||

|
||||
|
||||

|
||||
在神经网络中,卷积默认采用数据排布方式为 $NHWC$,意为(样本数,高,宽,通道数)。输入图像/特征图为4维张量 $(N,IH,IW,IC)$,其中 $N$ 为输入图像的个数,也可以理解为单次训练的样本数,$IH$,$IW$ 为输入图像的高和宽,$IC$ 为通道数;卷积核为4维张量 $(OC,KH,KW,IC)$,卷积核的通道数应与输入图像的通道数一致,所以均为 $IC$,这里的 $OC$ 应与下图中卷积核个数N在数值上对应相等,表示卷积核的个数,其遵循一个卷积核计算得到一张特征图这样一一对应的规则。注意图中的N与输入图像的个数 $N$ 并不相关,数值也不一致,图中的N表示卷积核个数。输出为4维张量 $(N,OH,OW,OC)$,这里的 $N$ 等价于前述输入图像的个数,$OC$ 表示输出特征图的个数,也就是每个样本卷积后的输出的通道数。卷积的一般计算方式为:
|
||||
|
||||
### Im2col算法过程
|
||||

|
||||
|
||||
这个算法的核心是改变了数据在内存中的排列存储方式,将卷积操作转换为矩阵相乘,对 Kernel 和 Input 进行重新排列。将输入数据按照卷积窗进行展开并存储在矩阵的列中,多个输入通道的对应的窗展开之后将拼接成最终输出 Matrix 的一列。其过程如下图所示,卷积核被转化为一个$$N×(KW*KH*C)$$的二维矩阵,输入被转化为一个$$(KW*KH*C)×(OH*OW)$$的矩阵,输入矩阵的列数由卷积核在输入图像上的滑动次数所决定,具体数值可由特征图的尺寸$$(OH*OW)$$计算得到,这两个数值根据上一节特征图的公式进行计算。
|
||||
### Im2Col算法原理
|
||||
|
||||

|
||||
Im2Col 算法的核心是改变了数据在内存中的排列存储方式,将卷积操作转换为矩阵相乘,对 Kernel 和 Input 进行重新排列。将输入数据按照卷积窗进行展开并存储在矩阵的列中,多个输入通道的对应的窗展开之后将拼接成最终输出 Matrix 的一列。其过程如下图所示,卷积核被转化为一个 $N×(KW*KH*C)$ 的二维矩阵,输入被转化为一个 $(KW*KH*C)×(OH*OW)$ 的矩阵,输入矩阵的列数由卷积核在输入图像上的滑动次数所决定,具体数值可由特征图的尺寸 $(OH*OW)$ 计算得到,这两个数值根据上一节特征图的公式进行计算。
|
||||
|
||||
#### Input重排
|
||||

|
||||
|
||||
对 Input 进行重排,得到的矩阵见下图右侧,矩阵的行数对应输出$$ OH*OW $$个数,也就是卷积核在Input上的滑动次数;每个行向量里,先排列计算一个输出点所需要输入上第一个通道的$$ KH*KW $$个数据,根据卷积窗的大小逐行拼接成一段行向量,排完当前通道的数据后,以同样模式再按次序排列之后的通道的数据,直到第$$ IC$$个通道,最终构成前述完整的一个行向量。
|
||||
1. Input重排
|
||||
|
||||

|
||||
对 Input 进行重排,得到的矩阵见下图右侧,矩阵的行数对应输出 $OH*OW$ 个数,也就是卷积核在Input上的滑动次数;每个行向量里,先排列计算一个输出点所需要输入上第一个通道的 $KH*KW$ 个数据,根据卷积窗的大小逐行拼接成一段行向量,排完当前通道的数据后,以同样模式再按次序排列之后的通道的数据,直到第 $IC$ 个通道,最终构成前述完整的一个行向量。
|
||||
|
||||
#### 权重数据重排
|
||||

|
||||
|
||||
对权重数据进行重排,将$$ N $$ 个卷积核展开为权重矩阵的一行,因此共有$$ N $$行,每个行向量上先排列第一个输入通道上$$KH*KW $$数据,根据卷积窗的大小逐行拼接成一段行向量,排完当前通道的数据后,以同样模式再依次排列后面的通道数据直到$$ IC$$。
|
||||
2. 权重数据重排
|
||||
|
||||

|
||||
对权重数据进行重排,将 $N$ 个卷积核展开为权重矩阵的一行,因此共有 $N$ 行,每个行向量上先排列第一个输入通道上 $KH*KW$ 数据,根据卷积窗的大小逐行拼接成一段行向量,排完当前通道的数据后,以同样模式再依次排列后面的通道数据直到 $IC$。
|
||||
|
||||
通过数据重排,完成 Im2col 的操作之后会得到一个输入矩阵,卷积的 Weights 也可以转换为一个矩阵,卷积的计算就可以转换为两个矩阵相乘的求解,得到最终的卷积计算结果。
|
||||

|
||||
|
||||

|
||||
通过数据重排,完成 Im2Col 的操作之后会得到一个输入矩阵,卷积的 Weights 也可以转换为一个矩阵,卷积的计算就可以转换为两个矩阵相乘的求解,得到最终的卷积计算结果。
|
||||
|
||||
#### 推理引擎中的数据重排
|
||||

|
||||
|
||||
首先归纳一下Im2col 算法计算卷积的过程。其具体过程如下(简单起见忽略 Padding 的情况,即认为$$OH=IH,OW=IW$$):
|
||||
3. 推理引擎中的数据重排
|
||||
|
||||
1. 将输入由$$N×IH×IW×IC$$根据卷积计算特性展开成$$(OH*OW)×(N*KH*KW*IC)$$形状二维矩阵。显然,转换后使用的内存空间相比原始输入多约$$KH∗KW−1$$倍;
|
||||
2. 权重形状一般为$$OC×KH×KW×IC$$四维张量,可以将其直接作为形状为$$(OC)×(KH*KW*IC)$$的二维矩阵处理;
|
||||
3. 对于准备好的两个二维矩阵,将$$(KH*KW*IC)$$作为累加求和的维度,运行矩阵乘可以得到输出矩阵$$(OH*OW)×(OC)$$;
|
||||
4. 将输出矩阵$$(OH*OW)×(OC)$$在内存布局视角即为预期的输出张量$$N×OH×OW×OC$$,或者使用 Col2Im 算法变为下一个算子输入$$ N×OH×OW×OC$$;
|
||||
首先归纳一下Im2Col 算法计算卷积的过程。其具体过程如下(简单起见忽略 Padding 的情况,即认为 $OH=IH,OW=IW$):
|
||||
|
||||
- 将输入由 $N×IH×IW×IC$ 根据卷积计算特性展开成 $(OH*OW)×(N*KH*KW*IC)$ 形状二维矩阵。显然,转换后使用的内存空间相比原始输入多约 $KH∗KW−1$ 倍;
|
||||
|
||||
- 权重形状一般为 $OC×KH×KW×IC$ 四维张量,可以将其直接作为形状为 $(OC)×(KH*KW*IC)$ 的二维矩阵处理;
|
||||
|
||||
- 对于准备好的两个二维矩阵,将 $(KH*KW*IC)$ 作为累加求和的维度,运行矩阵乘可以得到输出矩阵 $(OH*OW)×(OC)$;
|
||||
|
||||
- 将输出矩阵 $(OH*OW)×(OC)$ 在内存布局视角即为预期的输出张量 $N×OH×OW×OC$,或者使用 Col2Im 算法变为下一个算子输入 $N×OH×OW×OC$;
|
||||
|
||||
在权重数据的重排过程中,以上四个阶段在推理引擎中的执行方式和执行模块不一定在同一个阶段进行。其中1,3,4可能会在Kernel层执行,但2可能会在预编译阶段或者离线转换优化模块去执行。
|
||||
而在Input数据的重排则会在正式计算时感知到数据流后进行。总的来说,不同的推理引擎在应用Im2col算法时,输入数据的重排通常发生在以下阶段:
|
||||
|
||||
1. **模型转换或图优化阶段**: 在这个阶段,推理引擎可能会分析模型的卷积层,并决定是否应用Im2col算法。如果使用,引擎会相应地调整模型的结构,以便在执行卷积时进行数据重排。例如,TensorRT在构建优化图时,会考虑是否将卷积层转换为im2col形式。
|
||||
2. **推理初始化阶段**: 在执行推理之前,推理引擎会进行初始化,这可能就包括为Im2col操作分配必要的内存空间,并准备执行数据重排的代码路径。
|
||||
3. **预处理阶段**: 在实际执行推理之前,输入数据需要经过预处理,以满足模型的输入要求。这可能包括缩放、归一化和其他数据转换。在某些情况下,im2col的重排也可以看作是预处理的一部分,虽然它与卷积操作更相关。
|
||||
4. **卷积层的前向传播阶段**: 在执行卷积层的前向传播时,如果使用了im2col算法,推理引擎会在这一阶段对输入数据进行重排。即在卷积操作之前,输入特征图会被转换为一个二维矩阵,其中每一行对应于卷积核在输入特征图上的一个位置。这个重排操作是im2col算法的核心部分。
|
||||
5. **后处理阶段**: 在卷积操作完成后,如果需要,推理引擎可能会将数据从im2col格式转换回原始格式。这通常是在卷积层的输出被进一步处理或传递到下一个网络层之前完成的。
|
||||
而在Input数据的重排则会在正式计算时感知到数据流后进行。总的来说,不同的推理引擎在应用Im2Col算法时,输入数据的重排通常发生在以下阶段:
|
||||
|
||||
此外,不同的深度学习框架对于im2col的实现可能有所不同,但核心思想是一致的。以下是几个流行的深度学习框架对im2col输入数据重排的设计:
|
||||
- **模型转换或图优化阶段**: 在这个阶段,推理引擎可能会分析模型的卷积层,并决定是否应用Im2Col算法。如果使用,引擎会相应地调整模型的结构,以便在执行卷积时进行数据重排。例如,TensorRT在构建优化图时,会考虑是否将卷积层转换为Im2Col形式。
|
||||
|
||||
1. **TensorFlow**: TensorFlow中并没有直接叫做im2col的函数,但是可以使用` tf.extract_image_patches `来实现类似的功能。这个函数可以从输入张量中提取图像块,并按照指定的步幅和大小输出这些块,形成一个新的张量,这个张量就可以看作是im2col操作的结果。或者在执行阶段通过Session.run来调用。
|
||||
2. **PyTorch**: PyTorch提供了一个名为`torch.nn.Unfold`的模块,它可以实现im2col操作。Unfold模块将输入张量(通常是特征图)转换为一个二维张量,其中每一行对应于原始特征图中的一个滑动窗口位置。这个操作通常用于卷积层的正向传播中。
|
||||
3. **Caffe**: Caffe是较早的深度学习框架之一,它直接在内部实现了im2col操作。在Caffe中,卷积层在计算时会自动将输入数据转换为im2col格式,然后使用BLAS(Basic Linear Algebra Subprograms)来进行高效的矩阵乘法。
|
||||
4. **MXNet**: MXNet的im2col操作可以通过`nd.contrib.Im2col`来实现。这个操作将输入数据重排成一个二维矩阵,使得后续的卷积操作可以表示为矩阵乘法。
|
||||
5. **Chainer**: Chainer的`links.Convolution2D`层在内部使用了im2col来优化卷积运算。它会自动将输入特征图转换为col格式,然后应用权重和偏置,最后将结果转换回图像格式。
|
||||
- **推理初始化阶段**: 在执行推理之前,推理引擎会进行初始化,这可能就包括为Im2Col操作分配必要的内存空间,并准备执行数据重排的代码路径。
|
||||
|
||||
在深度学习框架中,Im2col通常是为了优化卷积操作而设计的,它通过将多次卷积操作转换为一次大矩阵乘法,从而可以利用现有的高性能线性代数库来加速计算。随着深度学习框架的发展,很多框架也实现了更加高效的卷积算法,比如Winograd算法或者直接使用cuDNN等专门的卷积计算库,这些库内部可能对im2col操作进行了进一步的优化。
|
||||
- **预处理阶段**: 在实际执行推理之前,输入数据需要经过预处理,以满足模型的输入要求。这可能包括缩放、归一化和其他数据转换。在某些情况下,Im2Col的重排也可以看作是预处理的一部分,虽然它与卷积操作更相关。
|
||||
|
||||
## Im2col 算法要点总结
|
||||
- **卷积层的前向传播阶段**: 在执行卷积层的前向传播时,如果使用了Im2Col算法,推理引擎会在这一阶段对输入数据进行重排。即在卷积操作之前,输入特征图会被转换为一个二维矩阵,其中每一行对应于卷积核在输入特征图上的一个位置。这个重排操作是Im2Col算法的核心部分。
|
||||
|
||||
- **后处理阶段**: 在卷积操作完成后,如果需要,推理引擎可能会将数据从Im2Col格式转换回原始格式。这通常是在卷积层的输出被进一步处理或传递到下一个网络层之前完成的。
|
||||
|
||||
在深度学习框架中,Im2Col通常是为了优化卷积操作而设计的,它通过将多次卷积操作转换为一次大矩阵乘法,从而可以利用现有的高性能线性代数库来加速计算。随着深度学习框架的发展,很多框架也实现了更加高效的卷积算法,比如Winograd算法或者直接使用cuDNN等专门的卷积计算库,这些库内部可能对Im2Col操作进行了进一步的优化。
|
||||
|
||||
### Im2Col算法总结
|
||||
|
||||
1. Im2Col 计算卷积使用 GEMM库的代价是额外的内存开销。使用 Im2Col 将三维张量展开成二维矩阵时,原本可以复用的数据平坦地分布到矩阵中,将输入数据复制了 $KH∗KW−1$ 份。
|
||||
|
||||
1. Im2col 计算卷积使用 GEMM库的代价是额外的内存开销。使用 Im2col 将三维张量展开成二维矩阵时,原本可以复用的数据平坦地分布到矩阵中,将输入数据复制了$$KH∗KW−1$$份。
|
||||
2. 转化成矩阵后,可以在连续内存和缓存上操作,而且有很多库提供了高效的实现方法(BLAS、MKL),Numpy 内部基于 MKL 实现运算的加速。
|
||||
3. 在实际实现时,离线转换模块实现的时候可以预先对权重数据执行 Im2col 操作,而Input 数据的Im2col和GEMM的数据重排会同时进行,以节省运行时间。
|
||||
|
||||
# 空间组合优化算法
|
||||
3. 在实际实现时,离线转换模块实现的时候可以预先对权重数据执行 Im2Col 操作,而Input 数据的 Im2Col 和 GEMM 的数据重排会同时进行,以节省运行时间。
|
||||
|
||||
Im2col 是一种比较朴素的卷积优化算法,在没有精心处理的情况下会带来较大的内存开销。空间组合(Spatial pack)是一种类似矩阵乘中重组内存的优化算法。它是指在应用Im2col算法时,通过对卷积操作中的空间数据进行特定的组合和重排,以减少计算和内存访问的复杂性,从而提高推理效率。
|
||||
## 空间组合优化算法
|
||||
|
||||
Im2Col 是一种比较朴素的卷积优化算法,在没有精心处理的情况下会带来较大的内存开销。空间组合(Spatial pack)是一种类似矩阵乘中重组内存的优化算法。它是指在应用 Im2Col 算法时,通过对卷积操作中的空间数据进行特定的组合和重排,以减少计算和内存访问的复杂性,从而提高推理效率。
|
||||
|
||||
空间组合优化算法是一种基于分治法(Divide and Conquer)的方法,基于空间特性,将卷积计算划分为若干份,分别处理。常见的空间组合优化方法有:
|
||||
|
||||
1. **分块卷积(Blocked Convolution)**: 将大卷积核分解为多个小卷积核,每个小卷积核单独计算,这样可以减少内存访问和提高缓存利用率。这种方法在处理大型图像或特征图时特别有效。
|
||||
2. **重叠数据块(Overlapping Blocks)**: 在进行im2col操作时,可以通过重叠数据块来减少边缘效应和填充(padding)的需求。这种方法可以减少计算量,但可能会增加内存访问的复杂性。
|
||||
|
||||
2. **重叠数据块(Overlapping Blocks)**: 在进行Im2Col操作时,可以通过重叠数据块来减少边缘效应和填充(padding)的需求。这种方法可以减少计算量,但可能会增加内存访问的复杂性。
|
||||
|
||||
3. **稀疏卷积(Sparse Convolution)**: 对于稀疏数据,可以通过只对非零值进行卷积来减少计算量。这种方法在处理稀疏特征图时特别有效。
|
||||
4. **权重共享(Weight Sharing)**: 在卷积操作中,同一个卷积核会在不同的位置重复使用。通过在im2col操作中利用这一点,可以减少权重数据的重复加载和存储。
|
||||
5. **张量化(Tensorization)**: 利用特定硬件(如GPU)的特定指令来优化张量操作,例如使用SIMD(单指令多数据)指令集。这种方法可以加速im2col操作中的矩阵乘法。
|
||||
6. **循环展开和软件流水线**: 这些是编译器优化技术,可以用于优化循环结构,减少循环开销和提高指令级并行性。在im2col操作中,循环展开可以减少循环迭代的开销,而软件流水线可以优化数据流和处理流程。
|
||||
7. **内存复用**: 通过复用中间计算结果所占用的内存,可以减少总的内存使用。在im2col操作中,可以复用输入和输出数据的内存空间,以减少内存分配和释放的次数。
|
||||
|
||||
这些空间组合优化方法可以单独使用,也可以组合使用,以提高im2col操作的效率。在实际应用中,选择哪种优化策略取决于具体的模型结构、硬件平台和性能目标。随着深度学习框架和硬件的发展,许多框架已经采用了更加高效的卷积实现,如直接卷积(Direct Convolution)、Winograd算法或利用专用硬件加速器,这些实现可能不再需要显式的im2col和col2im操作。
|
||||
4. **权重共享(Weight Sharing)**: 在卷积操作中,同一个卷积核会在不同的位置重复使用。通过在Im2Col操作中利用这一点,可以减少权重数据的重复加载和存储。
|
||||
|
||||
## 空间组合优化方法
|
||||
5. **张量化(Tensorization)**: 利用特定硬件(如GPU)的特定指令来优化张量操作,例如使用SIMD(单指令多数据)指令集。这种方法可以加速Im2Col操作中的矩阵乘法。
|
||||
|
||||
6. **循环展开和软件流水线**: 这些是编译器优化技术,可以用于优化循环结构,减少循环开销和提高指令级并行性。在Im2Col操作中,循环展开可以减少循环迭代的开销,而软件流水线可以优化数据流和处理流程。
|
||||
|
||||
7. **内存复用**: 通过复用中间计算结果所占用的内存,可以减少总的内存使用。在Im2Col操作中,可以复用输入和输出数据的内存空间,以减少内存分配和释放的次数。
|
||||
|
||||
这些空间组合优化方法可以单独使用,也可以组合使用,以提高Im2Col操作的效率。在实际应用中,选择哪种优化策略取决于具体的模型结构、硬件平台和性能目标。随着深度学习框架和硬件的发展,许多框架已经采用了更加高效的卷积实现,如直接卷积(Direct Convolution)、Winograd算法或利用专用硬件加速器,这些实现可能不再需要显式的Im2Col和col2im操作。
|
||||
|
||||
### 空间组合优化方法
|
||||
|
||||
以分块卷积为例,如图所示在空间上将输出、输入划分为四份:
|
||||
|
||||

|
||||

|
||||
|
||||
划分后,大卷积计算被拆分为若干个小卷积进行计算,小卷积块的大小必须与卷积核的大小相匹配。划分过程中计算总量不变,但计算小矩阵时访存局部性更好,可以借由计算机存储层次结构获得性能提升。
|
||||
|
||||

|
||||

|
||||
|
||||
在传统的卷积操作中,输入特征和卷积核的每个通道都需要参与计算,这导致内存访问模式复杂,难以优化。而分组卷积将通道分成多个组,每个组内的通道数减少,使得内存访问更加规则和局部化,有利于提高缓存利用率。此外,这种基于分治法的分解策略,有助于提高并行处理的效率。在分组卷积中,每个组内的卷积核是独立的,这意味着不同组之间的权重和激活可以共享内存空间。这种共享可以减少内存占用,尤其是在使用大量卷积核的网络结构中。
|
||||
|
||||
### 注意点
|
||||
### 算法注意点
|
||||
|
||||
值得注意的是,上文的描述中忽略了 Padding 的问题。实际将输入张量划分为若干个小张量时,除了将划分的小块中原始数据拷贝外,还需要将相邻的小张量的边界数据拷贝:
|
||||
|
||||
$$
|
||||
N\times\left(\frac{H}{h}+2 (KH-1)\right)\times\left(\frac{W}{w}+2 (KW-1)\right)\times C
|
||||
$$
|
||||
|
||||
这里的 $$2(KH−1)$$ 和 $$ 2(KW−1)$$ 遵循 Padding 规则。规则为 VALID 时,可以忽略;规则为 SAME 时,位于 Input Tensor 边界一边 Padding 补 0,不在 Input Tensor 边界 Padding 使用邻居张量值。也就是说,在真正使用这种方法的时候,可以通过重叠数据块来减少边缘效应和填充(padding)的需求。这种方法可以减少计算量,但可能会增加内存访问的复杂性。
|
||||
这里的 $2(KH−1)$ 和 $ 2(KW−1)$ 遵循 Padding 规则。规则为 VALID 时,可以忽略;规则为 SAME 时,位于 Input Tensor 边界一边 Padding 补 0,不在 Input Tensor 边界 Padding 使用邻居张量值。也就是说,在真正使用这种方法的时候,可以通过重叠数据块来减少边缘效应和填充(padding)的需求。这种方法可以减少计算量,但可能会增加内存访问的复杂性。
|
||||
|
||||

|
||||

|
||||
|
||||
### 仍存在的问题
|
||||
### 算法问题点
|
||||
|
||||
1. 实际应用中可以拆为很多份。例如可以拆成小张量边长为 4 或者 8 ,从而方便编译器向量化计算操作。随着拆分出的张量越小,Padding 引起的额外内存消耗越大,其局部性也越高,负面作用是消耗的额外内存也越多。
|
||||
|
||||
2. 对于不同规模的卷积,寻找合适的划分方法不是一件容易的事情。正如计算机领域的许多问题一样,该问题也是可以自动化的,例如通过使用 AI编译器 可以在这种情况下寻找较优的划分方法。
|
||||
|
||||
# Kernel层的优化
|
||||
## Kernel层的优化
|
||||
|
||||
推理引擎在Kernel层的优化方法和技术主要集中在CPU和GPU上,这些技术旨在提高计算效率和性能。以下分别介绍一下针对CPU和GPU的几种优化技术。
|
||||
|
||||
CPU优化技术:
|
||||
|
||||
1. **NEON**: NEON是ARM架构上的SIMD(单指令多数据)扩展,用于提高多媒体处理和浮点运算的性能。推理引擎可以利用NEON指令集来优化Kernel层,特别是在移动设备和嵌入式设备上。
|
||||
|
||||
2. **AVX**: AVX(Advanced Vector Extensions)是Intel处理器上的SIMD指令集,用于提高浮点运算和整数运算的性能。推理引擎可以利用AVX指令集来优化Kernel层,特别是在Intel CPU上。
|
||||
|
||||
3. **Metal**: Metal是苹果开发的低级图形和计算API,用于优化在Apple GPU上的性能。推理引擎可以利用Metal API来优化Kernel层,特别是在iOS和macOS设备上。
|
||||
|
||||
4. **TVM**: TVM(Tensor Virtual Machine)是一个开源的深度学习编译器框架,用于优化深度学习模型在各种硬件上的性能。它支持CPU、GPU、TPU和其他类型的硬件。
|
||||
|
||||
GPU优化技术:
|
||||
|
||||
1. **CUDA**: CUDA是NVIDIA的并行计算平台和编程模型,用于在NVIDIA GPU上执行并行计算。推理引擎可以利用CUDA来优化Kernel层,特别是在大规模矩阵运算和卷积操作方面。
|
||||
|
||||
2. **OpenCL**: OpenCL是一个开放的标准,用于编写在异构系统上运行的程序。它允许开发者利用CPU、GPU和其他类型的处理器来加速计算密集型任务。推理引擎可以利用OpenCL来优化Kernel层,特别是在GPU上。
|
||||
|
||||
3. **Vulkan**: Vulkan是新一代的图形和计算API,用于在各种GPU上执行并行计算。推理引擎可以利用Vulkan API来优化Kernel层,特别是在高性能计算和图形处理方面。
|
||||
|
||||
4. **Tensor Cores**: Tensor Cores是NVIDIA GPU上的一种特殊类型的核心,专门用于加速矩阵乘法和卷积操作。推理引擎可以利用Tensor Cores来优化Kernel层,特别是在执行大规模的矩阵运算时。
|
||||
|
||||
这些优化方法和技术可以根据具体的硬件平台和模型需求来选择和组合,以提高推理引擎在Kernel层的性能。在实际应用中,开发者需要根据目标设备和性能要求来选择最合适的优化策略。
|
||||
|
||||

|
||||

|
||||
|
||||
## 本节视频
|
||||
|
||||
<html>
|
||||
|
||||
<iframe src="https:&as_wide=1&high_quality=1&danmaku=0&t=30&autoplay=0" width="100%" height="500" scrolling="no" border="0" frameborder="no" framespacing="0" allowfullscreen="true"> </iframe>
|
||||
</html>
|
||||
|
@ -1,10 +1,5 @@
|
||||
# Winograd 算法
|
||||
|
||||
|
||||
|
||||
|
||||
### 实现步骤
|
||||
|
||||
## 本节视频
|
||||
|
||||
<html>
|
||||
|
43
build_books/format_table.py
Normal file
43
build_books/format_table.py
Normal file
@ -0,0 +1,43 @@
|
||||
# 适用于[License] (https://github.com/chenzomi12/AISystem/blob/main/LICENSE)版权许可
|
||||
|
||||
from bs4 import BeautifulSoup
|
||||
import os
|
||||
|
||||
"""
|
||||
1. 本脚本文件会设置所有html文件,使得表格居中显示。
|
||||
2. 确保你已经安装了bs4, 具体可以通过pip install bs4 进行安装
|
||||
"""
|
||||
|
||||
root_path = "./"
|
||||
html_root_path = "_build/html/"
|
||||
|
||||
|
||||
def get_html_list():
|
||||
index_html_path = os.path.join(root_path, html_root_path, "index.html")
|
||||
index_soup = BeautifulSoup(open(index_html_path))
|
||||
|
||||
content_list = index_soup.find(name="div", attrs={"class": "globaltoc"}). \
|
||||
find_all(name="a", attrs={"class": "reference internal"})
|
||||
html_list = [os.path.join(html_root_path, content_name["href"]) for content_name in content_list]
|
||||
return html_list
|
||||
|
||||
|
||||
def format_table():
|
||||
html_list = get_html_list()
|
||||
for html_file in html_list:
|
||||
try:
|
||||
soup = BeautifulSoup(open(html_file))
|
||||
all_tables = soup.find_all(name="table", attrs={"class": "docutils align-default"})
|
||||
for table in all_tables:
|
||||
table["style"] = "margin-left:auto;margin-right:auto;margin-top:10px;margin-bottom:20px;"
|
||||
|
||||
if len(all_tables):
|
||||
write_out_file = open(html_file, mode="w")
|
||||
write_out_file.write(soup.prettify())
|
||||
write_out_file.close()
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
format_table()
|
2
requirements.txt
Normal file
2
requirements.txt
Normal file
@ -0,0 +1,2 @@
|
||||
bs4
|
||||
sphinx==4.4.0
|
Reference in New Issue
Block a user