parameters: (op, grad)
return_statement: return input_gradients
docstring: The gradient of RoutingFunction.
  
    Args:
      op: The RoutingFunction op.
      grad: Gradient with respect to the output of the RoutingFunction op.
  
    Returns:
      Gradients with respect to the input of the RoutingFunction op.
docstring_summary: The gradient of RoutingFunction.
docstring_tokens: The gradient of RoutingFunction .
function: def _KFeatureRoutingFunctionGradient(op, grad):
    """The gradient of RoutingFunction.
  
    Args:
      op: The RoutingFunction op.
      grad: Gradient with respect to the output of the RoutingFunction op.
  
    Returns:
      Gradients with respect to the input of the RoutingFunction op.
    """
    gradient_op = _training_ops.k_feature_gradient
  
    input_data_tensor = op.inputs[0]
    tree_weights_tensor = op.inputs[1]
    tree_thresholds_tensor = op.inputs[2]
  
    routing_function_tensor = op.outputs[0]
  
    # The derivatives below are each defined over one or two of three dimensions:
    # (batch_size, num_nodes, num_features).  We explicitly expand each derivative
    # to three dimensions to ensure that they're broadcasted correctly.
    du_df_raw, df_dx_raw, df_dt_raw = gradient_op(
        input_data_tensor,
        tree_weights_tensor,
        tree_thresholds_tensor,
        routing_function_tensor,
        layer_num=op.get_attr('layer_num'),
        random_seed=op.get_attr('random_seed'))
  
    # dl / du is the derivative of the loss with respect to the output of the
    # routing function, which is provided by tensorflow.
    #
    # dl / du has dimension (batch_size, num_nodes), which we expand to
    # (batch_size, num_nodes, 1).
    dl_du = array_ops.expand_dims(grad, 2)
  
    # du / df is the derivative of the output of the routing function with respect
    # to the decision function at each node.  It is computed by
    # single_feature_routing_gradient_op.cc.
    #
    # du / df has dimension (batch_size, num_nodes), which we expand to
    # (batch_size, num_nodes, 1).
    du_df = array_ops.expand_dims(du_df_raw, 2)
  
    # df / dx is the derivative of the decision function with respect to the input
    # data.  f(x) = (-t * x + b), so df / dx = -t for the selected features and
    # zero elsewhere.
    #
    # df / dx has dimension (num_nodes, num_features), which we expand to
    # (1, num_nodes, num_features).
    df_dx = array_ops.expand_dims(df_dx_raw, 0)
  
    # df / dt is the derivative of the decision function with respect to its
    # parameters. f(x) = (-t * x + b), so df / dt = -x[feature].
    #
    # df / dt has dimension (batch_size, num_nodes, num_features).
    df_dt = -df_dt_raw
  
    # df / dt is the derivative of the decision function with respect to its
    # bias parameter. f(x) = (-t * x + b), so df / dt = 1.
    #
    # df / db has dimension (num_nodes), which we expand to
    # (1, num_nodes, 1).
    df_db = array_ops.expand_dims(
        array_ops.expand_dims(array_ops.ones_like(tree_thresholds_tensor), 0), 2)
  
    # Compute the derivatives of the loss with respect to the inputs using the
    # chain rule (backpropagation).
    dl_dx = math_ops.reduce_mean(dl_du * du_df * df_dx, 1)
    dl_dt = math_ops.reduce_mean(dl_du * du_df * df_dt, 0)
    dl_db = math_ops.reduce_mean(array_ops.squeeze(dl_du * du_df * df_db, [2]), 0)
  
    input_gradients = [dl_dx, dl_dt, dl_db]
  
    return input_gradients
function_tokens: def _KFeatureRoutingFunctionGradient ( op , grad ) : gradient_op = _training_ops . k_feature_gradient input_data_tensor = op . inputs [ 0 ] tree_weights_tensor = op . inputs [ 1 ] tree_thresholds_tensor = op . inputs [ 2 ] routing_function_tensor = op . outputs [ 0 ] # The derivatives below are each defined over one or two of three dimensions: # (batch_size, num_nodes, num_features).  We explicitly expand each derivative # to three dimensions to ensure that they're broadcasted correctly. du_df_raw , df_dx_raw , df_dt_raw = gradient_op ( input_data_tensor , tree_weights_tensor , tree_thresholds_tensor , routing_function_tensor , layer_num = op . get_attr ( 'layer_num' ) , random_seed = op . get_attr ( 'random_seed' ) ) # dl / du is the derivative of the loss with respect to the output of the # routing function, which is provided by tensorflow. # # dl / du has dimension (batch_size, num_nodes), which we expand to # (batch_size, num_nodes, 1). dl_du = array_ops . expand_dims ( grad , 2 ) # du / df is the derivative of the output of the routing function with respect # to the decision function at each node.  It is computed by # single_feature_routing_gradient_op.cc. # # du / df has dimension (batch_size, num_nodes), which we expand to # (batch_size, num_nodes, 1). du_df = array_ops . expand_dims ( du_df_raw , 2 ) # df / dx is the derivative of the decision function with respect to the input # data.  f(x) = (-t * x + b), so df / dx = -t for the selected features and # zero elsewhere. # # df / dx has dimension (num_nodes, num_features), which we expand to # (1, num_nodes, num_features). df_dx = array_ops . expand_dims ( df_dx_raw , 0 ) # df / dt is the derivative of the decision function with respect to its # parameters. f(x) = (-t * x + b), so df / dt = -x[feature]. # # df / dt has dimension (batch_size, num_nodes, num_features). df_dt = - df_dt_raw # df / dt is the derivative of the decision function with respect to its # bias parameter. f(x) = (-t * x + b), so df / dt = 1. # # df / db has dimension (num_nodes), which we expand to # (1, num_nodes, 1). df_db = array_ops . expand_dims ( array_ops . expand_dims ( array_ops . ones_like ( tree_thresholds_tensor ) , 0 ) , 2 ) # Compute the derivatives of the loss with respect to the inputs using the # chain rule (backpropagation). dl_dx = math_ops . reduce_mean ( dl_du * du_df * df_dx , 1 ) dl_dt = math_ops . reduce_mean ( dl_du * du_df * df_dt , 0 ) dl_db = math_ops . reduce_mean ( array_ops . squeeze ( dl_du * du_df * df_db , [ 2 ] ) , 0 ) input_gradients = [ dl_dx , dl_dt , dl_db ] return input_gradients