Как выбрать негативы из данных - PullRequest
0 голосов
/ 26 марта 2019

Я целый день пытаюсь понять следующий код, для меня это не имеет особого смысла.

Может кто-нибудь просветить меня, что он делает?

Некоторый контекст:

Нам присваиваются рейтинговые записи вида (user-id, item-id, rating). и для каждой записи (позитивной записи), мы пытаемся захватить несколько (четыре) отрицательных элемента (в том смысле, что пользователь не оценил).

И приведенный ниже код должен работать picking the negative items, но ничего себе, за ним трудно следовать :( И комментарии не сильно помогают ...

Самая запутанная часть - self._total_negatives и left_index = self.index_bounds[negative_users]

 class BisectionDataConstructor(BaseDataConstructor):
   """Use bisection to index within positive examples.

   This class tallies the number of negative items which appear before each
   positive item for a user. This means that in order to select the ith negative
   item for a user, it only needs to determine which two positive items bound
   it at which point the item id for the ith negative is a simply algebraic
   expression.
   """

   def _index_segment(self, user):

     lower, upper = self.index_bounds[user:user+2]
     items = self._sorted_train_pos_items[lower:upper]

     negatives_since_last_positive = np.concatenate(
       [items[0][np.newaxis], items[1:] - items[:-1] - 1])

     return np.cumsum(negatives_since_last_positive)

   def construct_lookup_variables(self):

     inner_bounds = np.argwhere(self._train_pos_users[1:] -
                                self._train_pos_users[:-1])[:, 0] + 1
     (upper_bound,) = self._train_pos_users.shape
     self.index_bounds = np.array([0] + inner_bounds.tolist() + [upper_bound])

     # Later logic will assume that the users are in sequential ascending order.
     assert np.array_equal(self._train_pos_users[self.index_bounds[:-1]],
                           np.arange(self._num_users))

     self._sorted_train_pos_items = self._train_pos_items.copy()

     for i in range(self._num_users):
       lower, upper = self.index_bounds[i:i+2]
       self._sorted_train_pos_items[lower:upper].sort()

     self._total_negatives = np.concatenate([
         self._index_segment(i) for i in range(self._num_users)])

   def lookup_negative_items(self, negative_users, **kwargs):

     output = np.zeros(shape=negative_users.shape, dtype=rconst.ITEM_DTYPE) - 1

     left_index = self.index_bounds[negative_users]
     right_index = self.index_bounds[negative_users + 1] - 1

     num_positives = right_index - left_index + 1
     num_negatives = self._num_items - num_positives
     neg_item_choice = stat_utils.very_slightly_biased_randint(num_negatives)

     use_shortcut = neg_item_choice >= self._total_negatives[right_index]
     output[use_shortcut] = (
         self._sorted_train_pos_items[right_index] + 1 +
         (neg_item_choice - self._total_negatives[right_index])
     )[use_shortcut]

     if np.all(use_shortcut):
       # The bisection code is ill-posed when there are no elements.
       return output

Это от https://github.com/tensorflow/models/blob/master/official/recommendation/data_pipeline.py

when  train_pos_users = np.array(
     [0,0,  1,1,1,   2,2,2,  3,3,3,3,3,3,  4,4])

self.index_bounds = array([ 0,  2,  5,  8, 14, 16])

Если вам это прилично знакомо, если где-то в сети есть описание того, что он делает, я мог бы очень сильно использовать его, чтобы понять, что он делает .. Я попытался поискать bisection negative sampling, но ничего не получается ..

  • редактировать

Таким образом, разделение пополам означает половину, что-то близкое к двоичному поиску

Я думаю, что код не делает то, что должен, и оставил проблему с github ..

https://github.com/tensorflow/models/issues/6441

...