我想知道在Tensorflow 2中进行量化感知训练期间,用于模拟BatchNorm折叠的当前可用选项是什么。Tensorflow 1具有tf.contrib.quantize.create_training_graph
函数,该函数将FakeQuantization层插入到图形中并负责模拟批量归一化折叠(根据此white paper)。
Tensorflow 2在他们最近采用的tf.keras
API中有一个关于如何使用量化的tutorial,但他们没有提及有关批标准化的任何内容。我尝试了一个带有BatchNorm层的简单示例:
import tensorflow_model_optimization as tfmo
model = tf.keras.Sequential([
l.Conv2D(32, 5, padding='same', activation='relu', input_shape=input_shape),
l.MaxPooling2D((2, 2), (2, 2), padding='same'),
l.Conv2D(64, 5, padding='same', activation='relu'),
l.BatchNormalization(), # BN!
l.MaxPooling2D((2, 2), (2, 2), padding='same'),
l.Flatten(),
l.Dense(1024, activation='relu'),
l.Dropout(0.4),
l.Dense(num_classes),
l.Softmax(),
])
model = tfmo.quantization.keras.quantize_model(model)
但是,它具有以下例外情况:
RuntimeError: Layer batch_normalization:<class 'tensorflow.python.keras.layers.normalization.BatchNormalization'> is not supported. You can quantize this layer by passing a `tfmot.quantization.keras.QuantizeConfig` instance to the `quantize_annotate_layer` API.
表示TF不知道如何处理。
我还看到了this related topic在tf.contrib.quantize.create_training_graph
应用于keras构造的模型上的情况。但是,他们不使用BatchNorm图层,因此我不确定这是否可行。
那么在TF2中使用此BatchNorm折叠功能有哪些选择?可以通过keras API来完成此操作,还是应该切换回TensorFlow 1 API并以旧的方式定义图形?
答案 0 :(得分:1)
如果在激活之前添加BatchNormalization,则量化不会有问题。注意:仅当量化层恰好位于Conv2D层之后时,BatchNormalization中才支持量化。 https://www.tensorflow.org/model_optimization/guide/quantization/training
# Change
l.Conv2D(64, 5, padding='same', activation='relu'),
l.BatchNormalization(), # BN!
# with this
l.Conv2D(64, 5, padding='same'),
l.BatchNormalization(),
l.Activation('relu'),
#Other way of declaring the same
o = (Conv2D(512, (3, 3), padding='valid' , data_format=IMAGE_ORDERING))(o)
o = (BatchNormalization())(o)
o = Activation('relu')(o)
答案 1 :(得分:1)
您应该按照说明应用量化注释。我想您现在可以像这样调用BatchNorm:
class DefaultBNQuantizeConfig(tfmot.quantization.keras.QuantizeConfig):
def get_weights_and_quantizers(self, layer):
return []
def get_activations_and_quantizers(self, layer):
return []
def set_quantize_weights(self, layer, quantize_weights):
pass
def set_quantize_activations(self, layer, quantize_activations):
pass
def get_output_quantizers(self, layer):
return []
def get_config(self):
return {}
如果您仍然想对图层进行量化,请将get_weights_and_quantizers的返回值更改为return [(layer.weights[i], LastValueQuantizer(num_bits=8, symmetric=True, narrow_range=False, per_axis=False)) for i in range(2)]
。然后根据上面返回列表的索引,将量化器设置为gamma,beta,...,位于set_quantize_weights