出于研究目的,我试图了解TF Lite是如何进行推理的。我只对软件逻辑感兴趣。
我使用的是TensorFlow 2.1和TensorFlow模型html" target="_blank">优化0.3。0
例如,我使用一个非常简单的完全连接的网络:
tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28, 1)),
tf.keras.layers.Dense(10, activation=None)
])
我通过量化感知训练在mnist上训练网络。
然后用TF Lite对网络进行量化:
converter = tf.lite.TFLiteConverter.from_keras_model(model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
converter.representative_dataset = data_generator(ds_train)
quantized_tflite_model = converter.convert()
为了确保我知道我在做什么,我做了三件事:我使用TF从32位模型获得输出。我使用TF Lite从量化模型中获取输出。我在Python中实现了32位模型的正向传递,并将其输出与之前的2进行了比较。
现在我试图理解如何实现量化模型的前向传递。
使用解释器。获取_tensor_details(),我将获得以下输出:
{'name': 'Identity', 'index': 0, 'shape': array([ 1, 10]), 'dtype': <class 'numpy.float32'>, 'quantization': (0.0, 0)}
{'name': 'flatten_input_int8', 'index': 1, 'shape': array([ 1, 28, 28, 1]), 'dtype': <class 'numpy.int8'>, 'quantization': (0.003921568859368563, -128)}
{'name': 'sequential/quant_dense/BiasAdd', 'index': 2, 'shape': array([ 1, 10]), 'dtype': <class 'numpy.int8'>, 'quantization': (0.22868551313877106, 49)}
{'name': 'sequential/quant_dense/LastValueQuant/FakeQuantWithMinMaxVars/transpose', 'index': 3, 'shape': array([ 10, 784]), 'dtype': <class 'numpy.int8'>, 'quantization': (0.01087072491645813, 0)}
{'name': 'sequential/quant_dense/MatMul_bias', 'index': 4, 'shape': array([10]), 'dtype': <class 'numpy.int32'>, 'quantization': (4.263029768480919e-05, 0)}
{'name': 'sequential/quant_dense/BiasAdd_float', 'index': 5, 'shape': array([ 1, 10]), 'dtype': <class 'numpy.float32'>, 'quantization': (0.0, 0)}
{'name': 'flatten_input', 'index': 6, 'shape': array([ 1, 28, 28, 1]), 'dtype': <class 'numpy.float32'>, 'quantization': (0.0, 0)}
我用这篇论文作为参考:https://arxiv.org/pdf/1712.05877.pdf 我还读了这一页:https://www.tensorflow.org/lite/performance/quantization_spec
我当前的实现如下所示:
def quantization_params(index):
return tensor_details[index]['quantization'][0], tensor_details[index]['quantization'][1]
image = get_single_test_image(show_image=False)
# #### Convert input image from float32 to int8 ####
q_scale, q_zero = quantization_params(index=1)
x = image / q_scale + q_zero
# #### Flatten input ####
x = x.flatten()
# #### Dense layer ####
kernel, bias = tflite_model.interpreter.get_tensor(3), tflite_model.interpreter.get_tensor(4)
s_input, z_input = quantization_params(index=1)
s_kernel, z_kernel = quantization_params(index=3)
s_output, z_output = quantization_params(index=4)
M = s_input * s_kernel
quantized_multiplier, right_shift = quantize_multiplier_smaller_than_one(M)
dense_output = np.zeros((kernel.shape[0],), dtype=np.int32)
for i in range(dense_output.shape[0]):
for j in range(kernel.shape[1]):
dense_output[i] += int((x[j] + z_input) * (kernel[i, j] + z_kernel))
x = dense_output + bias
x = np.right_shift(x * quantized_multiplier, right_shift)
函数quantize_multiplier_minor_than_one是我对C函数的Python实现:https://github.com/google/gemmlowp/blob/master/doc/quantization_example.cc
所以我的问题是,这是正确的方法吗?我肯定错过了一些计算,是什么?而且,当我有一个更大的网络时,我如何知道如何系统地使用正确的索引来提取每个层的量化参数。
非常感谢你的建议。
最后,我通过深入TensorFlow/Lite代码解决了这个问题。我找到了相关代码并对其进行了修改,因此它将我需要的所有相关信息打印到文本文件中。从那里,我可以解析Python中的所有内容,并运行Pythonic版本的cpp逻辑。
如果有人想尝试同样的方法,为了构建CPP解决方案,请转到从源代码构建
示例应用程序的入口点如下:https://github.com/tensorflow/tensorflow/tree/master/tensorflow/lite/examples/minimal
例如,卷积参考码如下:https://github.com/tensorflow/tensorflow/blob/master/tensorflow/lite/kernels/internal/reference/integer_ops/conv.h
享受(不是真的)
问题内容: 我以前的编程中,代码段仅用于调试目的(记录命令等)。通过使用预处理程序指令,可以完全禁用这些语句以进行生产,如下所示: 做类似的事情的最好方法是什么? 问题答案: 如果只想禁用日志记录方法,请使用该模块。如果日志级别设置为排除调试语句,那么它将非常接近无操作(它仅检查日志级别并返回而不插入日志字符串)。 如果要在特定条件下以字节码编译时实际删除代码块,则唯一的选择是相当神秘的全局变量。
我从Tensorflow Hub重新训练了一个mobilenet-v1图像分类模型,并使用toco对其进行转换,以便使用Tensorflow Lite进行推断。 但是,当我使用tflite模型运行推断时,它需要与我使用指定的输入大小不同的输入大小。 我如何在自己的数据上重新训练一个mobilenetv1量化模型? 下面是我尝试的步骤: > 从tensorflow for poets Codelab
问题内容: 如何实现与C#代码等效的Python? 这是一个好主意吗??请在您的答案中举例说明。 问题答案: 正如其他人在这里提到的: 在Python中不需要接口。这是因为Python具有适当的多重继承,还具有鸭式输入法,这意味着 必须 在Java中具有接口的地方,而不必在Python中具有接口。 也就是说,接口还有多种用途。其中一些被Python 2.6中引入的Pythons抽象基类覆盖。如果您
问题内容: 我想知道Python 3中的新super是如何实现的。 我做了一个小例子之后,这个问题就浮现在脑海中,我得到了一个奇怪的错误。我正在使用Pyutilib组件体系结构(PCA),并且已经制作了自定义元类来驱动另一个类的创建: 我收到以下错误: 我wonderign究竟超(一样),它引发的错误,而所有的,并存在。另外的“老方法”-正在工作。 问题答案: 如何执行?这是python3.3的代
问题内容: 我已经实现了 算法 对于GMM使用这个 后[GMMs]与最大似然优化 努比](https://towardsdatascience.com/how-to-code-gaussian-mixture-models- from-scratch-in-python-9e7975df5252)未成功,如下所示: when I run the algorithm on a 1-D time-se
这个问题要求解释在各种语言中如何在后台实现异常处理,但没有收到Python的任何回应。 我对Python特别感兴趣,因为Python通过EAFP原则“鼓励”异常抛出和捕捉。 我从其他SO答案中了解到,如果预计很少引发异常,try/catch块比if/etc语句更便宜,并且调用深度很重要,因为填充stacktrac很昂贵。这可能主要适用于所有编程语言。 python的特殊之处在于EAFP原则的高优先