import tensorflow as tf

            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,
                            no_batch_norm=False, W_d=None, W_p=None,  is_train=False):
        if W_d is None:
            W_d = self._make_var('W_d', (filter_size, filter_size, ch, ch_mul))
        if W_p is None:
            W_p = self._make_var('W_p', (1, 1, ch_mul * ch, ch))
