首页 > 编程语言 >转载:【AI系统】Winograd 算法

转载:【AI系统】Winograd 算法

时间:2024-12-14 14:22:33浏览次数:7  
标签:end AI 矩阵 Winograd times 卷积 算法 bmatrix

在上一篇文章的介绍中,介绍了 Im2Col 技术,它通过将三维张量重新排列成矩阵形式,然后利用基于内存访问局部性的优化库如 GEMM(通用矩阵乘法库)加速计算。随后,还探讨了空间组合优化,这一种利用局部性原理来提升效率的技术。

在本文将重点介绍 Winograd 优化算法,它是矩阵乘优化方法中 Coppersmith–Winograd 算法的一种应用,按照 Winograd 算法的原理将卷积的运算进行转换,从而减少卷积运算中乘法的计算总量。其主要是通过将卷积中的乘法使用加法来替换,并把一部分替换出来的加法放到卷积权重的提前处理阶段中,从而实现卷积计算的加速。Winograd 算法的优化局限于一些特定的常用卷积参数,这限制了其在更广泛场景下的应用。尽管存在这些局限性,Winograd 算法仍然是深度学习领域中的重要优化手段之一,对于提高卷积神经网络运行效率具有显著作用。

Winograd 算法原理

Winograd 算法最早是 1980 年由 Shmuel Winograd 提出的《Arithmetic complexity of computations》,当时并没有引起太大的轰动。在 CVPR 2016 会议上,Lavin 等人在《Fast algorithms for convolutional neural networks》中提出了利用 Winograd 加速卷积运算,于是 Winograd 加速卷积在算法圈里火了起来,并从此 Winograd 算法在包括 Mindspore Lite,MMN 等推理引擎中被广泛应用。

那 Winograd 为什么能加速卷积运算呢?简单来说就是用更多的加法计算来减少乘法计算,从而降低计算量,接下来就进一步了解如何使用 Winograd 加速卷积运算。

加速一维卷积计算

以一维卷积 $F(2,3)$ 为例,假设输入信号为 $d=[d_0,d_1,d_2,d_3]^T$,卷积核为 $g=[g_0,g_1,g_2]^T$,则整个卷积过程可以转换为如下的矩阵乘形式:

$$
\begin{align}
F(2,3) = \begin{bmatrix}
d_0 & d_1 & d_2\
d_1 & d_2 & d_3
\end{bmatrix}
\begin{bmatrix}
g_0 \
g_1 \
g_2
\end{bmatrix}
= \begin{bmatrix}
r_0 \
r_1
\end{bmatrix}
\end{align}
$$

如果是使用一般的矩阵乘法进行计算,则如下式所示,会进行 6 次乘法操作与 4 次加法操作。

$$
\begin{align}
r_0 & = d_0 \times g_0 + d_1 \times g_1 + d_2 \times g_2\
r_1 & = d_1 \times g_0 + d_2 \times g_1 + d_3 \times g_2
\end{align}
$$

具体的过程可以由下图了解到,在卷积的计算过程中,由于在卷积层的设计中,往往卷积的步幅(Stride)的大小会小于卷积核的大小,所以最后转换的矩阵乘中往往有规律的分布着大量重复元素,比如这个一维卷积例子中矩阵乘输入矩阵第一行的 $d_1$、$d_2$ 和第二行中的 $d_1$、$d_2$,卷积转换成的矩阵乘法比一般矩阵乘法的问题域更小,这就让优化存在了可能。

image

在 Winograd 算法中则是通过增加加法操作来减少乘法操作从而实现计算加速,具体操作如下式所示:

$$
\begin{align}
F(2,3) = \begin{bmatrix}
d_0 & d_1 & d_2\
d_1 & d_2 & d_3
\end{bmatrix}
\begin{bmatrix}
g_0 \
g_1 \
g_2
\end{bmatrix}
= \begin{bmatrix}
m_1 + m_2 + m_3 \
m_2 - m_3 - m_4
\end{bmatrix}
\end{align}
$$

其中,$m_1=(d_0-d_2)g_0$,$m_2=(d_1+d_2)\frac{g_0+g_1+g_2}{2}$,$m_3=(d_2-d_1)\frac{g_0-g_1+g_2}{2}$,$m_4=(d_1-d_3)g_2$。

因为在推理阶段卷积核上的元素是固定的,所以上式 $m_1$,$m_2$,$m_3$,$m_4$ 的式子中和 $g$ 相关的式子可以提前计算好,在预测阶段只需要计算一次,因此计算次数可以忽略。而在计算 $m_1$,$m_2$,$m_3$,$m_4$ 需要通过 4 次乘法操作与 4 次加法操作,然后基于计算好的 $m_1$,$m_2$,$m_3$,$m_4$ 的值,需要通过使用 4 次加法操作得到结果,所以这里一共需要 4 次乘法操作和 8 次加法操作。由于乘法操作比加法操作消耗的时间多,因此 Winograd 的 4 次乘法和 8 次加法是要比一般的矩阵乘法的 6 次乘法和 4 次加法要快的。

而 Winograd 加速卷积计算的具体推导过程如下,由上面的式子可以得知:

$$
\begin{align}
m_1 + m_2 + m_3 &= d_0 \times g_0 + d_1 \times g_1 + d_2 \times g_2\
m_2 - m_3 - m_4 &= d_1 \times g_0 + d_2 \times g_1 + d_3 \times g_2
\end{align}
$$

其中,因为 $m_1$ 与 $m_4$ 没有重复出现,所以令 $m_1 = d_0 \times g_0$,$m_4 = -d_3 \times g_2$,这样就可以约掉 $m_1$ 和 $m_4$,所以左边的式子只剩下两个变量,两个等式两个变量即可求出 $m_2$ 与 $m_3$,在这个时候的 $m_1$、$m_2$、$m_3$、$m_4$ 是这样的:

$$
\begin{align}
m_1 &= d_0 \times g_0\
m_2 &= \frac{g_1d_1 + g_2d_2 + g_0d_1 + g_1d_2}{2} \
m_3 &= \frac{g_1d_1 + g_2d_2 - g_0d_1 - g_1d_2}{2} \
m_4 &= -d_3 \times g_2\
\end{align
}
$$

$m_2$ 中包含了 $d_1$、$d_2$、$g_0$、$g_1$、$g_2$,将这个式子转换为两个多项式乘积的形式,也即拆成 $d$ 和 $g$ 分开的形式,如下:

$$
\begin{align}
m_2 = \frac{(d_1 + d_2)(g_0 + g_1 + g_2)}{2} - \frac{d_2g_0}{2} - \frac{d_1g_2}{2}
\end{align
}
$$

同理,也对 $m_3$ 进行转换得:

$$
\begin{align}
m_3 = \frac{(d_2 - d_1)(g_0 - g_1 + g_2)}{2} - \frac{d_2g_0}{2} + \frac{d_1g_2}{2}
\end{align
}
$$

由最初的(5)(6)式与上式可以得知,如果同时在 $m_2$ 与 $m_3$ 上同时加上一个值,对于式 (6) 来说整个式子是不变的,同时 $m_4$ 的值没有改变,而对于式 (5) 来说需要减去两倍的这个值才能保持整个式子不变。因此,当这个值为 $\frac{d_2 g_0}{2}$ 时可以简化表达式,通过这样的方式给上面的等式进行等价变换后得到的 $m_1$、$m_2$、$m_3$、$m_4$ 如下:

$$
\begin{align}
m_1 &= g_0(d_0 - d_2)\
m_2 &= \frac{(d_1 + d_2)(g_0 + g_1 + g_2)}{2} - \frac{d_1g_2}{2} \
m_3 &= \frac{(d_2 - d_1)(g_0 - g_1 + g_2)}{2} + \frac{d_1g_2}{2} \
m_4 &= -d_3 \times g_2\
\end{align
}
$$

同理,如果给 $m_2$ 加上一个值,同时给 $m_3$ 减去这个值,那么对于式 (5) 来说整个式子是不变的,并且 $m_1$ 的值没有改变,对于式 (6) 来说需要给 m4 需要减去两倍的这个值才能保持整个式子不变。因此,当这个值为 $\frac{d_1 g_2}{2}$ 时可以简化表达式,通过这样的方式给上面的等式进行等价变换后得到的 $m_1$、$m_2$、$m_3$、$m_4$ 如下:

$$
\begin{align}
m_1 &= g_0(d_0 - d_2)\
m_2 &= \frac{(d_1 + d_2)(g_0 + g_1 + g_2)}{2} \
m_3 &= \frac{(d_2 - d_1)(g_0 - g_1 + g_2)}{2} \
m_4 &= g_2(d_1-d_3)\
\end{align
}
$$

将上面的计算过程写成矩阵的形式如下:

$$
\begin{align}
Y = A^T[(Gg)\odot (B^Td)]
\end{align}
$$

其中,

  • $\odot$ 表示 element-wise multiplication(Hadamard product),即对应位置相乘操作;
  • $g$ 表示卷积核;$d$ 表示输入特征图(输入信号);
  • $G$ 表示卷积核变换矩阵,尺寸为 $(u+k-1) \times k$;
  • $B^T$ 表示输入变换矩阵,尺寸为 $(u+k-1)\times (u+k-1)$;
  • $A^T$ 表示输出变换矩阵,尺寸为 $(u+k-1) \times u$;
  • $u$ 表示输出尺寸,$k$ 表示卷积核尺寸,$u+k-1$ 表示输入尺寸。

式子中各个矩阵具体的值如下:

$$
\begin{align}
& B^T=\begin{bmatrix}
1 & 0 & -1 & 0 \
0 & 1 & 1 & 0 \
0 & -1 & 1 & 0 \
0 & 1 & 0 & -1
\end{bmatrix} \qquad
G=\begin{bmatrix}
1 & 0 & 0 \
\frac{1}{2} & \frac{1}{2} & \frac{1}{2} \
\frac{1}{2} & -\frac{1}{2} & \frac{1}{2} \
0 & 0 & 1 \
\end{bmatrix} \qquad
A^T = \begin{bmatrix}
1 & 1 & 1 & 0 \
0 & 1 & -1 & -1 \
\end{bmatrix} \
& g = \begin{bmatrix}
& g_0 & g_1 & g_2
\end{bmatrix}^T \qquad \qquad
d = \begin{bmatrix}
d_0 & d_1 & d_2 & d_3
\end{bmatrix}^T
\end{align
}
$$

加速二维卷积计算

将一维卷积 $F(2,3)$ 的变换扩展到二维卷积 $F(2 \times 2, 3 \times 3)$,同样用矩阵形式表示为:

$$
\begin{align}
Y = AT[[GgGT]\odot[B^TdB]]A
\end{align}
$$

其中,$g$ 为 $r \times r$ 的卷积核,$d$ 为 $(m + r -1) \times (m + r -1)$ 的图像块.

对于二维卷积,可以先将卷积过程使用 img2col 进行展开,将卷积核的元素拉成了一列,将输入信号每个滑动窗口中的元素拉成了一行,变成如下的矩阵乘的形式:

$$
\begin{align}
\begin{bmatrix}
k_{0} & k_{1} & k_{2} & k_{4} & k_{5} & k_{6} & k_{8} & k_{9} & k_{10} \
k_{1} & k_{2} & k_{3} & k_{5} & k_{6} & k_{7} & k_{9} & k_{10} & k_{11} \
k_{4} & k_{5} & k_{6} & k_{8} & k_{9} & k_{10} & k_{12} & k_{13} & k_{14} \
k_{5} & k_{6} & k_{7} & k_{9} & k_{10} & k_{11} & k_{13} & k_{14} & k_{15} \
\end{bmatrix}\begin{bmatrix}
w_0\
w_1\
w_2\
w_3\
w_4\
w_5\
w_6\
w_7\
w_8\
\end{bmatrix}=\begin{bmatrix}
r_0\
r_1\
r_2\
r_3
\end{bmatrix}
\end{align
}
$$

然后,将上述的矩阵乘的形式进行如下图的分块:

image

即可以表示成如下类似于前文中 Winograd 加速一维卷积计算形式:

$$
\begin{align}
F(2 \times 2, 3 \times 3)=\begin{bmatrix}
d_0 & d_1 & d_2\
d_1 & d_2 & d_3
\end{bmatrix}
\begin{bmatrix}
g_0 \
g_1 \
g_2
\end{bmatrix}
= \begin{bmatrix}
r_0 \
r_1
\end{bmatrix}
\end{align
}
$$

当然,变成了这样的形式就可以使用前文的推导方法,推导到出式(8)中的 Winograd 加速二维卷积计算的矩阵形式。

Winograd 实现步骤

基于上文的介绍,Winograd 算法的实现可以细分为四个主要步骤:

  1. 对输入卷积核的变换:$

    标签:end,AI,矩阵,Winograd,times,卷积,算法,bmatrix
    From: https://www.cnblogs.com/khronos0206/p/18606676

相关文章

  • 转载:【AI系统】Im2Col 算法
    作为早期的AI框架,Caffe中卷积的实现采用的是基于Im2Col的方法,至今仍是卷积重要的优化方法之一。从上一篇文章的介绍中可以看到,在CNN中卷积直接计算的定义中,卷积核在输入图片上滑动,对应位置的元素相乘后相加求和,滑窗的大小由卷积核决定。由于滑动操作时的窗口的数据横向是......
  • 转载:【AI系统】AI 框架基础介绍
    什么是AI算法?什么是神经网络?神经网络有什么用?为什么神经网络需要训练?什么是模型?AI框架有什么用?AI框架能解决什么问题?上面的几个问题其实还挺有挑战的,也是本文需要回答的一个问题。下面来对一些基础概念进程澄清:首先深度学习是机器学习研究领域中的一种范式,而深度学习的概念源......
  • 转载:【AI系统】AI 框架作用
    深度学习范式主要是通过发现经验数据中,错综复杂的结构进行学习。通过构建包含多个处理层的计算模型(网络模型),深度学习可以创建多个级别的抽象层来表示数据。例如,卷积神经网络CNN可以使用大量图像进行训练,例如对猫狗分类去学习猫和狗图片的特征。这种类型的神经网络通常从所采集图......
  • 转载:【AI系统】模型压缩基本介绍
    随着神经网络模型的复杂性和规模不断增加,模型对存储空间和计算资源的需求越来越多,使得部署和运行成本显著上升。模型压缩的目标是通过减少模型的存储空间、减少计算量或提高模型的计算效率,从而在保持模型性能的同时,降低模型部署的成本。模型压缩的目标可以概括为以下几点:减少模......
  • 转载:【AI系统】感知量化训练 QAT
    本文将会介绍感知量化训练(QAT)流程,这是一种在训练期间模拟量化操作的方法,用于减少将神经网络模型从FP32精度量化到INT8时的精度损失。QAT通过在模型中插入伪量化节点(FakeQuant)来模拟量化误差,并在训练过程中最小化这些误差,最终得到一个适应量化环境的模型。文中还会讨论伪量化......
  • 转载:【AI系统】低比特量化原理
    计算机里面数值有很多种表示方式,如浮点表示的FP32、FP16,整数表示的INT32、INT16、INT8,量化一般是将FP32、FP16降低为INT8甚至INT4等低比特表示。模型量化则是一种将浮点值映射到低比特离散值的技术,可以有效的减少模型的参数大小、内存消耗和推理延迟,但往往带来较大的精......
  • 转载:【AI系统】训练后量化与部署
    本文将会重点介绍训练后量化技术的两种方式:动态和静态方法,将模型权重和激活从浮点数转换为整数,以减少模型大小和加速推理。并以KL散度作为例子讲解校准方法和量化粒度控制来平衡模型精度和性能。训练后量化的方式训练后量化的方式主要分为动态和静态两种。动态离线量化动态......
  • 转载:【AI系统】动态图与静态图转换
    从TensorFlow、PyTorch,到PaddlePaddle、MindSpore、MegEngine,主流的AI框架动静态图转换,经历了动静分离、动静结合到动静统一的发展过程。兼顾动态图易用性和静态图执行性能高效两方面优势,均具备动态图转静态图的功能,支持使用动态图编写代码,框架自动转换为静态图网络结构执行计......
  • 转载:【AI系统】计算图挑战与未来
    目前主流的AI框架都选择使用计算图来抽象神经网络计算表达,通过通用的数据结构(张量)来理解、表达和执行神经网络模型,通过计算图可以把AI系统化的问题形象地表示出来。计算图与框架关系计算图回顾在AI框架中,其计算图的基本组成有两个主要的元素:1)基本数据结构张量和2)基本计......
  • 转载:【AI系统】并行训练基本介绍
    分布式训练是一种模型训练模式,它将训练工作量分散到多个工作节点上,从而大大提高了训练速度和模型准确性。虽然分布式训练可用于任何类型的AI模型训练,但将其用于大模型和计算要求较高的任务最为有利。本篇幅将围绕在PyTorch2.0中提供的多种分布式训练方式展开,包括并行训练,如:数......