Take in an array of correct labels and randomly select a different label
  for each label in the array. This is typically used to randomly select a
  target class in targeted adversarial examples attacks (i.e., when the
  search algorithm takes in both a source class and target class to compute
  the adversarial example).
  :param gt: the ground truth (correct) labels. They can be provided as a
             1D vector or 2D array of one-hot encoded labels.
  :param nb_classes: The number of classes for this task. The random class
                     will be chosen between 0 and nb_classes such that it
                     is different from the correct class.
  :return: A numpy array holding the randomly-selected target classes
           encoded as one-hot labels.

def random_targets(gt, nb_classes):
  """
  Take in an array of correct labels and randomly select a different label
  for each label in the array. This is typically used to randomly select a
  target class in targeted adversarial examples attacks (i.e., when the
  search algorithm takes in both a source class and target class to compute
  the adversarial example).
  :param gt: the ground truth (correct) labels. They can be provided as a
             1D vector or 2D array of one-hot encoded labels.
  :param nb_classes: The number of classes for this task. The random class
                     will be chosen between 0 and nb_classes such that it
                     is different from the correct class.
  :return: A numpy array holding the randomly-selected target classes
           encoded as one-hot labels.
  """
  # If the ground truth labels are encoded as one-hot, convert to labels.
  if len(gt.shape) == 2:
    gt = np.argmax(gt, axis=1)

  # This vector will hold the randomly selected labels.
  result = np.zeros(gt.shape, dtype=np.int32)

  for class_ind in xrange(nb_classes):
    # Compute all indices in that class.
    in_cl = gt == class_ind
    size = np.sum(in_cl)

    # Compute the set of potential targets for this class.
    potential_targets = other_classes(nb_classes, class_ind)

    # Draw with replacement random targets among the potential targets.
    result[in_cl] = np.random.choice(potential_targets, size=size)

  # Encode vector of random labels as one-hot labels.
  result = to_categorical(result, nb_classes)
  result = result.astype(np.int32)

  return result