def call(self, inputs): # Channels first arrangement: (batch_size, num_input_channels, width, height) # Channels last arrangement: (batch_size, width, height, num_input_channels) # If activation quantisation is enabled if self.binarise_input: # Compute the axis ID of the channels. Use tensorflow channels last arrangement as standard channels_axis = 3 if self.data_format == 'channels_first': channels_axis = 1 # Compute A, which is the average across channels. # The input will thus reduce to a single-channel image # In Keras, (minibatch_size, 1, height, width) A = K.mean(K.abs(inputs), axis=channels_axis, keepdims=True) # k filter should be of shape (filter_size, filter_size, 1, 1) as per keras 2 notation # K is of shape (batch_size, 1, width, height) (using channels first data format) K_variable = K.conv2d(A, self.k_filter, strides=self.strides, padding=self.padding, data_format=self.data_format, dilation_rate=self.dilation_rate) # Binarise the input binarisedInput = passthroughSign(inputs) # Call the base convolution operation # Convolution output will be of shape (batch_size, width, height, num_output_channels) (channels first) convolutionOutput = K.conv2d(binarisedInput, self.kernel, strides=self.strides, padding=self.padding, data_format=self.data_format, dilation_rate=self.dilation_rate) # Copy K for each output channel # K will thus go from shape (batch_size, 1, width, height) to (batch_size, 1, width, height) # (with channels_first data format) if K.backend() == 'tensorflow': K_variable = K.repeat_elements( K_variable, K.int_shape(convolutionOutput)[channels_axis], axis=channels_axis) else: K_variable = K.repeat_elements( K_variable, K.shape(convolutionOutput)[channels_axis], axis=channels_axis) outputs = K_variable * convolutionOutput return outputs else: # Call the base convolution operation. Only the weights are quantised in this case return super(XNORNetConv2D, self).call(inputs)
def call(self, inputs): # For theano, binarisation is done as a seperate layer if K.backend() == 'tensorflow': binarisedInput = passthroughSign(inputs) else: binarisedInput = inputs return super().call(binarisedInput)
def call(self, inputs): # In BinaryNet, the output activation is binarised (normally done at the input to each layer in our implementation) return passthroughSign(inputs)