from tensorflow.python.ops import math_ops from tensorflow.python.ops import variables from tensorflow.python.framework import dtypes import numpy as _np def convex_add(input_layer, layer_3, initial_convex_par=0.5, trainable=False): """ Do a convex combination of input_layer and layer_3. That is, return the output of lamda* input_layer + (1 - lamda) * layer_3 Args: input_layer (tf.Tensor): Input to take convex combinatio of layer_3 (tf.Tensor): Input to take convex combinatio of initial_convex_par (float): Initial value for convex parameter. Must be in [0, 1]. trainable (bool): Whether convex parameter should be trainable or not. Returns: tf.Tensor: Result of convex combination """ # Will implement this as sigmoid(p)*input_layer + (1-sigmoid(p))*layer_3 to ensure # convex parameter to be in the unit interval without constraints during # optimization # Find value for p, also check for legal initial_convex_par if initial_convex_par < 0: raise ValueError("Convex parameter must be >=0") elif initial_convex_par == 0: # sigmoid(-16) is approximately a 32bit roundoff error, practically 0 initial_p_value = -16 elif initial_convex_par < 1: # Compute inverse of sigmoid to find initial p value initial_p_value = -_np.log(1 / initial_convex_par - 1) elif initial_convex_par == 1: # Same argument as for 0 initial_p_value = 16 else: raise ValueError("Convex parameter must be <=1") p = variables.Variable( initial_value=initial_p_value, dtype=dtypes.float32, trainable=trainable ) lam = math_ops.sigmoid(p) return input_layer * lam + (1 - lam) * layer_3