| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| """Drop path operation. |
| |
| This scripts implements the drop path operation, proposed in |
| Gao Huang, Yu Sun, Zhuang Liu, Daniel Sedra, Kilian Weinberger, |
| Deep Networks with Stochastic Depth. In ECCV, 2016. |
| """ |
| import tensorflow as tf |
|
|
|
|
| def get_drop_path_keep_prob(keep_prob_for_last_stage, schedule, |
| current_stage, num_stages): |
| """Gets drop path keep probability for current stage. |
| |
| Args: |
| keep_prob_for_last_stage: A float, the drop path keep probability for |
| last stage. This flag is used in conjunction with the flag `schedule`, as |
| they together determine drop path keep probability for the other stages. |
| schedule: A string, the drop path schedule. Currently, we support |
| 'constant': use the same drop path keep probability for all stages, and |
| 'linear': linearly decrease the drop path keep probability from 1.0 at |
| 0-th stage (or STEM) to `keep_prob_for_last_stage` at last stage. |
| current_stage: An integer, current stage number. |
| num_stages: An integer, the number of stages. |
| |
| Returns: |
| The drop path keep probability for the current stage. |
| |
| Raises: |
| ValueError: If schedule is not supported. |
| """ |
| if schedule == 'constant': |
| return keep_prob_for_last_stage |
| elif schedule == 'linear': |
| return 1.0 - (1.0 - keep_prob_for_last_stage) * current_stage / num_stages |
| else: |
| raise ValueError('Unexpected schedule %s.' % schedule) |
|
|
|
|
| def generate_drop_path_random_mask(input_tensor, drop_path_keep_prob): |
| """Generates a random mask for drop path. |
| |
| This function generates a random mask for training models with drop path. Each |
| scalar in the output indicates whether the block or path will be kept. The |
| scalars are scaled with (1.0 / drop_path_keep_prob) so that the output will |
| have the same expectation no mather what the drop_path_keep_prob is. |
| |
| Reference: |
| "Deep Networks with Stochastic Depth" https://arxiv.org/pdf/1603.09382.pdf |
| |
| Args: |
| input_tensor: An input [batch_size, n_1, n_2, ..., n_k] tensor. |
| drop_path_keep_prob: A float, the keep probability for dropping path. |
| |
| Returns: |
| binary_tensor: A [batch_size, 1, 1, ..., 1] tensor with the same dtype as |
| the input_tensor. |
| """ |
| binary_tensor = None |
| if drop_path_keep_prob < 1.0: |
| input_shape = input_tensor.get_shape().as_list() |
| random_tensor_shape = [input_shape[0]] + [1] * (len(input_shape) - 1) |
| random_tensor = drop_path_keep_prob |
| random_tensor += tf.random.uniform( |
| random_tensor_shape, dtype=input_tensor.dtype) |
| binary_tensor = tf.math.divide(tf.floor(random_tensor), drop_path_keep_prob) |
| return binary_tensor |
|
|
|
|
| class DropPath(tf.keras.layers.Layer): |
| """Drop path layer. |
| |
| For details, please see the original paper listed below. |
| Gao Huang, Yu Sun, Zhuang Liu, Daniel Sedra, Kilian Weinberger, |
| Deep Networks with Stochastic Depth. In ECCV, 2016. |
| """ |
|
|
| def __init__(self, drop_path_keep_prob=1.0, name=None): |
| """Initializes a drop path layer. |
| |
| Args: |
| drop_path_keep_prob: A float, the keep probability for dropping path. |
| name: An optional string specifying the operation name. |
| |
| Rasies: |
| ValueError: If drop_path_keep_prob is <= 0 or > 1. |
| """ |
| super(DropPath, self).__init__(name=name) |
| self._drop_path_keep_prob = drop_path_keep_prob |
| if self._drop_path_keep_prob <= 0 or self._drop_path_keep_prob > 1.0: |
| raise ValueError('drop_path_keep_prob not valid. Got %f.' % |
| self._drop_path_keep_prob) |
|
|
| def call(self, input_tensor, training=False): |
| """Performs a forward pass. |
| |
| Args: |
| input_tensor: An input tensor of type tf.Tensor with shape [batch, height, |
| width, channels]. |
| training: A boolean flag indicating whether training behavior should be |
| used (default: False). |
| |
| Returns: |
| The output tensor. |
| """ |
| if self._drop_path_keep_prob == 1.0 or not training: |
| return input_tensor |
| drop_path_random_mask = generate_drop_path_random_mask( |
| input_tensor, self._drop_path_keep_prob) |
| if drop_path_random_mask is not None: |
| input_tensor = input_tensor * drop_path_random_mask |
| return input_tensor |
|
|
| def get_config(self): |
| config = { |
| 'drop_path_keep_prob': self._drop_path_keep_prob, |
| } |
| base_config = super(DropPath, self).get_config() |
| return dict(list(base_config.items()) + list(config.items())) |
|
|