打开 onnx 模型图,可以看到它是一个有向无环图。除了 Input、Output ,其他都是算子(是操作,而不是节点)
在ONNX(Open Neural Network Exchange)模型中,除了输入和输出,其他都是算子(Operations)。算子是表示神经网络模型中的不同操作或层的元素。一个ONNX模型由一系列算子组成,通过连接这些算子来定义模型的计算流程。
常见的算子包括卷积、全连接、池化、激活函数(如ReLU、Sigmoid)、批归一化(如Batch Normalization)、Dropout等。每个算子都有自己的输入和输出张量,并且可能有一些可调参数用于控制其行为。
算子之间的连接关系形成了一个有向图,反映了模型中不同操作的计算顺序。输入张量通过算子进行计算,然后产生输出张量,这些输出张量又可以作为其他算子的输入。最后一个算子的输出张量即为模型的输出。
ONNX提供了一种通用的中间表示形式,使得各种深度学习框架之间可以相互转换模型。通过使用ONNX,可以将模型从一个框架导出为ONNX格式,然后将其导入到另一个框架中进行训练或推理。这种灵活性使得研究人员和开发人员能够更方便地在不同框架之间共享和使用模型。
在onnx中,每个 conv 算子算一层
Conv (卷积)
conv 相当于在 gemm 基础上做了稀疏化和权重共享
attribute(属性)
pad 补零: auto_pad 自动补零 pads 指定补零
dilations 膨胀:
用于指定卷积核在输入张量的各个维度上的扩张率。这个属性是一个整数列表,长度通常与输入张量的维度相同。每个整数表示对应维度上的扩张率。
dilations 用于控制卷积核在输入张量的各个维度上的滑动步长,通过增加扩张率可以增加卷积操作的感受野,提取更多的特征信息。
group(分组):
在深度卷积神经网络中,group属性用于指定卷积操作的分组数。这个属性是一个整数值,用于将输入张量和卷积核进行分组,并对每个组进行独立的卷积运算。
具体来说,当group属性的值大于1时,输入张量和卷积核会被分成group个组,每个组包含相同数量的通道。然后,对每个组进行独立的卷积运算,最后将各个组的输出结果进行拼接,得到最终的卷积操作的输出张量。
总结来说,group属性用于将输入张量和卷积核进行分组,并对每个组进行独立的卷积运算。通过设置group属性,可以减少卷积操作的计算量,但可能会降低特征的表达能力。
kernel_shape(卷积核形状)
kernel_shape属性用于指定卷积核的形状。kernel_shape是一个整数列表,其长度应与输入张量的维度相同,每个元素表示卷积核在对应维度上的大小。
具体来说,对于二维卷积操作,输入张量的形状通常为[batch_size, height, width, channels],而kernel_shape应该是一个长度为2的整数列表,表示卷积核在高度和宽度上的大小。
例如,如果希望使用一个3x3的卷积核进行二维卷积操作,可以将kernel_shape设置为[3, 3]。
需要注意的是,kernel_shape属性只用于指定卷积核的形状,卷积核的通道数是由卷积层的参数决定的,而不是通过kernel_shape属性来指定的。
总结起来,kernel_shape属性是用于指定卷积核形状的属性,它是一个整数列表,长度与输入张量的维度相同,每个元素表示卷积核在对应维度上的大小。
strides(步长)
conv属性strides是卷积层的步长参数,用于控制卷积核在输入数据上滑动的步幅。它是一个包含两个整数的元组,分别表示在水平和竖直方向上的步长大小。默认值为(1, 1),即卷积核每次水平和竖直方向上移动一个像素。较大的步长可以减少输出特征图的大小,同时也会降低模型的计算量。
Input
x: T(N x OC x H x W)
W: T(M x C/group x kH x kW)
B(optional):T(M)
Output
Y: T (N x M x ? x ?)
重点算子
pytorch中的Linear相当于onnx模型中的gemm操作
torch.nn 包下的模型都是封装好的,会自动填充weight
Gemm(General Matrix multipication)
通用矩阵相乘:提供缩放因子 bias
Gemm(General Matrix Multiply)是一种通用的矩阵相乘操作。在计算机科学中,矩阵相乘是一种常见的线性代数运算,用于将两个矩阵相乘得到一个新的矩阵。
Gemm操作可以表示为:C = alpha * A * B + beta * C,其中A、B和C分别是输入矩阵,alpha和beta是标量值。
Gemm操作的实现通常使用高度优化的算法和硬件指令集,以提高计算效率。这些优化方法包括使用矩阵分块、并行计算、缓存优化等。Gemm操作在深度学习中广泛应用于卷积神经网络(CNN)的前向和反向传播过程中,用于计算卷积层和全连接层的输出。
在深度学习框架中,通常会使用底层的线性代数库(如BLAS、cuBLAS等)来执行Gemm操作,以实现高效的矩阵相乘计算。这些库提供了高度优化的Gemm实现,可以充分利用多核CPU或GPU的并行计算能力,加速深度学习模型的训练和推理过程。
a = np.random.ranf([6, 3]).astype(np.float32)
b = np.random.ranf([4, 6]).astype(np.float32)
c = np.random.ranf([1, 1]).astype(np.float32)
y = 0.5 * np.dot(a.T, b.T) + 0.5 * c
conv 相当于在 gemm 基础上做了稀疏化和权重共享
POOL 池化
与conv类似,他有滑窗,但是没有参数,并不进行参数的学习。池化操作是在每个通道上单独进行的
:::info
pool 与 conv的区别:
- 池化没有参数,卷积有参数
- 池化针对每个特征图独立操作,而卷积不是,它是对所有特征图进行加权操作
:::
Global Average Pool 全局平均池化,是AdaptiveAvgPool的(KN,KW)为(1, 1)的特征
flatten 拉平
将输入张量tensor X 拉平为一个2Dmatrix
将张量从0(下标)到axis轴和从axis轴到结尾的维度合并成1维
shape = (2, 3, 4, 5)
X = np.random.random_sample(shape).astype(np.float32)
axis = 2
if i==0:
new_shape = (1, -1)
else:
new_shape = (np.prod(shape[0:axis]).astype(int), -1)
Y = np.rashape(a, new_shape)
BatchNormalization 批标准化,bn
通常放在全连接层之后,可以大幅提高收敛速度。
标准化还能使特征的均值接近0,方差接近1。从而使数据变得更加稳定,提高模型训练和预测性能。
使用BanchNorm时,输入的特征图越大越好,因为BN是在整个特征图上进行标准化,使用样本均值代替总体。根据大数定律,数据量越大,样本均值越能代表总体
Normalization标准化:
BatchNorm:计算每个特征在整个Batch上的均值和方差
LayerNorm:计算每个特征上的E(x)和D(x)
InstanceNorm:计算在每个通道上的均值和方差
GroupNorm:计算在每个通道组上的E(x)和D(x)
以下是对这些标准化方法的更详细解释:
- 批标准化(Batch Normalization,BN):
BN是在每个小批量样本中对每个特征通道进行标准化。它计算每个特征在整个批次上的均值和方差,并将数据进行标准化,使其具有零均值和单位方差。BN通过减少内部协变量偏移并帮助梯度传播,从而加速神经网络的训练过程。- 层标准化(Layer Normalization,LN):
LN是在每个样本上对每个特征进行标准化。它计算每个特征在样本上的均值和方差,并将数据进行标准化。与BN不同,LN不依赖于批次的大小,适用于各种场景,例如循环神经网络(RNN)中的序列数据。- 实例标准化(Instance Normalization,IN):
IN是在每个样本上对每个通道进行标准化。它计算每个通道在样本上的均值和方差,并将数据进行标准化。IN常用于图像生成任务,如图像风格转换和图像生成模型。- 组标准化(Group Normalization,GN):
GN是在每个样本上对每个通道组进行标准化。通道组是将通道分成多个组,每个组包含一部分通道。GN计算每个通道组在样本上的均值和方差,并将数据进行标准化。GN适用于较小的批次大小和较大的通道数,尤其在计算资源有限的情况下表现较好。
GN介于LN和IN之间,当分组等于1时,GN就是LN;当分组等于特征数时,GN就是IN
这些标准化方法在深度学习中都发挥着重要的作用,可以帮助模型更稳定地训练和提高泛化能力。选择使用哪种标准化方法取决于具体的任务和数据特征。
UpSample 上采样
在深度学习中,上采样(Upsample)是一种常用的操作,用于将输入张量的尺寸增大。上采样可以用于多种任务,如图像分割、图像生成等。
每个输出的维度:output_dim = input_dim * scale
在上采样操作中,scale参数表示要将输入张量的尺寸增大的倍数。例如,如果scale为2,则表示将输入张量的尺寸在每个维度上增大两倍。
具体来说,上采样操作通常使用插值方法来填充新生成的像素值。常见的插值方法包括最近邻插值、双线性插值等。
需要注意的是,上采样操作并不改变输入张量的通道数,只是改变了张量的空间尺寸。因此,在进行上采样操作时,需要注意通道数的一致性,以便后续的操作能够正确进行。
pad 补0
当输入特征图的尺寸与卷积核的尺寸不成比例时,可能会导致部分特征被弃用或信息损失。为了解决这个问题,可以使用填充(padding)操作。
填充操作是在输入特征图的边缘周围添加额外的像素值,以扩展特征图的尺寸。填充可以在卷积操作(convolution)和池化操作(pooling)中使用。
在卷积操作中,填充可以保持输入特征图和输出特征图的尺寸一致,从而避免信息损失。填充通常使用0值进行填充,称为零填充(zero padding)。
在池化操作中,填充可以保持池化后的特征图尺寸与输入特征图一致,从而避免信息损失。填充通常使用最大值或平均值进行填充。
填充操作可以根据需要在不同的方向上进行,例如在高度(H)和宽度(W)方向上分别进行填充,或者在四个方向上进行对称填充。
通过适当的填充操作,可以确保输入特征图的尺寸与卷积核的尺寸成比例,从而避免信息损失,并获得更好的特征提取和模型性能。
concat 拼接
将多个张量在某个维度堆叠成一个张量。要求输入张量有相同的shape,除了堆叠的维度
其他
Add、Sub、Mul、Div、Pow运算操作
Reshape 改变形状
Transpose 换轴
Squeeze与Unsqueeze 挤压与反挤压
Gather:Embedding(二维:[m, m])
gather常用于词嵌入(二维)
Expand 扩张,按照broadcast规则复刻原有数据
ReduceMean&ReduceSum 减少
Loop:while 循环
中间调整算子
中间调整算子(Intermediate Adjustment Operations)是指在神经网络模型中用于调整中间特征图的操作或层。这些算子通常位于模型的不同层之间,用于改变特征图的尺寸、通道数或特征表示。
常见的中间调整算子包括池化(Pooling)、上采样(Upsampling)、下采样(Downsampling)、转置卷积(Transpose Convolution)、填充(Padding)等。
- 池化操作用于减小特征图的尺寸,常见的池化操作有最大池化(Max Pooling)和平均池化(Average Pooling),可以通过设置池化核大小和步长来控制输出尺寸。
- 上采样操作用于增大特征图的尺寸,常见的上采样操作有双线性插值(Bilinear Interpolation)和转置卷积(Transpose Convolution),可以通过设置上采样倍数来控制输出尺寸。
- 下采样操作用于减小特征图的通道数,常见的下采样操作有全局平均池化(Global Average Pooling)和全连接层(Fully Connected),可以通过设置输出通道数来控制输出特征数量。
- 转置卷积操作用于将特征图进行逆卷积操作,可以增大特征图的尺寸和通道数,常用于图像分割和图像生成任务。
- 填充操作用于在特征图周围添加边缘填充,可以保持特征图尺寸不变或扩大特征图尺寸,常用于卷积层中处理边缘像素的问题。
这些中间调整算子在神经网络模型中起到了重要的作用,可以改变特征图的表示能力和空间尺寸,从而提高模型的性能和表达能力。