import tensorflow as tf

        start_y = tf.random.uniform(shape=(1,), minval=0, maxval=im_height, dtype=tf.int32)
        mask = tf.pad(mask, [[cutout_size + start_y[0], im_height - start_y[0]],
                            [cutout_size + start_x[0], im_width - start_x[0]]])
        mask = mask[cutout_size: cutout_size + im_height,
                    cutout_size: cutout_size + im_width]
        mask = tf.tile(tf.reshape(mask, (im_height, im_width, 1)), (1, 1, 3))
        image = tf.where(tf.equal(mask, 0), x=image, y=tf.zeros_like(image))
        return image

    def _add_drop_path(self, X, keep_prob):
        with tf.variable_scope('drop_path'):
            batch_size = tf.shape(X)[0]
            noise_shape = (batch_size, 1, 1, 1)
            random_tensor = keep_prob + tf.random_uniform(noise_shape, dtype=tf.float32)
            binary_tensor = tf.floor(random_tensor)
            X = (X / keep_prob) * binary_tensor
        return X

    def _do_conv(self, X, w, h, in_ch, out_ch, filter_size=1, no_relu=False, no_reg=False, is_train=False):
        W = self._make_var('W', (filter_size, filter_size, in_ch, out_ch), no_reg=no_reg)
        if not no_relu:
            X = tf.nn.relu(X)
        X = tf.nn.conv2d(X, W, (1, 1, 1, 1), padding='SAME')
        X = self._add_batch_norm(X, out_ch, is_train=is_train)
        X = tf.reshape(X, (-1, w, h, out_ch)) # Sanity shape check
        return X

    def _do_separable_conv(self, X, w, h, ch, filter_size=3, stride=1, ch_mul=1,
