def build(self) -> tf.keras.models.Model: x = self.stem_module(self.section_filters[0], self.image_input) for block, (layers, filters) in enumerate( zip(self.section_blocks, self.section_filters)): for layer in range(layers): if filters != x.shape[-1]: x = self.transition_block(x, filters, strides=2) x = self.residual_block(x) if self.include_top: x = tf.keras.layers.Activation("relu")(x) x = utils.global_pool(x) x = lq.layers.QuantDense( self.num_classes, kernel_initializer="glorot_normal", )(x) x = tf.keras.layers.Activation("softmax", dtype="float32")(x) model = tf.keras.Model(inputs=self.image_input, outputs=x, name=self.name) # Load weights. if self.weights == "imagenet": weights_path = (self.imagenet_weights_path if self.include_top else self.imagenet_no_top_weights_path) model.load_weights(weights_path) elif self.weights is not None: model.load_weights(self.weights) return model
def _scale_binary_conv_output(self, conv_input: tf.Tensor, conv_output: tf.Tensor, name: str) -> tf.Tensor: """Data-dependent convolution scaling. Scales the output of the convolution in the (squeeze-and-excite style) data-dependent way described in Section 4.3 of Martinez at. al. """ in_filters = conv_input.shape[-1] out_filters = conv_output.shape[-1] z = utils.global_pool(conv_input, name=f"{name}_scaling_pool") dim_reduction = tf.keras.layers.Dense( int(in_filters // self.scaling_r), activation="relu", kernel_initializer="he_normal", kernel_regularizer=self.kernel_regularizer, name=f"{name}_scaling_dense_reduce", use_bias=False, )(z) dim_expansion = tf.keras.layers.Dense( out_filters, activation="sigmoid", kernel_initializer="he_normal", kernel_regularizer=self.kernel_regularizer, name=f"{name}_scaling_dense_expand", use_bias=False, )(dim_reduction) scales = tf.keras.layers.Reshape( (1, 1, out_filters), name=f"{name}_scaling_reshape")(dim_expansion) return tf.keras.layers.Multiply(name=f"{name}_scaling_multiplication")( [conv_output, scales])
def build(self) -> tf.keras.models.Model: x = stem_module(self.stem_filters, self.image_input) for block, (layers, filters, use_squeeze_and_excite) in enumerate( zip( self.blocks_per_section, self.section_filters, self.use_squeeze_and_excite_in_section, )): for layer in range(layers): if filters == x.shape[-1]: x = self.residual_block(x, use_squeeze_and_excite) else: strides = 1 if (block == 0 or layer != 0) else 2 x = self.transition_block(x, filters, strides, use_squeeze_and_excite) x = tf.keras.layers.Activation("relu")(x) if self.include_top: x = utils.global_pool(x) x = tf.keras.layers.Dense(self.num_classes, kernel_initializer="glorot_normal")(x) x = tf.keras.layers.Activation("softmax", dtype="float32")(x) model = tf.keras.Model(inputs=self.image_input, outputs=x, name=self.name) return model
def build(self) -> tf.keras.models.Model: # Layer 1 out = tf.keras.layers.Conv2D( self.filters, (7, 7), strides=2, kernel_initializer=self.kernel_initializer, padding="same", use_bias=False, )(self.image_input) out = tf.keras.layers.BatchNormalization(momentum=0.8)(out) out = tf.keras.layers.MaxPool2D((3, 3), strides=2, padding="same")(out) # Layer 2 out = self.residual_block(out, filters=self.filters) # Layer 3 - 5 for _ in range(3): out = self.residual_block(out) # Layer 6 - 17 for _ in range(3): out = self.residual_block(out, double_filters=True) for _ in range(3): out = self.residual_block(out) # Layer 18 if self.include_top: out = utils.global_pool(out) out = tf.keras.layers.Dense(self.num_classes)(out) out = tf.keras.layers.Activation("softmax", dtype="float32")(out) model = tf.keras.Model(inputs=self.image_input, outputs=out, name="birealnet18") # Load weights. if self.weights == "imagenet": # Download appropriate file if self.include_top: weights_path = utils.download_pretrained_model( model="birealnet", version="v0.3.0", file="birealnet_weights.h5", file_hash= "6e6efac1584fcd60dd024198c87f42eb53b5ec719a5ca1f527e1fe7e8b997117", ) else: weights_path = utils.download_pretrained_model( model="birealnet", version="v0.3.0", file="birealnet_weights_notop.h5", file_hash= "5148b61c0c2a1094bdef811f68bf4957d5ba5f83ad26437b7a4a6855441ab46b", ) model.load_weights(weights_path) elif self.weights is not None: model.load_weights(self.weights) return model
def last_block(self, x: tf.Tensor, name: str = "") -> tf.Tensor: """Last block, shared across ResNet, StrongBaselineNet and Real-to-Bin nets.""" x = utils.global_pool(x, name=f"{name}_global_pool") x = tf.keras.layers.Dense( self.num_classes, name=f"{name}_logits", )(x) return tf.keras.layers.Softmax(name=f"{name}_probs", dtype=tf.float32)(x)
def build_model(input_res=(32, 32), data_format="channels_first"): if data_format == "channels_first": input_shape = (3, input_res[0], input_res[1]) else: input_shape = (input_res[0], input_res[1], 3) inp = tf.keras.Input(shape=input_shape) x = tf.keras.layers.Conv2D(6, 3, 2, data_format=data_format)(inp) x = utils.global_pool(x, data_format=data_format) x = tf.keras.layers.Dense(2)(x) return tf.keras.Model(inputs=inp, outputs=x)
def test_global_pool(input_res, data_format): shape = (3, *input_res) if data_format == "channels_first" else (*input_res, 3) inp = tf.keras.Input(shape=shape) x = tf.keras.layers.Conv2D(6, 3, 2, data_format=data_format)(inp) x = utils.global_pool(x, data_format=data_format) x = tf.keras.layers.Dense(2)(x) model = tf.keras.Model(inp, x) assert model.outputs[0].shape.as_list() == [None, 2]
def squeeze_and_excite(inp: tf.Tensor, filters: int, r: int = 16): """Squeeze and Excite as per [Squeeze-and-Excitation Networks](https://arxiv.org/abs/1709.01507). Use of S&E in BNNs was pioneered in [Training binary neural networks with real-to-binary convolutions](https://openreview.net/forum?id=BJg4NgBKvH). """ out = utils.global_pool(inp) out = tf.keras.layers.Dense( inp.shape[-1] // r, activation="relu", kernel_initializer="he_normal", use_bias=False, kernel_regularizer=tf.keras.regularizers.l2(1e-5), )(out) out = tf.keras.layers.Dense( filters, activation="sigmoid", kernel_initializer="he_normal", use_bias=False, kernel_regularizer=tf.keras.regularizers.l2(1e-5), )(out) return tf.reshape(out, [-1, 1, 1, filters])
def build(self) -> tf.keras.models.Model: x = self.image_input x = self.group_stem(x, name="stem") for i, (n, f) in enumerate(zip(self.num_blocks, self.transition_features)): for j in range(n): x = self.block(x, f"section_{i}_block_{j}") if f: x = self.transition_block(x, f, f"section_{i}_transition") x = self.norm(x, "head_bn") x = self.act(x, "head_relu") if self.include_top: x = utils.global_pool(x, name="head_globalpool") x = tf.keras.layers.Dense( self.num_classes, kernel_initializer=self.kernel_initializer, name="head_dense", )(x) x = tf.keras.layers.Activation( "softmax", dtype="float32", name="head_softmax" )(x) model = tf.keras.models.Model( inputs=self.image_input, outputs=x, name=self.name ) if self.weights == "imagenet": model.load_weights( self.imagenet_weights_path if self.include_top else self.imagenet_no_top_weights_path ) elif self.weights is not None: model.load_weights(self.weights) return model
def build(self) -> BinaryDenseNet: if self.image_input.shape[1] and self.image_input.shape[1] < 50: x = tf.keras.layers.Conv2D( self.initial_filters, kernel_size=3, padding="same", kernel_initializer="he_normal", use_bias=False, )(self.image_input) else: x = tf.keras.layers.Conv2D( self.initial_filters, kernel_size=7, strides=2, padding="same", kernel_initializer="he_normal", use_bias=False, )(self.image_input) x = tf.keras.layers.BatchNormalization(momentum=0.9, epsilon=1e-5)(x) x = tf.keras.layers.Activation("relu")(x) x = tf.keras.layers.MaxPool2D(3, strides=2, padding="same")(x) for block, layers_per_block in enumerate(self.layers): for _ in range(layers_per_block): x = self.densely_connected_block(x, self.dilation_rate[block]) if block < len(self.layers) - 1: x = tf.keras.layers.BatchNormalization(momentum=0.9, epsilon=1e-5)(x) if self.dilation_rate[block + 1] == 1: x = tf.keras.layers.MaxPooling2D(2, strides=2)(x) x = tf.keras.layers.Activation("relu")(x) x = tf.keras.layers.Conv2D( round(x.shape.as_list()[-1] // self.reduction[block] / 32) * 32, kernel_size=1, kernel_initializer="he_normal", use_bias=False, )(x) x = tf.keras.layers.BatchNormalization(momentum=0.9, epsilon=1e-5)(x) x = tf.keras.layers.Activation("relu")(x) if self.include_top: x = utils.global_pool(x) x = tf.keras.layers.Dense(self.num_classes, kernel_initializer="he_normal")(x) x = tf.keras.layers.Activation("softmax", dtype="float32")(x) model = BinaryDenseNet(inputs=self.image_input, outputs=x, name=self.name) if self.weights == "imagenet": if self.include_top: weights_path = self.imagenet_weights_path else: weights_path = self.imagenet_no_top_weights_path model.load_weights(weights_path) elif self.weights is not None: model.load_weights(self.weights) return model
def build(self) -> tf.keras.models.Model: if self.image_input.shape[1] and self.image_input.shape[1] < 50: x = tf.keras.layers.Conv2D( self.initial_filters, kernel_size=3, padding="same", kernel_initializer="he_normal", use_bias=False, )(self.image_input) else: x = tf.keras.layers.Conv2D( self.initial_filters, kernel_size=7, strides=2, padding="same", kernel_initializer="he_normal", use_bias=False, )(self.image_input) x = tf.keras.layers.BatchNormalization(momentum=0.9, epsilon=1e-5)(x) x = tf.keras.layers.Activation("relu")(x) x = tf.keras.layers.MaxPool2D(3, strides=2, padding="same")(x) x = tf.keras.layers.BatchNormalization(momentum=0.9, epsilon=1e-5)(x) for block, (layers, filters) in enumerate(zip(*self.spec)): # This trick adds shortcut connections between original ResNet # blocks. We wultiply the number of blocks by two, but add only one # layer instead of two in each block for layer in range(layers * 2): strides = 1 if block == 0 or layer != 0 else 2 x = self.residual_block(x, filters, strides=strides) x = tf.keras.layers.Activation("relu")(x) if self.include_top: x = utils.global_pool(x) x = tf.keras.layers.Dense(self.num_classes, kernel_initializer="glorot_normal")(x) x = tf.keras.layers.Activation("softmax", dtype="float32")(x) model = tf.keras.Model( inputs=self.image_input, outputs=x, name=f"binary_resnet_e_{self.num_layers}", ) # Load weights. if self.weights == "imagenet": # Download appropriate file if self.include_top: weights_path = utils.download_pretrained_model( model="resnet_e", version="v0.1.0", file="resnet_e_18_weights.h5", file_hash= "bde4a64d42c164a7b10a28debbe1ad5b287c499bc0247ecb00449e6e89f3bf5b", ) else: weights_path = utils.download_pretrained_model( model="resnet_e", version="v0.1.0", file="resnet_e_18_weights_notop.h5", file_hash= "14cb037e47d223827a8d09db88ec73d60e4153a4464dca847e5ae1a155e7f525", ) model.load_weights(weights_path) elif self.weights is not None: model.load_weights(self.weights) return model