我想在 Tensorflow 2.5 中使用自定义层进行量化感知训练 (QAT)
我按照指南:
https://www.tensorflow.org/model_optimization/guide/quantization/training_comprehensive_guide
我已经创建了图层:
class RotateLayer(layers.Layer):
def __init__(self , **kwargs):
super(RotateLayer, self).__init__()
filter_size = 4
num_of_filters = 64
self._filter_size = filter_size
self._num_of_filters = num_of_filters
def build(self , input_shape):
# create filter
n = self._filter_size ** 2 * self._num_of_filters
w_init = tf.random_normal_initializer(stddev=np.sqrt(2. / n))
self.kernel = []
self.kernel.append(self.add_weight(initializer=w_init, shape=(self._filter_size,self._filter_size,1,self._num_of_filters),dtype="float32", name='kernel_rotate', trainable=True))
self.kernel.append(self.add_weight(initializer=w_init , shape=(1, self._num_of_filters), dtype="float32",name='bias_rotate', trainable=True))
return
def call(self, x):
_, H, W, _ = x.shape
output_rotate_i = []
for i in range(self._filter_size):
output_rotate_j = []
for j in range(self._filter_size):
out = tf.nn.conv2d(x[:, i:, j:, :], tf.roll(self.kernel[0], shift=[-i, -j], axis=[1, 2]),strides=self._filter_size, padding='VALID', data_format='NHWC')
out = tf.nn.bias_add(out , tf.squeeze(self.kernel[1]))
output_rotate_j.append(out)
output_rotate_i.append(tf.stack(output_rotate_j , axis=3))
output_rotate = tf.stack(output_rotate_i , axis=2)
output_rotate = tf.reshape(output_rotate , shape=(-1 , H , W , self._num_of_filters))
return output_rotate
和配置:
class RotateLayerQuantizeConfig(tfmot.quantization.keras.QuantizeConfig):
# Configure how to quantize weights.
def get_weights_and_quantizers(self, layer):
return [(layer.kernel, 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, 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 {}
我已经将包含层的模型转换为量化感知:
model_to_quantize = quantize_annotate_model(model)
with quantize_scope(
{'RotateLayerQuantizeConfig': RotateLayerQuantizeConfig,
'RotateLayer': RotateLayer}):
quant_aware_model = tfmot.quantization.keras.quantize_apply(model)
模型已成功转换,但是,通过检查变量和权重,我发现它们对于特定层并不相同。(对于其他未定义为自定义图层的图层,它们是相同的!)
似乎权重已重新初始化,而不是从原始模型(非量化)克隆权重。
这里我的层的变量不一样(层是0和1,0的例子)层名称:model_to_quantize.trainable_variables[0].name is 'quantize_annotate/kernel_rotate:0' quant_aware_model.trainable_variables[0].name是'rotate_layer_2/kernel_rotate:0'
tf.abs(model_to_quantize.trainable_variables[0] - quant_aware_model.trainable_variables[0]).numpy().max()
Out: 0.23129302
对于其他层,它是相同的:层名称:model_to_quantize.trainable_variables[2].name is 'conv2d/kernel:0' quant_aware_model.trainable_variables[2].name is 'conv2d/kernel:0'
tf.abs(model_to_quantize.trainable_variables[2] - quant_aware_model.trainable_variables[2]).numpy().max()
Out: 0.0