(spanning_leaves,
                             margin=50,
                             desired_num_valid_classes=150,
                             desired_num_test_classes=150)
return {'valid': valid_root, 'test': test_root}
Propose roots for the validation and test sub-graphs.

  This is done as follows: each subgraph root will be the Synset that spans the
  largest number of leaves that still meets the criterion of spanning a number
  of leaves within its allowable range, which is: desired number of classes for
  that split +/- margin. We aim to include approx. 70% / 15% / 15% of the
  classes in the training / validation / testing splits, resp.

  Args:
    spanning_leaves: A dict mapping each Synset to the leaf Synsets that are
      reachable from it.
    margin: The number of additional or fewer leaves that the root of a split's
      subgraph can span compared to the expected number of classes for the
      corresponding split. This is needed for this splitting method, as there
      may not be a node in the tree that spans exactly the expected number of
      classes for some split.
    desired_num_valid_classes: num classes desirably assigned to the validation
      split. ILSVRC 2012 has a total of 1000 classes, so 15% corresponds to 150
      classes, hence the default value of 150.
    desired_num_test_classes: similarly as above, but for the test split.

  Returns:
    a dict that maps 'valid' and 'test' to the synset that spans the leaves that
      will desirably be assigned to that split.

  Raises:
    RuntimeError: When no candidate subgraph roots are available with the given
      margin value.
Propose roots for the validation and test sub-graphs.
Propose roots for the validation and test sub - graphs .
def propose_valid_test_roots(spanning_leaves,
                             margin=50,
                             desired_num_valid_classes=150,
                             desired_num_test_classes=150):
  """Propose roots for the validation and test sub-graphs.

  This is done as follows: each subgraph root will be the Synset that spans the
  largest number of leaves that still meets the criterion of spanning a number
  of leaves within its allowable range, which is: desired number of classes for
  that split +/- margin. We aim to include approx. 70% / 15% / 15% of the
  classes in the training / validation / testing splits, resp.

  Args:
    spanning_leaves: A dict mapping each Synset to the leaf Synsets that are
      reachable from it.
    margin: The number of additional or fewer leaves that the root of a split's
      subgraph can span compared to the expected number of classes for the
      corresponding split. This is needed for this splitting method, as there
      may not be a node in the tree that spans exactly the expected number of
      classes for some split.
    desired_num_valid_classes: num classes desirably assigned to the validation
      split. ILSVRC 2012 has a total of 1000 classes, so 15% corresponds to 150
      classes, hence the default value of 150.
    desired_num_test_classes: similarly as above, but for the test split.

  Returns:
    a dict that maps 'valid' and 'test' to the synset that spans the leaves that
      will desirably be assigned to that split.

  Raises:
    RuntimeError: When no candidate subgraph roots are available with the given
      margin value.
  """
  # Sort in decreasing order of the length of the lists of spanning leaves, so
  # e.g. the node that spans the most leaves will be the first element.  Ties
  # are broken by the WordNet ID of the Synset.
  def _sort_key(synset_and_leaves):
    synset, leaves = synset_and_leaves
    return (len(leaves), synset.wn_id)

  spanning_leaves_sorted = sorted(six.iteritems(spanning_leaves), key=_sort_key)
  spanning_leaves_sorted.reverse()

  # Get the candidate roots for the validation and test sub-graphs, by finding
  # the nodes whose number of spanning leaves are within the
  # allowed margin.
  valid_candidates, test_candidates = [], []
  for s, leaves in spanning_leaves_sorted:
    num_leaves = len(leaves)
    low_limit_valid = desired_num_valid_classes - margin
    high_limit_valid = desired_num_valid_classes + margin
    if low_limit_valid < num_leaves and num_leaves < high_limit_valid:
      valid_candidates.append(s)
    low_limit_test = desired_num_test_classes - margin
    high_limit_test = desired_num_test_classes + margin
    if low_limit_test < num_leaves and num_leaves < high_limit_test:
      test_candidates.append(s)

  if not valid_candidates or not test_candidates:
    raise RuntimeError('Found no root candidates. Try a different margin.')

  # For displaying the list of candidates
  for cand in valid_candidates:
    logging.info('Candidate %s, %s with %d spanning leaves', cand.words,
                 cand.wn_id, len(spanning_leaves[cand]))

  # Propose the first possible candidate for each of validation and test
  valid_root = valid_candidates[0]
  # Make sure not to choose the same root for testing as for validation
  test_candidate_ind = 0
  test_root = test_candidates[test_candidate_ind]
  while test_root == valid_root:
    test_candidate_ind += 1
    if test_candidate_ind == len(test_candidates):
      raise RuntimeError('No candidates for test root. Try a different margin.')
    test_root = test_candidates[test_candidate_ind]

  return {'valid': valid_root, 'test': test_root}
def propose_valid_test_roots ( spanning_leaves , margin = 50 , desired_num_valid_classes = 150 , desired_num_test_classes = 150 ) : # Sort in decreasing order of the length of the lists of spanning leaves, so # e.g. the node that spans the most leaves will be the first element.  Ties # are broken by the WordNet ID of the Synset. def _sort_key ( synset_and_leaves ) : synset , leaves = synset_and_leaves return ( len ( leaves ) , synset . wn_id ) spanning_leaves_sorted = sorted ( six . iteritems ( spanning_leaves ) , key = _sort_key ) spanning_leaves_sorted . reverse ( ) # Get the candidate roots for the validation and test sub-graphs, by finding # the nodes whose number of spanning leaves are within the # allowed margin. valid_candidates , test_candidates = [ ] , [ ] for s , leaves in spanning_leaves_sorted : num_leaves = len ( leaves ) low_limit_valid = desired_num_valid_classes - margin high_limit_valid = desired_num_valid_classes + margin if low_limit_valid < num_leaves and num_leaves < high_limit_valid : valid_candidates . append ( s ) low_limit_test = desired_num_test_classes - margin high_limit_test = desired_num_test_classes + margin if low_limit_test < num_leaves and num_leaves < high_limit_test : test_candidates . append ( s ) if not valid_candidates or not test_candidates : raise RuntimeError ( 'Found no root candidates. Try a different margin.' ) # For displaying the list of candidates for cand in valid_candidates : logging . info ( 'Candidate %s, %s with %d spanning leaves' , cand . words , cand . wn_id , len ( spanning_leaves [ cand ] ) ) # Propose the first possible candidate for each of validation and test valid_root = valid_candidates [ 0 ] # Make sure not to choose the same root for testing as for validation test_candidate_ind = 0 test_root = test_candidates [ test_candidate_ind ] while test_root == valid_root : test_candidate_ind += 1 if test_candidate_ind == len ( test_candidates ) : raise RuntimeError ( 'No candidates for test root. Try a different margin.' ) test_root = test_candidates [ test_candidate_ind ] return { 'valid' : valid_root , 'test' : test_root }