in gym_wikinav/envs/wikinav_env/web_graph.py [0:0]
def _get_candidates(self):
"""
Build a beam of candidate next-page IDs consisting of the valid
solution and other negatively-sampled candidate links on the page.
NB: The candidate list returned may have a regular pattern, e.g. the
stop sentinel / filler candidates (for candidate lists which are smaller
than the beam size) may always be in the same position in the list.
Make sure to not build models (e.g. ones with output biases) that might
capitalize on this pattern.
Returns:
candidates: List of article IDs of length `self.beam_size`.
The list is guaranteed to contain 1) the gold next page
according to the oracle trajectory and 2) the stop sentinel.
(Note that these two will make up just one candidate if the
valid next action is to stop.)
"""
# Retrieve gold next-page choice for this example
try:
gold_next_id = path[cursor + 1]
except IndexError:
# We are at the end of this path and ready to quit. Prepare a
# dummy beam that won't have any effect.
candidates = [self._dummy_page] * self.beam_size
self._gold_action = 0
return candidates
ids = self.graph.get_article_links(self.cur_article_id)
ids = [int(x) for x in ids if x != gold_next_id]
# Beam must be large enough to hold gold + STOP + a distractor
assert self.beam_size >= 3
gold_is_stop = gold_next_id == self.graph.stop_sentinel
# Number of distractors to sample
sample_size = self.beam_size - 1 if gold_is_stop \
else self.beam_size - 2
if len(ids) > sample_size:
ids = random.sample(ids, sample_size)
if len(ids) < sample_size:
ids += [self._dummy_page] * (sample_size - len(ids))
# Add the gold page.
ids = [gold_next_id] + ids
if not gold_is_stop:
ids += [self.graph.stop_sentinel]
random.shuffle(ids)
assert len(ids) == self.beam_size
self._gold_action = gold_next_id
return ids