def ComputeDown(self, layer, step):
    """Backpropagate through this layer.
    Args:
      step: The training step. Needed because some hyperparameters depend on
      which training step they are being used in.
    """
    if layer.is_input:  # Nobody to backprop to.
      return
    # At this point layer.deriv contains the derivative with respect to the
    # outputs of this layer. Compute derivative with respect to the inputs.
    h = layer.hyperparams
    loss = None
    if h.fast_dropout:
      if layer.hyperparams.sparsity:
        layer.AddSparsityGradient()
      loss = self.GetFastDropoutGradient(layer)
    else:
      if layer.is_output:
        loss = layer.GetLoss(get_deriv=True)
      else:
        if layer.hyperparams.sparsity:
          layer.AddSparsityGradient()
        layer.ComputeDeriv()
    # Now layer.deriv contains the derivative w.r.t to the inputs.
    # Send it down each incoming edge and update parameters on the edge.
    for edge in layer.incoming_edge:
      if edge.conv or edge.local:
        AccumulateConvDeriv(edge.node1, edge, layer.deriv)
      else:
        self.AccumulateDeriv(edge.node1, edge, layer.deriv)
      self.UpdateEdgeParams(edge, layer.deriv, step)
    # Update the parameters on this layer (i.e., the bias).
    self.UpdateLayerParams(layer, step)
    return loss
Backpropagate through this layer.
    Args:
      step: The training step. Needed because some hyperparameters depend on
      which training step they are being used in.
    
deepnet/fastdropoutnet.py