当前位置: 首页 > 知识库问答 >
问题:

Tensorflow Lite推断-如何缩小卷积层输出?

齐学文
2023-03-14

我用一个卷积层建立了一个简单的CNN模型,并用Tensorflow Lite进行了转换。(对于MNIST!!)所以现在我的模型得到8位整数输入,权重也是8位整数。

我想测试从TFLite获得的参数,所以我为推理步骤编写了C代码。

输入图像像素被赋予0到255之间的8位整数,权重在-128到127之间。(偏差是32位整数。)当然,卷积结果由大于255的数字组成。

我检查了这份文件(https://arxiv.org/pdf/1712.05877.pdf,“仅用于有效整数算术推理的神经网络的量化和训练”),它有一些如何处理卷积结果的技巧。它说我必须(1)缩小比例,(2)缩小(到uint8),以及(3)应用激活函数来生成8位输出。

根据我的理解,我需要将2^(-n)乘以卷积结果。因此,我将卷积输出除以256,并将最大数限制为255,并进一步使用完全连接的层权重计算它们。

它显示了一个很好的结果(准确度为0.96),但没有TFLite评估所说的那么高。(准确度0.98)

我认为我做得不对,因为“256”(我把卷积输出分成)是一个随机数。实际上,当我把它改成340时,它显示了最好的结果,但仍然远远低于使用TFLite解释器的TFLite评估。

实现推理步骤的正确而复杂的方法是什么?我如何缩小规模?

共有1个答案

贡俊
2023-03-14

这是一个关于TF Lite中量化的基本原理的大问题。你提到的论文是一个很好的参考和理解基础数学的指南。TF Lite现在使用与上述论文略有不同的量化方案,但仍然完全支持在当前方案实施之前转换的模型。您可以在这里查看新的量化方案的详细信息,以供参考:

https://www.tensorflow.org/lite/performance/quantization_spec

您的问题的答案同样适用于TF Lite中的所有量化方案。对于您问题的细节,您希望了解如何从32位累加器(将激活*过滤器的所有乘积相加的结果)到量化值(uint8或int8)。从本文中,您可以看到矩阵乘法(对于您感兴趣的卷积情况,它是一种类似的算法)是使用所有整数运算完成的,除了第2.2节等式5中定义的实值乘法器M。量化方案的目标是在纯整数运算中执行所有数学运算,因此挑战是“如何用纯整数运算乘以实值M?”。

“诀窍”是表示M,如等式6所示,作为2乘以负指数M_0,这是一个至少为0.5的实数,并从上面以1为界。乍一看,这似乎并没有使我们的问题变得更容易。但是,首先考虑<代码> 2 ^(-n)< /代码>部分。这可以在计算机上表示为一点点的移位(我将在一秒钟内讨论舍入)。假设处理了任何舍入问题,这一部分只需使用整数运算即可轻松完成。现在来看mu0部分。通过构造,我们将M_0绑定到一个范围,在该范围内,我们可以使用整数类型的定点表示(例如int32),并将所有位用作分数位(如果您不熟悉定点表示,您可能需要参考外部信息源)。

我们把M_0的32位定点表示称为“量化乘数”。您可以在下面的链接中看到操作的细节,但是,本质上,将累加器乘以量化乘法器涉及到一个标准整数乘法,得到一个64位的数字,然后得到该结果的高32位。

实际代码有点难理解,因为有各种各样的问题需要通过适当的舍入(如本文所讨论的)、溢出、值饱和、箝位等来处理。您可以通过查看此处的参考实现来开始理解它:

https://github.com/tensorflow/tensorflow/blob/master/tensorflow/lite/kernels/internal/common.h#L153-L162

其中SatatingRoundingDoublingHighMul通过量化乘法器实现定点乘法,并且RoundingDiVideByPOT通过2^(-n)实现乘法。

在设备上运行的实际代码中,TF Lite使用各种优化指令来实现这种算法,但是参考代码得到相同的答案,并且更容易检查和理解。希望有帮助!

 类似资料:
  • 如果输入到神经网络卷积层的是128x128x3大小的图像,并对其应用40个5x5大小的滤波器,那么输出大小会是多少?

  • 卷积神经网络有一个批量过滤器, 持续不断的在图片上滚动收集图片里的信息,每一次收集的时候都只是收集一小块像素区域, 然后把收集来的信息进行整理, 这时候整理出来的信息有了一些实际上的呈现, 比如这时的神经网络能看到一些边缘的图片信息, 然后在以同样的步骤, 用类似的批量过滤器扫过产生的这些边缘信息, 神经网络从这些边缘信息里面总结出更高层的信息结构,比如说总结的边缘能够画出眼睛,鼻子等等. 再经过

  • Convolution1D层 keras.layers.convolutional.Convolution1D(nb_filter, filter_length, init='uniform', activation='linear', weights=None, border_mode='valid', subsample_length=1, W_regularizer=None, b_regu

  • Conv1D层 keras.layers.convolutional.Conv1D(filters, kernel_size, strides=1, padding='valid', dilation_rate=1, activation=None, use_bias=True, kernel_initializer='glorot_uniform', bias_initializer='zero

  • 我在Keras建立了一个卷积神经网络。 根据CS231讲座,卷积操作为每个过滤器创建一个特征映射(即激活映射),然后将其堆叠在一起。在我的例子中,卷积层有一个300维的输入。因此,我预计会进行以下计算: 每个过滤器的窗口大小为5。因此,每个滤波器产生300-5 1=296个卷积 但是,实际输出形状看起来不同: 偏移值的形状很有意义,因为每个过滤器都有一个偏移值。然而,我不了解重量的形状。显然,第一

  • 假设我们有一个5x5大小的图像和一个3x3大小的内核,带有跨步2和填充。通过神经网络中的卷积层后,输出图像的大小是多少。