2929from tensorflow .keras .backend import clear_session
3030from tensorflow .keras .utils import to_categorical
3131from tensorflow .keras import metrics
32+ import pytest
3233
3334from qkeras import QConv2DBatchnorm
3435from qkeras import QConv2D
36+ from qkeras import QDenseBatchnorm
3537from qkeras import QDense
3638from qkeras import QActivation
3739from qkeras import QDepthwiseConv2D
@@ -110,7 +112,7 @@ def get_qconv2d_batchnorm_model(input_shape, kernel_size, folding_mode,
110112 return model
111113
112114
113- def get_models_with_one_layer (kernel_quantizer , folding_mode , ema_freeze_delay ):
115+ def get_conv2d_models_with_one_layer (kernel_quantizer , folding_mode , ema_freeze_delay ):
114116
115117 x_shape = (2 , 2 , 1 )
116118 loss_fn = tf .keras .losses .MeanSquaredError ()
@@ -164,6 +166,60 @@ def get_models_with_one_layer(kernel_quantizer, folding_mode, ema_freeze_delay):
164166 return (unfold_model , fold_model )
165167
166168
169+ def get_dense_models_with_one_layer (kernel_quantizer , folding_mode , ema_freeze_delay ):
170+
171+ x_shape = (4 ,)
172+ loss_fn = tf .keras .losses .MeanSquaredError ()
173+ optimizer = get_sgd_optimizer (learning_rate = 1e-3 )
174+
175+ # define a model with seperate conv2d and bn layers
176+ x = x_in = layers .Input (x_shape , name = "input" )
177+ x = QDense (
178+ 2 ,
179+ kernel_initializer = "ones" ,
180+ bias_initializer = "zeros" , use_bias = False ,
181+ kernel_quantizer = kernel_quantizer , bias_quantizer = None ,
182+ name = "conv2d" )(x )
183+ x = layers .BatchNormalization (
184+ axis = - 1 ,
185+ momentum = 0.99 ,
186+ epsilon = 0.001 ,
187+ center = True ,
188+ scale = True ,
189+ beta_initializer = "zeros" ,
190+ gamma_initializer = "ones" ,
191+ moving_mean_initializer = "zeros" ,
192+ moving_variance_initializer = "ones" ,
193+ beta_regularizer = None ,
194+ gamma_regularizer = None ,
195+ beta_constraint = None ,
196+ gamma_constraint = None ,
197+ renorm = False ,
198+ renorm_clipping = None ,
199+ renorm_momentum = 0.99 ,
200+ fused = None ,
201+ trainable = True ,
202+ virtual_batch_size = None ,
203+ adjustment = None ,
204+ name = "bn" )(x )
205+ unfold_model = Model (inputs = [x_in ], outputs = [x ])
206+ unfold_model .compile (loss = loss_fn , optimizer = optimizer , metrics = "acc" )
207+
208+ x = x_in = layers .Input (x_shape , name = "input" )
209+ x = QDenseBatchnorm (
210+ 2 ,
211+ kernel_initializer = "ones" , bias_initializer = "zeros" , use_bias = False ,
212+ kernel_quantizer = kernel_quantizer , beta_initializer = "zeros" ,
213+ gamma_initializer = "ones" , moving_mean_initializer = "zeros" ,
214+ moving_variance_initializer = "ones" , folding_mode = folding_mode ,
215+ ema_freeze_delay = ema_freeze_delay ,
216+ name = "foldconv2d" )(x )
217+ fold_model = Model (inputs = [x_in ], outputs = [x ])
218+ fold_model .compile (loss = loss_fn , optimizer = optimizer , metrics = "acc" )
219+
220+ return (unfold_model , fold_model )
221+
222+
167223def get_debug_model (model ):
168224 layer_output_list = []
169225 for layer in model .layers :
@@ -181,10 +237,7 @@ def generate_dataset(train_size=10,
181237 output_shape = None ):
182238 """create tf.data.Dataset with shape: (N,) + input_shape."""
183239
184- x_train = np .random .randint (
185- 4 , size = (train_size , input_shape [0 ], input_shape [1 ], input_shape [2 ]))
186- x_train = np .random .rand (
187- train_size , input_shape [0 ], input_shape [1 ], input_shape [2 ])
240+ x_train = np .random .rand (* (train_size ,) + input_shape )
188241
189242 if output_shape :
190243 y_train = np .random .random_sample ((train_size ,) + output_shape )
@@ -397,31 +450,48 @@ def test_loading():
397450 assert_equal (weight1 [1 ], weight2 [1 ])
398451
399452
400- def test_same_training_and_prediction ():
453+ @pytest .mark .parametrize ("model_name" , ["conv2d" , "dense" ])
454+ def test_same_training_and_prediction (model_name ):
401455 """test if fold/unfold layer has the same training and prediction output."""
402456
403457 epochs = 5
404458 loss_fn = tf .keras .losses .MeanSquaredError ()
405459 loss_metric = metrics .Mean ()
406460 optimizer = get_sgd_optimizer (learning_rate = 1e-3 )
407461
408- x_shape = (2 , 2 , 1 )
409- kernel = np .array ([[[[1. , 1. ]], [[1. , 0. ]]], [[[1. , 1. ]], [[0. , 1. ]]]])
410- gamma = np .array ([2. , 1. ])
411- beta = np .array ([0. , 1. ])
412- moving_mean = np .array ([1. , 1. ])
413- moving_variance = np .array ([1. , 2. ])
462+ if model_name == "conv2d" :
463+ x_shape = (2 , 2 , 1 )
464+ kernel = np .array ([[[[1. , 1. ]], [[1. , 0. ]]], [[[1. , 1. ]], [[0. , 1. ]]]])
465+ gamma = np .array ([2. , 1. ])
466+ beta = np .array ([0. , 1. ])
467+ moving_mean = np .array ([1. , 1. ])
468+ moving_variance = np .array ([1. , 2. ])
469+ elif model_name == "dense" :
470+ x_shape = (4 ,)
471+ kernel = np .array ([[1. , 1. ], [1. , 0. ], [1. , 1. ], [0. , 1. ]])
472+ gamma = np .array ([2. , 1. ])
473+ beta = np .array ([0. , 1. ])
474+ moving_mean = np .array ([1. , 1. ])
475+ moving_variance = np .array ([1. , 2. ])
414476 iteration = np .array (- 1 )
415477
416478 train_ds = generate_dataset (train_size = 10 , batch_size = 10 , input_shape = x_shape ,
417479 num_class = 2 )
418480
419- (unfold_model , fold_model_batch ) = get_models_with_one_layer (
420- kernel_quantizer = None , folding_mode = "batch_stats_folding" ,
421- ema_freeze_delay = 10 )
422- (_ , fold_model_ema ) = get_models_with_one_layer (
423- kernel_quantizer = None , folding_mode = "ema_stats_folding" ,
424- ema_freeze_delay = 10 )
481+ if model_name == "conv2d" :
482+ (unfold_model , fold_model_batch ) = get_conv2d_models_with_one_layer (
483+ kernel_quantizer = None , folding_mode = "batch_stats_folding" ,
484+ ema_freeze_delay = 10 )
485+ (_ , fold_model_ema ) = get_conv2d_models_with_one_layer (
486+ kernel_quantizer = None , folding_mode = "ema_stats_folding" ,
487+ ema_freeze_delay = 10 )
488+ elif model_name == "dense" :
489+ (unfold_model , fold_model_batch ) = get_dense_models_with_one_layer (
490+ kernel_quantizer = None , folding_mode = "batch_stats_folding" ,
491+ ema_freeze_delay = 10 )
492+ (_ , fold_model_ema ) = get_dense_models_with_one_layer (
493+ kernel_quantizer = None , folding_mode = "ema_stats_folding" ,
494+ ema_freeze_delay = 10 )
425495
426496 unfold_model .layers [1 ].set_weights ([kernel ])
427497 unfold_model .layers [2 ].set_weights (
@@ -455,12 +525,20 @@ def test_same_training_and_prediction():
455525 # models should be different, but the two folding modes should be the same
456526 epochs = 5
457527 iteration = np .array (8 )
458- (unfold_model , fold_model_batch ) = get_models_with_one_layer (
459- kernel_quantizer = None , folding_mode = "batch_stats_folding" ,
460- ema_freeze_delay = 10 )
461- (_ , fold_model_ema ) = get_models_with_one_layer (
462- kernel_quantizer = None , folding_mode = "ema_stats_folding" ,
463- ema_freeze_delay = 10 )
528+ if model_name == "conv2d" :
529+ (unfold_model , fold_model_batch ) = get_conv2d_models_with_one_layer (
530+ kernel_quantizer = None , folding_mode = "batch_stats_folding" ,
531+ ema_freeze_delay = 10 )
532+ (_ , fold_model_ema ) = get_conv2d_models_with_one_layer (
533+ kernel_quantizer = None , folding_mode = "ema_stats_folding" ,
534+ ema_freeze_delay = 10 )
535+ elif model_name == "dense" :
536+ (unfold_model , fold_model_batch ) = get_dense_models_with_one_layer (
537+ kernel_quantizer = None , folding_mode = "batch_stats_folding" ,
538+ ema_freeze_delay = 10 )
539+ (_ , fold_model_ema ) = get_dense_models_with_one_layer (
540+ kernel_quantizer = None , folding_mode = "ema_stats_folding" ,
541+ ema_freeze_delay = 10 )
464542 unfold_model .layers [1 ].set_weights ([kernel ])
465543 unfold_model .layers [2 ].set_weights (
466544 [gamma , beta , moving_mean , moving_variance ])
0 commit comments