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

如何通过TensorFlow的量化感知训练和实验量化获得量化权重

匡凌
2023-03-14

我正在使用TensorFlow的量化感知训练API,并希望部署一个具有任意比特宽度的模型。由于tflite部署仅支持8位量化,因此我将使用自定义推理算法进行部署,但我仍然需要访问正确大小的模型权重。

目前,在使用量化感知训练后,我的模型仍然处于浮点状态,据我所知,访问量化权重的唯一方法是将模型转换为tflite格式。然而,在使用实验函数时,这是不可能的。

这是我的量化配置类:

    class Quantizer(tfmot.quantization.keras.QuantizeConfig):
    # Configure how to quantize weights.
    def get_weights_and_quantizers(self, layer):
        return [(layer.kernel, tfmot.quantization.keras.quantizers.LastValueQuantizer(num_bits=8, symmetric=True, narrow_range=False, per_axis=False))]

    # Configure how to quantize activations.
    def get_activations_and_quantizers(self, layer):
        return [(layer.activation, tfmot.quantization.keras.quantizers.MovingAverageQuantizer(num_bits=8, symmetric=False, narrow_range=False, per_axis=False))]

    def set_quantize_weights(self, layer, quantize_weights):
        # Add this line for each item returned in `get_weights_and_quantizers`
        # , in the same order
            layer.kernel = quantize_weights[0]

    def set_quantize_activations(self, layer, quantize_activations):
        # Add this line for each item returned in `get_activations_and_quantizers`
        # , in the same order.
        layer.activation = quantize_activations[0]

    # Configure how to quantize outputs (may be equivalent to activations).
    def get_output_quantizers(self, layer):
        return []

    def get_config(self):
        return {}
    
class ModifiedQuantizer(Quantizer):
    # Configure weights to quantize with 4-bit instead of 8-bits.
    def get_weights_and_quantizers(self, layer):
        return [(layer.kernel, quantizer(num_bits=bits, symmetric=symmetric, narrow_range=narrow_range, per_axis=per_axis))]

下面是我如何量化模型的:

    supported_layers = [
    tf.keras.layers.Conv2D,
    tf.keras.layers.DepthwiseConv2D
]

class Quantizer(tfmot.quantization.keras.QuantizeConfig):
    # Configure how to quantize weights.
    def get_weights_and_quantizers(self, layer):
        return [(layer.kernel, tfmot.quantization.keras.quantizers.LastValueQuantizer(num_bits=8, symmetric=True, narrow_range=False, per_axis=False))]

    # Configure how to quantize activations.
    def get_activations_and_quantizers(self, layer):
        return [(layer.activation, tfmot.quantization.keras.quantizers.MovingAverageQuantizer(num_bits=8, symmetric=False, narrow_range=False, per_axis=False))]

    def set_quantize_weights(self, layer, quantize_weights):
        # Add this line for each item returned in `get_weights_and_quantizers`
        # , in the same order
            layer.kernel = quantize_weights[0]

    def set_quantize_activations(self, layer, quantize_activations):
        # Add this line for each item returned in `get_activations_and_quantizers`
        # , in the same order.
        layer.activation = quantize_activations[0]

    # Configure how to quantize outputs (may be equivalent to activations).
    def get_output_quantizers(self, layer):
        return []

    def get_config(self):
        return {}
    
class ModifiedQuantizer(Quantizer):
    # Configure weights to quantize with 4-bit instead of 8-bits.
    def get_weights_and_quantizers(self, layer):
        return [(layer.kernel, quantizer(num_bits=bits, symmetric=symmetric, narrow_range=narrow_range, per_axis=per_axis))]
    
    # Configure how to quantize activations.
    def get_activations_and_quantizers(self, layer):
        return [(layer.activation, tfmot.quantization.keras.quantizers.MovingAverageQuantizer(num_bits=bits, symmetric=False, narrow_range=False, per_axis=False))]

    def quantize_all_layers(layer):
        for supported_layer in supported_layers:
            if isinstance(layer, supported_layer):
                return quantize_annotate_layer(layer, quantize_config=ModifiedQuantizer())
        # print(layer.name)
        return layer
    annotated_model = clone_model(
        model,
        clone_function=quantize_all_layers
    )

with quantize_scope(
    {'Quantizer': Quantizer},
    {'ModifiedQuantizer': ModifiedQuantizer},
    {'_relu6': models._relu6}):
    q_aware_model = quantize_apply(annotated_model)

optimizer = keras.optimizers.Adam(
    learning_rate=0.001)
q_aware_model.compile(loss=tf.keras.losses.SparseCategoricalCrossentropy(
    from_logits=True),
    optimizer=optimizer, metrics=['sparse_categorical_accuracy'])

train_images, train_labels, val_images, val_labels, _, _ = cifar10.load()

q_aware_model.fit(train_images, train_labels, batch_size=64, epochs=1, verbose=1,
                  validation_data=(val_images, val_labels))

如前所述,当使用例如位=4的修改量化器时,模型仍然保存在浮点中,并且不知道如何访问量化权重。

谢谢!

共有1个答案

苏高远
2023-03-14

我怀疑您可以通过调用LastValueQuantizer来获得量化权重__对给定层的权重张量调用_u。问题是如何调用该方法。

当前签名为:

    LastValueQuantizer.__call__(inputs, training, weights, **kwargs)

我假设inputs是层的权重,weightsLastValueQuantizer返回的值。构建。如果您可以获得由build返回的weights的引用,我希望可以直接使用LastValueQuantizer对层的权重进行量化__调用

[nav] In [1]: from tensorflow_model_optimization.quantization.keras.quantizers import LastValueQuantizer
INFO:tensorflow:Enabling eager execution
INFO:tensorflow:Enabling v2 tensorshape
INFO:tensorflow:Enabling resource variables
INFO:tensorflow:Enabling tensor equality
INFO:tensorflow:Enabling control flow v2

[nav] In [2]: q = LastValueQuantizer(num_bits=3, per_axis=True, symmetric=True, narrow_range=True)

[ins] In [3]: ??q.__call__
Signature: q.__call__(inputs, training, weights, **kwargs)
Source:   
  def __call__(self, inputs, training, weights, **kwargs):
    """Quantize tensor.

    Args:
      inputs: Input tensor to be quantized.
      training: Whether the graph is currently training.
      weights: Dictionary of weights the quantizer can use to quantize the
        tensor. This contains the weights created in the `build` function.
      **kwargs: Additional variables which may be passed to the quantizer.

    Returns:
      Quantized tensor.
    """
    return quant_ops.LastValueQuantize(
        inputs,
        weights['min_var'],
        weights['max_var'],
        is_training=training,
        num_bits=self.num_bits,
        per_channel=self.per_axis,
        symmetric=self.symmetric,
        narrow_range=self.narrow_range
    )
 类似资料:
  • 我有一个包含Conv2D层的网络,然后是ReLU激活,声明如下: 它被移植到TFLite,具有以下代表性: 无Q感知训练的基本TFLite网络 然而,在网络上执行量化感知训练并再次移植后,ReLU层现在在图中是明确的: TFLite网络在Q感知训练后 这导致它们在目标上被单独处理,而不是在Conv2D内核的评估期间,在我的整个网络中导致10%的性能损失。 使用以下隐式语法声明激活不会产生问题: 具

  • 本文向大家介绍TensorFlow实现随机训练和批量训练的方法,包括了TensorFlow实现随机训练和批量训练的方法的使用技巧和注意事项,需要的朋友参考一下 TensorFlow更新模型变量。它能一次操作一个数据点,也可以一次操作大量数据。一个训练例子上的操作可能导致比较“古怪”的学习过程,但使用大批量的训练会造成计算成本昂贵。到底选用哪种训练类型对机器学习算法的收敛非常关键。 为了Tensor

  • 我目前正在使用TensorFlow Lite,我试图理解动态范围量化(DRQ)和全整数量化(FIQ)之间的区别。我知道在第一个(DRQ)中,只有权重是量化的,而在第二个(FIQ)中,权重和激活(输出)都是量化的。 然而,我不确定我是否完全理解这意味着什么。关于权重的量化,它们只是从float32转换到int8,还是进行另一种操作?同样,为什么需要一个有代表性的数据集来量化FIQ中的激活? 此外,我

  • 本文向大家介绍tensorflow 初始化未初始化的变量实例,包括了tensorflow 初始化未初始化的变量实例的使用技巧和注意事项,需要的朋友参考一下 今日在Stack Overflow上看到一个问如何只初始化未初始化的变量,有人提供了一个函数,特地粘贴过来共大家品鉴: 通过tf.global_variables()返回一个全局变量的列表global_vars, 然后以python列表解析式的

  • 最近,我读了很多关于keras批处理规范化的文章,讨论了很多。 根据该网站:设置“tf.layers.batch\u normalization”中的“training=False”,这样训练将获得更好的验证结果 答案是: 如果使用training=True启用批次标准化,则将开始标准化批次本身,并收集每个批次的平均值和方差的移动平均值。现在是棘手的部分。移动平均值是指数移动平均值,tf的默认动量

  • 在TensorFlow中执行批量规格化的正确方法是什么?(即,我不想计算连续均值和方差)。我当前的实现基于tf。nn。batch\u normalization(批次规格化),其中x是具有形状的卷积层的输出。[批次大小、宽度、高度、通道数]。我想在通道方面执行批处理规范。 但这种实施的结果非常糟糕。与tensorflow比较。承包商。苗条的batch\u norm显示其票价较低(同样糟糕的培训表现