def qconv_model(): x = x_in = keras.layers.Input((23, 23, 1), name="input") x = QActivation("quantized_relu(4)", name="QA_0")(x) x = QConv2D(16, 2, 2, kernel_quantizer=quantizers.binary(), bias_quantizer=quantizers.ternary(), name="qconv2d_1")(x) x = QConv2D(8, 2, 2, kernel_quantizer=quantizers.quantized_bits(4, 0, 1), bias_quantizer=quantizers.quantized_bits(4, 0, 1), activation=quantizers.quantized_relu(6, 2), name="qconv2D_2")(x) x = QConv2D(2, 2, 2, kernel_quantizer=quantizers.quantized_bits(4, 0, 1), bias_quantizer=quantizers.quantized_bits(4, 0, 1), activation=quantizers.quantized_relu(6, 2), name="qconv2d_3")(x) x = QActivation("quantized_bits(6, 0, 1)", name="QA_4")(x) model = keras.Model(inputs=[x_in], outputs=[x]) return model
def build_model(input_shape): x = x_in = Input(shape=input_shape, name="input") x = QConv2D( 32, (2, 2), strides=(2,2), kernel_quantizer=quantized_bits(4,0,1), bias_quantizer=quantized_bits(4,0,1), name="conv2d_0_m")(x) x = QActivation("quantized_relu(4,0)", name="act0_m")(x) x = QConv2D( 64, (3, 3), strides=(2,2), kernel_quantizer=quantized_bits(4,0,1), bias_quantizer=quantized_bits(4,0,1), name="conv2d_1_m")(x) x = QActivation("quantized_relu(4,0)", name="act1_m")(x) x = QConv2D( 64, (2, 2), strides=(2,2), kernel_quantizer=quantized_bits(4,0,1), bias_quantizer=quantized_bits(4,0,1), name="conv2d_2_m")(x) x = QActivation("quantized_relu(4,0)", name="act2_m")(x) x = Flatten()(x) x = QDense(num_classes, kernel_quantizer=quantized_bits(4,0,1), bias_quantizer=quantized_bits(4,0,1), name="dense")(x) x = Activation("softmax", name="softmax")(x) model = Model(inputs=[x_in], outputs=[x]) return model
def concatenate_qmodel(quantizer1, quantizer2, quantizer3): # Layer that concatenates a list of inputs. # It takes as input a list of tensors, all of the same shape except # for the concatenation axis, and returns a single tensor, # the concatenation of all inputs.. x1 = input1 = keras.layers.Input((16, 16, 1), name="input_0") x1 = QConv2D(16, 2, 2, kernel_quantizer=quantizer1, bias_quantizer=quantizer1, name="conv2d_0")(x1) x2 = input2 = keras.layers.Input((16, 16, 1), name="input_1") x2 = QConv2D(32, 2, 2, kernel_quantizer=quantizer2, bias_quantizer=quantizer2, name="conv2d_1")(x2) x3 = input3 = keras.layers.Input((16, 16, 1), name="input_2") x3 = QConv2D(64, 2, 2, kernel_quantizer=quantizer3, bias_quantizer=quantizer3, name="conv2d_2")(x3) x = keras.layers.concatenate([x1, x2, x3], axis=-1, name="concatenate") model = keras.Model(inputs=[input1, input2, input3], outputs=[x]) return model
def qbn_model_inference(): x = x_in = keras.layers.Input((23, 23, 1), name="input") x = QConv2D(4, 2, 23, kernel_quantizer=quantizers.quantized_bits(4, 0, 1, alpha=1.0), bias_quantizer=quantizers.quantized_bits(4, 0, 1, alpha=1.0), use_bias=False, name="qconv2d_1")(x) x = QBatchNormalization(mean_quantizer=quantizers.quantized_bits(6, 0, 1), gamma_quantizer=None, variance_quantizer=None, beta_quantizer=quantizers.quantized_bits(6, 0, 1), inverse_quantizer=quantizers.quantized_bits( 16, 0, 1), scale=False, center=False, gamma_range=8, beta_range=4, name="qbn_2")(x) x = QConv2D(2, 1, 1, kernel_quantizer=quantizers.quantized_bits(3, 0), bias_quantizer=quantizers.quantized_bits(3, 2), name="qconv2d_3")(x) model = keras.Model(inputs=[x_in], outputs=[x]) hw_weight_dict = model_save_quantized_weights(model) return (hw_weight_dict, model)
def qbn_model_inference(): x = x_in = keras.layers.Input((23, 23, 1), name="input") x = QConv2D(4, 2, 23, kernel_quantizer=quantizers.quantized_ulaw(4, 1, 1), bias_quantizer=quantizers.stochastic_ternary(), use_bias=False, name="qconv2d_1")(x) x = QBatchNormalization(gamma_quantizer=quantizers.quantized_relu_po2( 3, 2), variance_quantizer=quantizers.quantized_po2( 3, 2, quadratic_approximation=False), beta_quantizer=quantizers.quantized_bits(6, 0, 1), scale=False, center=False, gamma_range=8, beta_range=4, name="qbn_2")(x) x = QConv2D(2, 1, 1, kernel_quantizer=quantizers.quantized_po2(3, 0), bias_quantizer=quantizers.quantized_po2(3, 2), name="qconv2d_3")(x) model = keras.Model(inputs=[x_in], outputs=[x]) layer = model.get_layer("qbn_2") weight_arr = [ np.array([3, 4, 1, 7]), np.array([6, 4, 1, -7]), np.array([2, 7, -8, 2]), np.array([-1, -7, 4, 9]) ] # quantize the weights quantizer_list = layer.get_quantizers() for (i, quantizer) in enumerate(quantizer_list): if quantizer is not None: weight_arr[i] = keras.backend.eval( quantizer(keras.backend.constant(weight_arr[i]))) num_weights = 4 if not layer.scale: num_weights -= 1 if not layer.center: num_weights -= 1 layer.set_weights(weight_arr[:num_weights]) return model
def test_populate_bias_quantizer_from_accumulator(): """Test populate_bias_quantizer_from_accumulator function. Define a qkeras model with a QConv2DBatchnorm layer. Set bias quantizer in the layer as None. Call populate_bias_quantizer_from_accumulator function to automatically generate bias quantizer type from the MAC accumulator type. Set the bias quantizer accordingly in the model. Call populate_bias_quantizer_from_accumulator again in this model. This time since bias quantizer is already set, populate_bias_quantizer_from_accumulator function should not change the bias quantizer. """ x_shape = (2, 2, 1) # get a qkeras model with QConv2DBatchnorm layer. Set bias quantizer in the # layer as None. x = x_in = layers.Input(x_shape, name="input") x1 = QConv2D(filters=1, kernel_size=(1, 1), strides=(1, 1), use_bias=False, kernel_quantizer="quantized_bits(4, 0, 1)", name="conv2d_1")(x) x2 = QConv2D(filters=1, kernel_size=(1, 1), strides=(1, 1), use_bias=False, kernel_quantizer="quantized_bits(4, 0, 1)", name="conv2d_2")(x) x = layers.Maximum()([x1, x2]) x = QActivation("quantized_relu(4, 1)")(x) x = QConv2DBatchnorm( filters=2, kernel_size=(2, 2), strides=(4, 4), kernel_initializer="ones", bias_initializer="zeros", use_bias=False, kernel_quantizer="quantized_bits(4, 0, 1)", bias_quantizer=None, beta_initializer="zeros", gamma_initializer="ones", moving_mean_initializer="zeros", moving_variance_initializer="ones", folding_mode="batch_stats_folding", ema_freeze_delay=10, name="foldconv2d")(x) x1 = x x2 = layers.Flatten(name="flatten")(x) x2 = QDense(2, use_bias=False, kernel_initializer="ones", kernel_quantizer="quantized_bits(6, 2, 1)", name="dense")(x2) model = Model(inputs=[x_in], outputs=[x1, x2]) assert_equal(model.layers[5].get_quantizers()[1], None) # Call populate_bias_quantizer_from_accumulator function # to automatically generate bias quantizer from the MAC accumulator type. _ = bn_folding_utils.populate_bias_quantizer_from_accumulator( model, ["quantized_bits(8, 0, 1)"]) q = model.layers[5].get_quantizers()[1] assert_equal(q.__str__(), "quantized_bits(10,3,1)") # Call populate_bias_quantizer_from_accumulator function again # bias quantizer should not change _ = bn_folding_utils.populate_bias_quantizer_from_accumulator( model, ["quantized_bits(8, 0, 1)"]) q = model.layers[5].get_quantizers()[1] assert_equal(q.__str__(), "quantized_bits(10,3,1)")
def test_conv2d(): input_quantizers = None act = "quantized_bits(6, 0, 1)" weight = quantizers.quantized_relu_po2(4, 2) x = x_in = keras.layers.Input((23, 23, 1), name="input") x = QActivation(act, name="QA_0")(x) x = QConv2D(16, 2, 2, kernel_quantizer=weight, bias_quantizer=weight, name="qconv2d_1")(x) model = keras.Model(inputs=[x_in], outputs=[x]) dtype_dict = run(model, input_quantizers) multiplier = dtype_dict["qconv2d_1"]["multiplier"] accumulator = dtype_dict["qconv2d_1"]["accumulator"] op_count = dtype_dict["qconv2d_1"]["operation_count"] assert multiplier["quantizer_type"] == "quantized_bits" assert multiplier["bits"] == 15 assert multiplier["int_bits"] == 2 assert multiplier["is_signed"] == 1 assert multiplier["op_type"] == "shifter" assert accumulator["quantizer_type"] == "quantized_bits" assert accumulator["bits"] == 18 assert accumulator["int_bits"] == 5 assert accumulator["is_signed"] == 1 assert accumulator["op_type"] == "add" assert op_count == 7744
def create_mix_network(): xi = Input((28, 28, 1)) x = QConv2D(32, (3, 3), kernel_quantizer=binary())(xi) x = Activation("relu")(x) x = Conv2D(32, (3, 3))(x) x = Activation("softmax")(x) return Model(inputs=xi, outputs=x)
def get_model(quantize=False): x1 = input1 = keras.layers.Input((16, 16, 3), name="input_0") if quantize: x1 = QConv2D(16, 2, 2, kernel_quantizer=quantizers.quantized_bits(5, 0, 1), bias_quantizer=quantizers.quantized_bits(5, 0, 1), name="conv_0")(x1) else: x1 = keras.layers.Conv2D(16, 2, 2, name="conv_0")(x1) x2 = input2 = keras.layers.Input(shape=(16, 16, 3), name="input_1") if quantize: x2 = QConv2D(16, 2, 2, kernel_quantizer=quantizers.quantized_bits(5, 0, 1), bias_quantizer=quantizers.quantized_bits(5, 0, 1), name="conv_1")(x2) else: x2 = keras.layers.Conv2D(16, 2, 2, name="conv_1")(x2) x = keras.layers.add([x1, x2], name="add") if quantize: x = QActivation(activation="quantized_relu(8, 2)", name="relu")(x) else: x = keras.layers.Activation("relu", name="relu")(x) if quantize: x = QConv2D(2, 2, 2, kernel_quantizer=quantizers.quantized_bits(5, 0, 1), bias_quantizer=quantizers.quantized_bits(5, 0, 1), name="conv_2")(x) else: x = keras.layers.Conv2D(2, 2, 2, name="conv_2")(x) model = keras.Model(inputs=[input1, input2], outputs=[x]) return model
def po2_qbits_model(): x = x_in = keras.layers.Input((23, 23, 1), name="input") x = QActivation("quantized_relu_po2(3, 2)", name="QA_0")(x) x = QConv2D(16, 2, 2, kernel_quantizer=quantizers.quantized_bits(4, 0, 1), bias_quantizer=quantizers.quantized_bits(4, 0, 1), name="qconv2d_1")(x) model = keras.Model(inputs=[x_in], outputs=[x]) return model
def qkeras_cnn(name_, Inputs, nclasses, filters, kernel, strides, pooling, dropout, activation, pruning_params={}, qb=quantized_bits(6, 0, alpha=1)): length = len(filters) if any( len(lst) != length for lst in [filters, kernel, strides, pooling, dropout]): sys.exit( "One value for stride and kernel must be added for each filter! Exiting" ) x = x_in = Inputs x = BatchNormalization()(x) x = ZeroPadding2D(padding=(1, 1), data_format="channels_last")(x) for i, (f, k, s, p, d) in enumerate(zip(filters, kernel, strides, pooling, dropout)): print(( "Adding layer with {} filters, kernel_size=({},{}), strides=({},{})" ).format(f, k, k, s, s)) x = QConv2D(int(f), kernel_size=(int(k), int(k)), strides=(int(s), int(s)), kernel_quantizer=qb, bias_quantizer=qb, kernel_initializer='lecun_uniform', kernel_regularizer=l1(0.0001), use_bias=False, name='conv_%i' % i)(x) if float(p) != 0: x = MaxPooling2D(pool_size=(int(p), int(p)))(x) x = BatchNormalization()(x) x = Activation(activation, name='conv_act_%i' % i)(x) x = Flatten()(x) x = QDense(128, kernel_quantizer=qb, bias_quantizer=qb, kernel_initializer='lecun_uniform', kernel_regularizer=l1(0.0001), name='dense_1', use_bias=False)(x) x = Dropout(0.25)(x) x = BatchNormalization()(x) x = Activation(activation, name='dense_act')(x) x_out = Dense(nclasses, activation='softmax', name='output')(x) model = Model(inputs=[x_in], outputs=[x_out], name=name_) return model
def float_po2_model(): x = x_in = keras.layers.Input((23, 23, 1), name="input") x = QConv2D(16, 2, 2, kernel_quantizer=quantizers.quantized_po2(5, 0), bias_quantizer=quantizers.quantized_po2(5, 0), name="qconv2d_1")(x) x = QActivation("quantized_relu_po2(3, 2)", name="QA_0")(x) x = QConv2D(10, 2, 2, kernel_quantizer=quantizers.quantized_bits(5, 2, 1), bias_quantizer=quantizers.quantized_bits(5, 2, 1), name="qconv2d_0")(x) model = keras.Model(inputs=[x_in], outputs=[x]) for layer in model.layers: print(layer) print(layer.output_shape) return model
def get_models_with_one_layer(kernel_quantizer, folding_mode, ema_freeze_delay): x_shape = (2, 2, 1) loss_fn = tf.keras.losses.MeanSquaredError() optimizer = tf.keras.optimizers.SGD(learning_rate=1e-3) # define a model with seperate conv2d and bn layers x = x_in = layers.Input(x_shape, name="input") x = QConv2D( filters=2, kernel_size=(2, 2), strides=(4, 4), kernel_initializer="ones", bias_initializer="zeros", use_bias=False, kernel_quantizer=kernel_quantizer, bias_quantizer=None, name="conv2d")(x) x = layers.BatchNormalization( axis=-1, momentum=0.99, epsilon=0.001, center=True, scale=True, beta_initializer="zeros", gamma_initializer="ones", moving_mean_initializer="zeros", moving_variance_initializer="ones", beta_regularizer=None, gamma_regularizer=None, beta_constraint=None, gamma_constraint=None, renorm=False, renorm_clipping=None, renorm_momentum=0.99, fused=None, trainable=True, virtual_batch_size=None, adjustment=None, name="bn")(x) unfold_model = Model(inputs=[x_in], outputs=[x]) unfold_model.compile(loss=loss_fn, optimizer=optimizer, metrics="acc") x = x_in = layers.Input(x_shape, name="input") x = QConv2DBatchnorm( filters=2, kernel_size=(2, 2), strides=(4, 4), kernel_initializer="ones", bias_initializer="zeros", use_bias=False, kernel_quantizer=kernel_quantizer, beta_initializer="zeros", gamma_initializer="ones", moving_mean_initializer="zeros", moving_variance_initializer="ones", folding_mode=folding_mode, ema_freeze_delay=ema_freeze_delay, name="foldconv2d")(x) fold_model = Model(inputs=[x_in], outputs=[x]) fold_model.compile(loss=loss_fn, optimizer=optimizer, metrics="acc") return (unfold_model, fold_model)
def test_sequential_qnetwork(): model = tf.keras.Sequential() model.add(Input((28, 28, 1), name='input')) model.add( QConv2D(32, (2, 2), strides=(2, 2), kernel_quantizer=quantized_bits(4, 0, 1), bias_quantizer=quantized_bits(4, 0, 1), name='conv2d_0_m')) model.add(QActivation(quantized_relu(4, 0), name='act0_m')) model.add( QConv2D(64, (3, 3), strides=(2, 2), kernel_quantizer=quantized_bits(4, 0, 1), bias_quantizer=quantized_bits(4, 0, 1), name='conv2d_1_m')) model.add(QActivation(quantized_relu(4, 0), name='act1_m')) model.add( QConv2D(64, (2, 2), strides=(2, 2), kernel_quantizer=quantized_bits(4, 0, 1), bias_quantizer=quantized_bits(4, 0, 1), name='conv2d_2_m')) model.add(QActivation(quantized_relu(4, 0), name='act2_m')) model.add(Flatten()) model.add( QDense(10, kernel_quantizer=quantized_bits(4, 0, 1), bias_quantizer=quantized_bits(4, 0, 1), name='dense')) model.add(Activation('softmax', name='softmax')) # Check that all model operation were found correctly model_ops = extract_model_operations(model) for layer in model_ops.keys(): assert model_ops[layer]['type'][0] != 'null' return model
def build_layerwise_model(input_shape, **pruning_params): return Sequential([ prune.prune_low_magnitude( QConv2D( 32, (2, 2), strides=(2,2), kernel_quantizer=quantized_bits(4,0,1), bias_quantizer=quantized_bits(4,0,1), name="conv2d_0_m"), input_shape=input_shape, **pruning_params), QActivation("quantized_relu(4,0)", name="act0_m"), prune.prune_low_magnitude( QConv2D( 64, (3, 3), strides=(2,2), kernel_quantizer=quantized_bits(4,0,1), bias_quantizer=quantized_bits(4,0,1), name="conv2d_1_m"), **pruning_params), QActivation("quantized_relu(4,0)", name="act1_m"), prune.prune_low_magnitude( QConv2D( 64, (2, 2), strides=(2,2), kernel_quantizer=quantized_bits(4,0,1), bias_quantizer=quantized_bits(4,0,1), name="conv2d_2_m"), **pruning_params), QActivation("quantized_relu(4,0)", name="act2_m"), Flatten(), prune.prune_low_magnitude( QDense( num_classes, kernel_quantizer=quantized_bits(4,0,1), bias_quantizer=quantized_bits(4,0,1), name="dense"), **pruning_params), Activation("softmax", name="softmax") ])
def quantized_cnn(Inputs, nclasses, filters, kernel, strides, pooling, dropout, activation="quantized_relu(32,16)", quantizer_cnn=quantized_bits(1), quantizer_dense=quantized_bits(1)): length = len(filters) if any( len(lst) != length for lst in [filters, kernel, strides, pooling, dropout]): sys.exit( "One value for stride and kernel must be added for each filter! Exiting" ) x = x_in = Inputs for i, (f, k, s, p, d) in enumerate(zip(filters, kernel, strides, pooling, dropout)): print(( "Adding layer with {} filters, kernel_size=({},{}), strides=({},{})" ).format(f, k, k, s, s)) x = QConv2D(int(f), kernel_size=(int(k), int(k)), strides=(int(s), int(s)), kernel_quantizer=quantizer_cnn, bias_quantizer=quantizer_cnn, name='conv_%i' % i)(x) x = QActivation(activation)(x) x = BatchNormalization()(x) if float(p) != 0: x = MaxPooling2D(pool_size=(int(p), int(p)))(x) # x = Dropout(float(d))(x) x = Flatten()(x) x = QDense(128, kernel_quantizer=quantizer_dense, bias_quantizer=quantizer_dense)(x) x = QActivation(activation)(x) x = BatchNormalization()(x) x = Dense(nclasses)(x) model = Model(inputs=[x_in], outputs=[x]) return model
def get_qconv2d_model(input_shape, kernel_size, kernel_quantizer=None): num_class = 2 x = x_in = layers.Input(input_shape, name="input") x = QConv2D(filters=2, kernel_size=kernel_size, strides=(4, 4), kernel_initializer="ones", bias_initializer="zeros", use_bias=False, kernel_quantizer=kernel_quantizer, bias_quantizer=None, name="conv2d")(x) x = layers.BatchNormalization(axis=-1, momentum=0.99, epsilon=0.001, center=True, scale=True, beta_initializer="zeros", gamma_initializer="ones", moving_mean_initializer="zeros", moving_variance_initializer="ones", beta_regularizer=None, gamma_regularizer=None, beta_constraint=None, gamma_constraint=None, renorm=False, renorm_clipping=None, renorm_momentum=0.99, fused=None, trainable=True, virtual_batch_size=None, adjustment=None, name="bn")(x) x = layers.Flatten(name="flatten")(x) x = layers.Dense(num_class, use_bias=False, kernel_initializer="ones", name="dense")(x) x = layers.Activation("softmax", name="softmax")(x) model = Model(inputs=[x_in], outputs=[x]) return model
def gen_model(img_shape): img_input = x = keras.Input(shape=img_shape) x = QConv2D(filters=5, kernel_size=4, strides=4, kernel_quantizer=quantizers.quantized_bits( 8, 3, alpha="auto_po2"), bias_quantizer=quantizers.quantized_bits(8, 3), name="conv")(x) x = QActivation(activation=quantizers.quantized_relu(4, 0), name="act")(x) x = keras.layers.Flatten(name="flatten")(x) x = QDense(5, kernel_quantizer=quantizers.quantized_bits( 8, 0, alpha="auto_po2"), bias_quantizer=quantizers.quantized_bits(8, 3), name="dense")(x) model = keras.Model(inputs=img_input, outputs=[x]) return model
def init( self, printSummary=True ): # keep_negitive = 0 on inputs, otherwise for weights keep default (=1) encoded_dim = self.pams['encoded_dim'] CNN_layer_nodes = self.pams['CNN_layer_nodes'] CNN_kernel_size = self.pams['CNN_kernel_size'] CNN_pool = self.pams['CNN_pool'] Dense_layer_nodes = self.pams[ 'Dense_layer_nodes'] # does not include encoded layer channels_first = self.pams['channels_first'] inputs = Input( shape=self.pams['shape'] ) # adapt this if using `channels_first` image data format # load bits to quantize nBits_input = self.pams['nBits_input'] nBits_accum = self.pams['nBits_accum'] nBits_weight = self.pams['nBits_weight'] nBits_encod = self.pams['nBits_encod'] nBits_dense = self.pams[ 'nBits_dense'] if 'nBits_dense' in self.pams else nBits_weight nBits_conv = self.pams[ 'nBits_conv'] if 'nBits_conv' in self.pams else nBits_weight input_Qbits = self.GetQbits( nBits_input, keep_negative=1) #oddly fails if keep_neg=0 accum_Qbits = self.GetQbits(nBits_accum, keep_negative=1) dense_Qbits = self.GetQbits(nBits_dense, keep_negative=1) conv_Qbits = self.GetQbits(nBits_conv, keep_negative=1) encod_Qbits = self.GetQbits(nBits_encod, keep_negative=1) # keeping weights and bias same precision for now # define model x = inputs x = QActivation(input_Qbits, name='input_qa')(x) for i, n_nodes in enumerate(CNN_layer_nodes): if channels_first: x = QConv2D(n_nodes, CNN_kernel_size[i], activation='relu', padding='same', data_format='channels_first', name="conv2d_" + str(i) + "_m", kernel_quantizer=conv_Qbits, bias_quantizer=conv_Qbits)(x) else: x = QConv2D(n_nodes, CNN_kernel_size[i], activation='relu', padding='same', name="conv2d_" + str(i) + "_m", kernel_quantizer=conv_Qbits, bias_quantizer=conv_Qbits)(x) if CNN_pool[i]: if channels_first: x = MaxPooling2D((2, 2), padding='same', data_format='channels_first', name="mp_" + str(i))(x) else: x = MaxPooling2D((2, 2), padding='same', name="mp_" + str(i))(x) shape = K.int_shape(x) x = QActivation(accum_Qbits, name='accum1_qa')(x) x = Flatten(name="flatten")(x) # encoder dense nodes for i, n_nodes in enumerate(Dense_layer_nodes): x = QDense(n_nodes, activation='relu', name="en_dense_" + str(i), kernel_quantizer=dense_Qbits, bias_quantizer=dense_Qbits)(x) x = QDense(encoded_dim, activation='relu', name='encoded_vector', kernel_quantizer=dense_Qbits, bias_quantizer=dense_Qbits)(x) encodedLayer = QActivation(encod_Qbits, name='encod_qa')(x) # Instantiate Encoder Model self.encoder = Model(inputs, encodedLayer, name='encoder') if printSummary: self.encoder.summary() encoded_inputs = Input(shape=(encoded_dim, ), name='decoder_input') x = encoded_inputs # decoder dense nodes for i, n_nodes in enumerate(Dense_layer_nodes): x = Dense(n_nodes, activation='relu', name="de_dense_" + str(i))(x) x = Dense(shape[1] * shape[2] * shape[3], activation='relu', name='de_dense_final')(x) x = Reshape((shape[1], shape[2], shape[3]), name="de_reshape")(x) for i, n_nodes in enumerate(CNN_layer_nodes): if CNN_pool[i]: if channels_first: x = UpSampling2D((2, 2), data_format='channels_first', name="up_" + str(i))(x) else: x = UpSampling2D((2, 2), name="up_" + str(i))(x) if channels_first: x = Conv2DTranspose(n_nodes, CNN_kernel_size[i], activation='relu', padding='same', data_format='channels_first', name="conv2D_t_" + str(i))(x) else: x = Conv2DTranspose(n_nodes, CNN_kernel_size[i], activation='relu', padding='same', name="conv2D_t_" + str(i))(x) if channels_first: # shape[0] will be # of channel x = Conv2DTranspose(filters=self.pams['shape'][0], kernel_size=CNN_kernel_size[0], padding='same', data_format='channels_first', name="conv2d_t_final")(x) else: x = Conv2DTranspose(filters=self.pams['shape'][2], kernel_size=CNN_kernel_size[0], padding='same', name="conv2d_t_final")(x) x = QActivation(input_Qbits, name='q_decoder_output')(x) #Verify this step needed? outputs = Activation('sigmoid', name='decoder_output')(x) self.decoder = Model(encoded_inputs, outputs, name='decoder') if printSummary: self.decoder.summary() self.autoencoder = Model(inputs, self.decoder(self.encoder(inputs)), name='autoencoder') if printSummary: self.autoencoder.summary() if self.pams['loss'] == "weightedMSE": self.autoencoder.compile(loss=self.weightedMSE, optimizer='adam') self.encoder.compile(loss=self.weightedMSE, optimizer='adam') elif self.pams['loss'] != '': self.autoencoder.compile(loss=self.pams['loss'], optimizer='adam') self.encoder.compile(loss=self.pams['loss'], optimizer='adam') else: self.autoencoder.compile(loss='mse', optimizer='adam') self.encoder.compile(loss='mse', optimizer='adam') CNN_layers = '' if len(CNN_layer_nodes) > 0: CNN_layers += '_Conv' for i, n in enumerate(CNN_layer_nodes): CNN_layers += f'_{n}x{CNN_kernel_size[i]}' if CNN_pool[i]: CNN_layers += 'pooled' Dense_layers = '' if len(Dense_layer_nodes) > 0: Dense_layers += '_Dense' for n in Dense_layer_nodes: Dense_layers += f'_{n}' self.name = f'Autoencoded{CNN_layers}{Dense_layers}_Encoded_{encoded_dim}' if not self.weights_f == '': self.autoencoder.load_weights(self.weights_f)
def test_qnetwork(): x = x_in = Input((28, 28, 1), name='input') x = QSeparableConv2D( 32, (2, 2), strides=(2, 2), depthwise_quantizer="binary", pointwise_quantizer=quantized_bits(4, 0, 1), depthwise_activation=quantized_bits(6, 2, 1), bias_quantizer=quantized_bits(4, 0, 1), name='conv2d_0_m')( x) x = QActivation('quantized_relu(6,2,1)', name='act0_m')(x) x = QConv2D( 64, (3, 3), strides=(2, 2), kernel_quantizer="ternary", bias_quantizer=quantized_bits(4, 0, 1), name='conv2d_1_m', activation=quantized_relu(6, 3, 1))( x) x = QConv2D( 64, (2, 2), strides=(2, 2), kernel_quantizer=quantized_bits(6, 2, 1), bias_quantizer=quantized_bits(4, 0, 1), name='conv2d_2_m')( x) x = QActivation('quantized_relu(6,4,1)', name='act2_m')(x) x = Flatten(name='flatten')(x) x = QDense( 10, kernel_quantizer=quantized_bits(6, 2, 1), bias_quantizer=quantized_bits(4, 0, 1), name='dense')( x) x = Activation('softmax', name='softmax')(x) model = Model(inputs=[x_in], outputs=[x]) # reload the model to ensure saving/loading works json_string = model.to_json() clear_session() model = quantized_model_from_json(json_string) # generate same output for weights np.random.seed(42) for layer in model.layers: all_weights = [] for i, weights in enumerate(layer.get_weights()): input_size = np.prod(layer.input.shape.as_list()[1:]) if input_size is None: input_size = 576 * 10 # to avoid learning sizes shape = weights.shape assert input_size > 0, 'input size for {} {}'.format(layer.name, i) # he normal initialization with a scale factor of 2.0 all_weights.append( 10.0 * np.random.normal(0.0, np.sqrt(2.0 / input_size), shape)) if all_weights: layer.set_weights(all_weights) # apply quantizer to weights model_save_quantized_weights(model) all_weights = [] for layer in model.layers: for i, weights in enumerate(layer.get_weights()): w = np.sum(weights) all_weights.append(w) all_weights = np.array(all_weights) # test_qnetwork_weight_quantization all_weights_signature = np.array( [2., -6.75, -0.625, -2., -0.25, -56., 1.125, -1.625, -1.125]) assert all_weights.size == all_weights_signature.size assert np.all(all_weights == all_weights_signature) # test_qnetwork_forward: expected_output = np.array([[0.e+00, 0.e+00, 0.e+00, 0.e+00, 0.e+00, 0.e+00, 1.e+00, 0.e+00, 0.e+00, 0.e+00], [0.e+00, 0.e+00, 0.e+00, 0.e+00, 0.e+00, 0.e+00, 1.e+00, 0.e+00, 0.e+00, 0.e+00], [0.e+00, 0.e+00, 0.e+00, 0.e+00, 0.e+00, 0.e+00, 0.e+00, 0.e+00, 6.e-08, 1.e+00], [0.e+00, 0.e+00, 0.e+00, 0.e+00, 0.e+00, 0.e+00, 1.e+00, 0.e+00, 0.e+00, 0.e+00], [0.e+00 ,0.e+00, 0.e+00, 0.e+00, 0.e+00, 0.e+00, 1.e+00, 0.e+00, 0.e+00, 0.e+00], [0.e+00, 0.e+00, 0.e+00, 0.e+00, 0.e+00, 0.e+00, 0.e+00, 0.e+00, 5.e-07, 1.e+00], [0.e+00, 0.e+00, 0.e+00, 0.e+00, 0.e+00, 0.e+00 ,1.e+00, 0.e+00, 0.e+00, 0.e+00], [0.e+00, 1.e+00, 0.e+00, 0.e+00, 0.e+00, 0.e+00 ,0.e+00, 0.e+00, 0.e+00, 0.e+00], [0.e+00, 0.e+00, 0.e+00, 0.e+00, 1.e+00, 0.e+00, 0.e+00, 0.e+00, 0.e+00, 0.e+00], [0.e+00, 0.e+00, 0.e+00, 0.e+00, 0.e+00, 1.e+00, 0.e+00, 0.e+00, 0.e+00, 0.e+00]]).astype(np.float16) inputs = 2 * np.random.rand(10, 28, 28, 1) actual_output = model.predict(inputs).astype(np.float16) assert_allclose(actual_output, expected_output, rtol=1e-4)
def test_qnetwork(): x = x_in = Input((28, 28, 1), name='input') x = QSeparableConv2D(32, (2, 2), strides=(2, 2), depthwise_quantizer=binary(), pointwise_quantizer=quantized_bits(4, 0, 1), depthwise_activation=quantized_bits(6, 2, 1), bias_quantizer=quantized_bits(4, 0, 1), name='conv2d_0_m')(x) x = QActivation('quantized_relu(6,2,1)', name='act0_m')(x) x = QConv2D(64, (3, 3), strides=(2, 2), kernel_quantizer=ternary(), bias_quantizer=quantized_bits(4, 0, 1), name='conv2d_1_m')(x) x = QActivation('quantized_relu(6, 3, 1)', name='act1_m')(x) x = QConv2D(64, (2, 2), strides=(2, 2), kernel_quantizer=quantized_bits(6, 2, 1), bias_quantizer=quantized_bits(4, 0, 1), name='conv2d_2_m')(x) x = QActivation('quantized_relu(6,4,1)', name='act2_m')(x) x = Flatten(name='flatten')(x) x = QDense(10, kernel_quantizer=quantized_bits(6, 2, 1), bias_quantizer=quantized_bits(4, 0, 1), name='dense')(x) x = Activation('softmax', name='softmax')(x) model = Model(inputs=[x_in], outputs=[x]) # generate same output for weights np.random.seed(42) for layer in model.layers: all_weights = [] for i, weights in enumerate(layer.get_weights()): input_size = np.prod(layer.input.shape.as_list()[1:]) if input_size is None: input_size = 576 * 10 # hack to avoid learning sizes shape = weights.shape assert input_size > 0, 'input size for {} {}'.format(layer.name, i) # he normal initialization with a scale factor of 2.0 all_weights.append( 10.0 * np.random.normal(0.0, np.sqrt(2.0 / input_size), shape)) if all_weights: layer.set_weights(all_weights) # apply quantizer to weights model_save_quantized_weights(model) all_weights = [] for layer in model.layers: for i, weights in enumerate(layer.get_weights()): w = np.sum(weights) all_weights.append(w) all_weights = np.array(all_weights) # test_qnetwork_weight_quantization all_weights_signature = np.array( [2.0, -6.75, -0.625, -2.0, -0.25, -56.0, 1.125, -2.625, -0.75]) assert all_weights.size == all_weights_signature.size assert np.all(all_weights == all_weights_signature) # test_qnetwork_forward: y = np.array([[ 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 5.341e-02, 9.468e-01, 0.000e+00, 0.000e+00, 0.000e+00 ], [ 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 5.960e-08, 0.000e+00, 1.919e-01, 0.000e+00, 0.000e+00, 8.081e-01 ], [ 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 2.378e-04, 0.000e+00, 0.000e+00, 0.000e+00, 2.843e-05, 9.995e-01 ], [ 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 1.000e+00, 0.000e+00, 0.000e+00, 0.000e+00 ], [ 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 1.000e+00, 0.000e+00, 2.623e-06, 0.000e+00 ], [ 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 7.749e-07, 0.000e+00, 0.000e+00, 1.634e-04, 1.000e+00 ], [ 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 1.000e+00, 0.000e+00, 0.000e+00, 0.000e+00 ], [ 0.000e+00, 1.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 6.557e-07, 0.000e+00, 0.000e+00, 0.000e+00 ], [ 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 1.000e+00, 0.000e+00, 5.960e-08, 0.000e+00, 0.000e+00, 0.000e+00 ], [ 0.000e+00, 0.000e+00, 0.000e+00, 0.000e+00, 9.125e-03, 9.907e-01, 9.418e-06, 0.000e+00, 5.597e-05, 0.000e+00 ]]).astype(np.float16) inputs = 2 * np.random.rand(10, 28, 28, 1) p = model.predict(inputs).astype(np.float16) assert np.all(p == y)