code: def random_targets(gt, nb_classes):
    
    # 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
docs: 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.