Exemple #1
0
    def predict(self, user_ids, item_ids):
        max_seq_len = self._max_user_seq_len
        self._net.train(False)

        item_seqs = self._interactions.get_batch_seqs(user_ids, item_ids, max_seq_len=max_seq_len)
        item_seqs = Variable(my_utils.gpu(my_utils.numpy2tensor(item_seqs).type(torch.LongTensor),
                                          self._use_cuda), requires_grad=False)
        out = self._net(item_seqs,
                        Variable(my_utils.gpu(my_utils.numpy2tensor(user_ids), self._use_cuda)),
                        Variable(my_utils.gpu(my_utils.numpy2tensor(item_ids), self._use_cuda)))
        return my_utils.cpu(out).detach().data.numpy().flatten()
 def _reset_transform_identity(self):
     self._W1.weight.data.copy_(my_utils.numpy2tensor(
         np.concatenate(
             (np.identity(self._embedding_size), -np.identity(self._embedding_size))
             , axis=0).T
     )
     )
     self._W2.weight.data.copy_(my_utils.numpy2tensor(
         np.concatenate(
             (np.identity(self._embedding_size), np.identity(self._embedding_size))
             , axis=0).T)
     )
    def _make_mask(self, x):
        mask = np.asarray(my_utils.tensor2numpy(x.data.cpu().clone()), dtype=np.float64)
        # mask = my_utils.tensor2numpy(x != 0)
        mask[mask != gc.PADDING_IDX] = 1.0
        # mask[mask <= 0] = float('inf')
        mask[mask <= 0] = 65535

        return my_utils.gpu(Variable(my_utils.numpy2tensor(mask)).type(torch.FloatTensor), use_cuda=my_utils.is_cuda(x))
Exemple #4
0
    def predict(self, user_ids, item_ids, playlist_ids):
        max_seq_len = self._max_user_seq_len
        self._net.train(False)
        #last item id is the target item

        item_seqs = self._interactions.get_batch_seqs(user_ids,
                                                      item_ids,
                                                      playlist_ids,
                                                      max_seq_len=max_seq_len,
                                                      type='all')
        item_seqs = Variable(my_utils.gpu(
            my_utils.numpy2tensor(item_seqs).type(torch.LongTensor),
            self._use_cuda),
                             requires_grad=False)

        if self._args.data_type == 'upt':
            out = self._net(
                item_seqs,
                Variable(
                    my_utils.gpu(my_utils.numpy2tensor(user_ids),
                                 self._use_cuda)),
                Variable(
                    my_utils.gpu(my_utils.numpy2tensor(item_ids),
                                 self._use_cuda)),
                Variable(
                    my_utils.gpu(my_utils.numpy2tensor(playlist_ids),
                                 self._use_cuda)),
            )
        elif self._args.data_type == 'ut':
            out = self._net(
                item_seqs,
                Variable(
                    my_utils.gpu(my_utils.numpy2tensor(user_ids),
                                 self._use_cuda)),
                Variable(
                    my_utils.gpu(my_utils.numpy2tensor(item_ids),
                                 self._use_cuda)), None)
        elif self._args.data_type == 'pt':
            out = self._net(
                item_seqs,
                Variable(
                    my_utils.gpu(my_utils.numpy2tensor(playlist_ids),
                                 self._use_cuda)),
                Variable(
                    my_utils.gpu(my_utils.numpy2tensor(item_ids),
                                 self._use_cuda)), None)
        else:
            import sys
            print 'not supporting data type:', self._args.data_type
            sys.exit(1)

        return my_utils.cpu(out).detach().data.numpy().flatten()
Exemple #5
0
 def _reset_transform_identity(self):
     self._W1.weight.data.copy_(my_utils.numpy2tensor
         (
             np.concatenate(
                 (-np.identity(self._embedding_size),
                 np.identity(self._embedding_size)
                 )
                 , axis=0
             ).T  # initialy, it is subtractions of target user u and target item j, u-j
         )
     )
     if self._n_playlists:
         self._W2.weight.data.copy_(my_utils.numpy2tensor
             (
                 np.concatenate(
                     (-np.identity(self._embedding_size),
                      np.identity(self._embedding_size)
                      )
                     , axis=0
                 ).T  # initialy, it is subtractions of target user u and target item j, u-j
             )
         )
    def _reset_weights(self):
        self._user_embeddings.weight.data.normal_(0, 1.0 / self._embedding_size)
        self._user_embeddings.weight.data[gc.PADDING_IDX].fill_(0)
        self._item_embeddings.weight.data.normal_(0, 1.0 / self._embedding_size)
        self._item_embeddings.weight.data[gc.PADDING_IDX].fill_(0)

        if self._sum_func: initializer.lecun_uniform_initialization(self._sum_func.weight)


        for i , fc in enumerate(self._fcs):
            if i == 0:
                fc.weight.data.copy_(my_utils.numpy2tensor(
                        np.concatenate(
                            (np.identity(self._embedding_size), -np.identity(self._embedding_size))
                            , axis=0).T  # initialy, it is subtractions of target user u and target item j, u-j
                        ))
            else:
                fc.weight.data.normal_(0, 1.0 / self._embedding_size)
Exemple #7
0
    def init_parameters(self):
        '''
        init the parameters in here
        :return:
        '''

        position_enc = np.array([[
            pos / np.power(10000, 2 * (j // 2) / self._embedding_dim)
            for j in range(self._embedding_dim)
        ] if pos != gc.PADDING_IDX else np.zeros(self._embedding_dim)
                                 for pos in range(self._num_embeddings)])

        position_enc[1:, 0::2] = np.sin(position_enc[1:, 0::2])  # dim 2i
        position_enc[1:, 1::2] = np.cos(position_enc[1:, 1::2])  # dim 2i+1
        # return my_utils.numpy2tensor(position_enc).type(torch.FloatTensor)

        self.weight.data = my_utils.numpy2tensor(position_enc).type(
            torch.FloatTensor)
Exemple #8
0
    def _get_neg_pred(self,
                      item_seqs_var,
                      batch_user_var,
                      batch_playlist_var,
                      batch_negative_items,
                      adv=False):
        '''
        user_ids are numpy data
        :param user_ids:
        :param user_seqs:
        :return:
        '''

        negative_prediction = None
        for i in range(batch_negative_items.shape[1]):
            negative_items = batch_negative_items[:, i]

            batch_neg_item_var = Variable(
                my_utils.gpu(my_utils.numpy2tensor(negative_items).type(
                    torch.LongTensor),
                             use_cuda=self._use_cuda))
            if self._args.data_type == 'upt':
                tmp_negative_prediction = self._net(item_seqs_var,
                                                    batch_user_var,
                                                    batch_neg_item_var,
                                                    batch_playlist_var,
                                                    adv=adv)
            elif self._args.data_type == 'pt':
                tmp_negative_prediction = self._net(item_seqs_var,
                                                    batch_playlist_var,
                                                    batch_neg_item_var,
                                                    adv=adv)
            else:  #ut
                tmp_negative_prediction = self._net(item_seqs_var,
                                                    batch_user_var,
                                                    batch_neg_item_var,
                                                    adv=adv)
            if negative_prediction is None:
                negative_prediction = tmp_negative_prediction
            else:
                negative_prediction = torch.max(negative_prediction,
                                                tmp_negative_prediction)

        return negative_prediction
    def load_checkpoint(self, args):
        lst_models = ['sdm', 'sdp']
        if args.eval:
            lst_models = ['sdm', 'sdp', 'dmmr']
        if args.model in lst_models:
            best_hits = 0.0
            best_ndcg = 0.0
            best_saved_file = ''

            saved_file_pattern = '%s_%s_%s*' % (args.dataset, args.model,
                                                self._make_model_desc(args))
            for filepath in glob.glob(
                    os.path.join(args.saved_path, saved_file_pattern)):
                # filepath = os.path.join(args.saved_path, fname)
                if os.path.isfile(filepath):
                    print("=> loading checkpoint '{}'".format(filepath))
                    checkpoint = torch.load(filepath)
                    hits = float(checkpoint['best_hits'])
                    ndcg = float(checkpoint['best_ndcg'])
                    if hits > best_hits or (hits == best_hits
                                            and ndcg > best_ndcg):
                        # if ndcg > best_ndcg or (ndcg == best_ndcg and hits > best_hits):
                        best_saved_file = filepath
                        best_hits = hits
                        best_ndcg = ndcg
            if best_saved_file != '':
                checkpoint = torch.load(best_saved_file)
                self._net.load_state_dict(checkpoint['model'])
                self._optimizer.load_state_dict(checkpoint['optimizer'])
                print("=> loaded checkpoint '{}' (epoch {})".format(
                    best_saved_file, checkpoint['epoch']))

            return (best_hits, best_ndcg)

        else:
            #sdmr : Deep Metric memory Recommender
            #load best sdp checkpoint
            best_sdp_file = ''
            best_sdp_hits, best_sdp_ndcgs = 0, 0
            sdp_files_pattern = '%s_sdp_%s*' % (
                args.dataset, self._make_model_desc(args, 'sdp'))
            # print sdp_files_pattern
            for filepath in glob.glob(
                    os.path.join(args.saved_path, sdp_files_pattern)):
                print filepath
                if os.path.isfile(filepath):
                    print("=> loading checkpoint '{}'".format(filepath))
                    if args.cuda:
                        checkpoint = torch.load(filepath)
                    else:
                        checkpoint = torch.load(
                            filepath,
                            map_location=lambda storage, loc: storage)
                    hits = float(checkpoint['best_hits'])
                    ndcg = float(checkpoint['best_ndcg'])
                    if hits > best_sdp_hits or (hits == best_sdp_hits
                                                and ndcg > best_sdp_ndcgs):
                        best_sdp_file = filepath
                        best_sdp_hits = hits
                        best_sdp_ndcgs = ndcg

            #load best sdm checkpoint
            best_sdm_file = ''
            best_sdm_hits, best_sdm_ndcgs = 0, 0
            sdm_files_pattern = '%s_sdm_%s*' % (
                args.dataset, self._make_model_desc(args, 'sdm'))
            for filepath in glob.glob(
                    os.path.join(args.saved_path, sdm_files_pattern)):
                if os.path.isfile(filepath):
                    print("=> loading checkpoint '{}'".format(filepath))
                    if args.cuda:
                        checkpoint = torch.load(filepath)
                    else:
                        checkpoint = torch.load(
                            filepath,
                            map_location=lambda storage, loc: storage)

                    hits = float(checkpoint['best_hits'])
                    ndcg = float(checkpoint['best_ndcg'])
                    if hits > best_sdm_hits or (hits == best_sdm_hits
                                                and ndcg > best_sdm_ndcgs):
                        # if ndcg > best_sdm_ndcgs or (ndcg == best_sdm_ndcgs and hits > best_sdm_hits):
                        best_sdm_file = filepath
                        best_sdm_hits = hits
                        best_sdm_ndcgs = ndcg

            #now loading best checkpoints from sdp and sdm for sdmr:
            if best_sdp_file != '':
                #load checkpoint into cpu if not using cuda
                if args.cuda:
                    checkpoint = torch.load(best_sdp_file)
                else:
                    checkpoint = torch.load(
                        best_sdp_file,
                        map_location=lambda storage, loc: storage)
                self._net._sdp.load_state_dict(checkpoint['model'])

                print("=> loaded checkpoint '{}' (epoch {})".format(
                    best_sdp_file, checkpoint['epoch']))

                # no train or re-train the sdm and sdp weights?
                for params in self._net._sdp.parameters():
                    params.requires_grad = bool(args.sdmr_retrain)

            if best_sdm_file != '':
                #load checkpoint into gpu or in cpu if not using cuda
                if args.cuda:
                    checkpoint = torch.load(best_sdm_file)
                else:
                    checkpoint = torch.load(
                        best_sdm_file,
                        map_location=lambda storage, loc: storage)

                self._net._sdm.load_state_dict(checkpoint['model'])

                print("=> loaded checkpoint '{}' (epoch {})".format(
                    best_sdm_file, checkpoint['epoch']))
                #no train the sdm and sdp?
                for params in self._net._sdm.parameters():
                    params.requires_grad = bool(args.sdmr_retrain)

            sum_weights = np.concatenate(
                ((1 - args.beta) *
                 my_utils.tensor2numpy(self._net._sdp._sum_func.weight.data),
                 args.beta *
                 my_utils.tensor2numpy(self._net._sdm._sum_func.weight.data)),
                axis=1)
            sum_bias = (1-args.beta) * my_utils.tensor2numpy(self._net._sdp._sum_func.bias.data) + \
                       args.beta * my_utils.tensor2numpy(self._net._sdm._sum_func.bias.data)

            self._net._sum_func.weight.data.copy_(
                my_utils.numpy2tensor(sum_weights))
            self._net._sum_func.bias.data.copy_(
                my_utils.numpy2tensor(sum_bias))
            return 0, 0
Exemple #10
0
    def fit(self,
            interactions,
            verbose=False,
            topN=10,
            vadRatings=None,
            vadNegatives=None,
            testRatings=None,
            testNegatives=None,
            max_seq_len=100,
            args=None):

        if not self._is_initialized():
            self._initialize(interactions, max_seq_len=max_seq_len)

        user_ids = interactions._user_ids.astype(np.int64)
        item_ids = interactions._item_ids.astype(np.int64)
        playlist_ids = interactions._playlists.astype(np.int64)

        # self._check_input(sequences)
        if verbose:
            best_hit = 0.0
            best_ndcg = 0.0
            best_epoch = 0
            test_hit, test_ndcg = 0.0, 0.0

        if args.load_best_chkpoint > 0:
            # print self._net.parameters
            best_hit, best_ndcg = self.load_checkpoint(args)
            print 'Results from best checkpoints ...'
            # print self._net.parameters
            if verbose:
                t1 = time.time()
                hits, ndcg = my_evaluator.evaluate(self, vadRatings,
                                                   vadNegatives, topN)
                for topN in range(10, 11, 1):
                    hits_test, ndcg_test = my_evaluator.evaluate(
                        self, testRatings, testNegatives, topN)
                    t2 = time.time()
                    eval_time = t2 - t1
                    print(
                        '| Eval time: %d '
                        '| Vad hits@%d = %.3f | Vad ndcg@%d = %.3f '
                        '| Test hits@%d = %.3f | Test ndcg@%d = %.3f |' %
                        (eval_time, topN, hits, topN, ndcg, topN, hits_test,
                         topN, ndcg_test))
                    if topN == 10:
                        test_hit = hits_test
                        test_ndcg = ndcg_test
                        best_hit, best_ndcg = hits, ndcg
                topN = 10
            print 'End!'

        if args.eval:
            print 'Evaluation using the saved checkpoint done!'
            return

        if self._has_params():
            for epoch in range(self._n_iters):

                self._lr_schedule.step(epoch)

                self._net.train()  # set training environment
                t1 = time.time()
                users, items, playlists = my_utils.shuffle(
                    user_ids,
                    item_ids,
                    playlist_ids,
                    random_state=self._random_state)
                users = np.asarray(users)
                items = np.asarray(items)
                playlists = np.asarray(playlists)
                #neg_items = self._sampler.random_neg_items(users, num_neg=args.num_neg)
                neg_items = self._sampler.random_neg_items(
                    playlists, num_neg=args.num_neg)

                epoch_loss = 0.0
                epoch_noise_loss = 0.0

                t1 = time.time()
                total_interactions = 0
                for (minibatch_idx,
                     (batch_user, batch_item, batch_playlists,
                      batch_neg_items)) in enumerate(
                          my_utils.minibatch(users,
                                             items,
                                             playlists,
                                             neg_items,
                                             batch_size=self._batch_size)):
                    total_interactions += len(batch_user)  # or batch_size

                    if args.model == 'mass' or args.model == 'masr':
                        item_seqs = interactions.get_batch_seqs(
                            batch_user,
                            batch_item,
                            batch_playlists,
                            max_seq_len=self._max_user_seq_len,
                            type='all')
                        item_seqs_var = Variable(my_utils.gpu(
                            my_utils.numpy2tensor(item_seqs).type(
                                torch.LongTensor), self._use_cuda),
                                                 requires_grad=False)
                    else:
                        item_seqs, item_seqs_var = None, None

                    batch_user_var = Variable(
                        my_utils.gpu(my_utils.numpy2tensor(batch_user).type(
                            torch.LongTensor),
                                     use_cuda=self._use_cuda))
                    batch_item_var = Variable(
                        my_utils.gpu(my_utils.numpy2tensor(batch_item).type(
                            torch.LongTensor),
                                     use_cuda=self._use_cuda))

                    if args.adv:
                        ########################### construct adversarial pertubations:#################################
                        if args.model == 'mdr' or args.model == 'mass':
                            if args.data_type == 'upt' or args.data_type == 'pt':
                                batch_playlist_var = Variable(
                                    my_utils.gpu(my_utils.numpy2tensor(
                                        batch_playlists).type(
                                            torch.LongTensor),
                                                 use_cuda=self._use_cuda))
                            else:
                                batch_playlist_var = None
                            if args.data_type == 'upt':
                                positive_prediction_adv = self._net(
                                    item_seqs_var,
                                    batch_user_var,
                                    batch_item_var,
                                    batch_playlist_var,
                                    adv=True)
                                negative_prediction_adv = self._get_neg_pred(
                                    item_seqs_var,
                                    batch_user_var,
                                    batch_playlist_var,
                                    batch_neg_items,
                                    adv=True)
                            elif args.data_type == 'pt':
                                positive_prediction_adv = self._net(
                                    item_seqs_var,
                                    batch_playlist_var,
                                    batch_item_var,
                                    None,
                                    adv=True)
                                negative_prediction_adv = self._get_neg_pred(
                                    item_seqs_var,
                                    batch_user_var,
                                    batch_playlist_var,
                                    batch_neg_items,
                                    adv=True)
                            elif args.data_type == 'ut':
                                positive_prediction_adv = self._net(
                                    item_seqs_var,
                                    batch_user_var,
                                    batch_item_var,
                                    None,
                                    adv=True)
                                negative_prediction_adv = self._get_neg_pred(
                                    item_seqs_var,
                                    batch_user_var,
                                    batch_playlist_var,
                                    batch_neg_items,
                                    adv=True)
                            else:
                                import sys
                                print 'error, donot support data_type', args.data_type, ' please select: upt, pt, or ut'
                                sys.exit(1)

                        loss_adv = self._loss_func(positive_prediction_adv,
                                                   negative_prediction_adv)
                        self._optimizer.zero_grad()
                        loss_adv.backward(retain_graph=True)

                        #update adversarial noise
                        self._net._update_noise_params()

                        epoch_noise_loss += my_utils.cpu(loss_adv).data.numpy()

                        ###########################update model's params:#################################
                        if args.model == 'mdr' or args.model == 'mass':
                            if args.data_type == 'upt' or args.data_type == 'pt':
                                batch_playlist_var = Variable(
                                    my_utils.gpu(my_utils.numpy2tensor(
                                        batch_playlists).type(
                                            torch.LongTensor),
                                                 use_cuda=self._use_cuda))
                            else:
                                batch_playlist_var = None
                            if args.data_type == 'upt':
                                positive_prediction_adv = self._net(
                                    item_seqs_var,
                                    batch_user_var,
                                    batch_item_var,
                                    batch_playlist_var,
                                    adv=True)
                                negative_prediction_adv = self._get_neg_pred(
                                    item_seqs_var,
                                    batch_user_var,
                                    batch_playlist_var,
                                    batch_neg_items,
                                    adv=True)
                            elif args.data_type == 'pt':
                                positive_prediction_adv = self._net(
                                    item_seqs_var,
                                    batch_playlist_var,
                                    batch_item_var,
                                    None,
                                    adv=True)
                                negative_prediction_adv = self._get_neg_pred(
                                    item_seqs_var,
                                    batch_user_var,
                                    batch_playlist_var,
                                    batch_neg_items,
                                    adv=True)
                            elif args.data_type == 'ut':
                                positive_prediction_adv = self._net(
                                    item_seqs_var,
                                    batch_user_var,
                                    batch_item_var,
                                    None,
                                    adv=True)
                                negative_prediction_adv = self._get_neg_pred(
                                    item_seqs_var,
                                    batch_user_var,
                                    batch_playlist_var,
                                    batch_neg_items,
                                    adv=True)
                            else:
                                import sys
                                print 'error, donot support data_type', args.data_type, ' please select: upt, pt, or ut'
                                sys.exit(1)

                        loss_adv = self._loss_func(positive_prediction_adv,
                                                   negative_prediction_adv)

                        #normal loss
                        if args.model == 'mdr' or args.model == 'mass':
                            if args.data_type == 'upt' or args.data_type == 'pt':
                                batch_playlist_var = Variable(
                                    my_utils.gpu(my_utils.numpy2tensor(
                                        batch_playlists).type(
                                            torch.LongTensor),
                                                 use_cuda=self._use_cuda))
                            else:
                                batch_playlist_var = None
                            if args.data_type == 'upt':
                                positive_prediction = self._net(
                                    item_seqs_var,
                                    batch_user_var,
                                    batch_item_var,
                                    batch_playlist_var,
                                    adv=False)
                                negative_prediction = self._get_neg_pred(
                                    item_seqs_var,
                                    batch_user_var,
                                    batch_playlist_var,
                                    batch_neg_items,
                                    adv=False)
                            elif args.data_type == 'pt':
                                positive_prediction = self._net(
                                    item_seqs_var,
                                    batch_playlist_var,
                                    batch_item_var,
                                    None,
                                    adv=False)
                                negative_prediction = self._get_neg_pred(
                                    item_seqs_var,
                                    batch_user_var,
                                    batch_playlist_var,
                                    batch_neg_items,
                                    adv=False)
                            elif args.data_type == 'ut':
                                positive_prediction = self._net(item_seqs_var,
                                                                batch_user_var,
                                                                batch_item_var,
                                                                None,
                                                                adv=False)
                                negative_prediction = self._get_neg_pred(
                                    item_seqs_var,
                                    batch_user_var,
                                    batch_playlist_var,
                                    batch_neg_items,
                                    adv=False)
                            else:
                                import sys
                                print 'error, donot support data_type', args.data_type, ' please select: upt, pt, or ut'
                                sys.exit(1)

                        loss = self._loss_func(positive_prediction,
                                               negative_prediction)
                        loss_total = loss + args.reg_noise * loss_adv

                        epoch_loss += my_utils.cpu(loss_total).data.numpy()
                        self._optimizer.zero_grad()  # clear previous grad
                        loss_total.backward()

                        # clear all the grads for noises now since we are not updating the noise.
                        self._net._clear_grad(adv=True)
                        self._optimizer.step()
                        pass

                    else:

                        #sample negative items
                        #batch_neg_items = self.sample_neg_items(batch_user, num_negs=args.num_neg)
                        if args.model == 'mdr' or args.model == 'mass':
                            if args.data_type == 'upt' or args.data_type == 'pt':
                                batch_playlist_var = Variable(
                                    my_utils.gpu(my_utils.numpy2tensor(
                                        batch_playlists).type(
                                            torch.LongTensor),
                                                 use_cuda=self._use_cuda))
                            else:
                                batch_playlist_var = None
                            if args.data_type == 'upt':
                                positive_prediction = self._net(
                                    item_seqs_var, batch_user_var,
                                    batch_item_var, batch_playlist_var)
                                negative_prediction = self._get_neg_pred(
                                    item_seqs_var, batch_user_var,
                                    batch_playlist_var, batch_neg_items)
                            elif args.data_type == 'pt':
                                positive_prediction = self._net(
                                    item_seqs_var, batch_playlist_var,
                                    batch_item_var, None)
                                negative_prediction = self._get_neg_pred(
                                    item_seqs_var, batch_user_var,
                                    batch_playlist_var, batch_neg_items)
                            elif args.data_type == 'ut':
                                positive_prediction = self._net(
                                    item_seqs_var, batch_user_var,
                                    batch_item_var, None)
                                negative_prediction = self._get_neg_pred(
                                    item_seqs_var, batch_user_var,
                                    batch_playlist_var, batch_neg_items)
                            else:
                                import sys
                                print 'error, donot support data_type', args.data_type, ' please select: upt, pt, or ut'
                                sys.exit(1)

                        self._optimizer.zero_grad()

                        loss = self._loss_func(positive_prediction,
                                               negative_prediction)

                        #regularizer = self._net._get_l2_loss()
                        #if self._model == 'mass': loss += self._reg_mass * regularizer
                        #elif self._model == 'mdr': loss += self._reg_mdr * regularizer
                        #else: loss += self._reg_mdr * regularizer[0] + self._reg_mass * regularizer[1]

                        epoch_loss += my_utils.cpu(loss).data.numpy()

                        loss.backward()

                        self._optimizer.step()

                        if gc.DEBUG:
                            # print 'W1 :', self._net._W1.weight.data
                            # print 'W2 :', self._net._W2.weight.data
                            #
                            # print 'W1 grad:', self._net._W1.weight.grad.data
                            # print 'W2 grad:', self._net._W2.weight.grad.data
                            #
                            print 'Loss is :', loss
                            print 'Positive prediction:', positive_prediction
                            print 'negative prediction:', negative_prediction
                            if minibatch_idx >= 1: break  # debug

                epoch_loss = epoch_loss / total_interactions
                epoch_noise_loss = epoch_noise_loss / total_interactions
                t2 = time.time()
                epoch_train_time = t2 - t1
                if verbose:
                    t1 = time.time()
                    hits, ndcg = my_evaluator.evaluate(self, vadRatings,
                                                       vadNegatives, topN)
                    hits_test, ndcg_test = my_evaluator.evaluate(
                        self, testRatings, testNegatives, topN)
                    t2 = time.time()
                    eval_time = t2 - t1
                    print(
                        '|Epoch %d | Train time: %d | Train loss: %.3f | Train Noise loss: %.3f | Eval time: %d '
                        '| Vad hits@%d = %.3f | Vad ndcg@%d = %.3f '
                        '| Test hits@%d = %.3f | Test ndcg@%d = %.3f |' %
                        (epoch, epoch_train_time, epoch_loss, epoch_noise_loss,
                         eval_time, topN, hits, topN, ndcg, topN, hits_test,
                         topN, ndcg_test))
                    if hits > best_hit or (hits == best_hit
                                           and ndcg > best_ndcg):
                        # if (hits + ndcg) > (best_hit + best_ndcg):
                        # if (ndcg > best_ndcg) or (ndcg == best_ndcg and hits > best_hit):
                        best_hit, best_ndcg, best_epoch = hits, ndcg, epoch
                        test_hit, test_ndcg = hits_test, ndcg_test
                        #self.save_checkpoint(args, best_hit, best_ndcg, epoch)
                        if args.out:
                            self.save_checkpoint(args, hits, ndcg,
                                                 epoch)  # save best params

                else:
                    print('|Epoch %d | Train time: %d | loss: %.3f' %
                          (epoch, epoch_train_time, epoch_loss))

                if np.isnan(epoch_loss) or epoch_loss == 0.0:
                    raise ValueError(
                        'Degenerate epoch loss: {}'.format(epoch_loss))

            print(
                'Best result: '
                '| vad hits@%d = %.3f | vad ndcg@%d = %.3f '
                '| test hits@%d = %.3f | test ndcg@%d = %.3f | epoch = %d' %
                (topN, best_hit, topN, best_ndcg, topN, test_hit, topN,
                 test_ndcg, best_epoch))
Exemple #11
0
    def fit(self, interactions, topN=10,
            testRatings=None, testNegatives=None,
            max_seq_len=5, args=None):

        if not self._is_initialized():
            self._initialize(interactions, max_seq_len=max_seq_len)

        user_ids = interactions._user_ids.astype(np.int64)
        item_ids = interactions._item_ids.astype(np.int64)

        best_hit = 0.0
        best_ndcg = 0.0
        best_epoch = 0
        test_hit, test_ndcg = 0.0, 0.0

        if args.load_best_chkpoint > 0:

            best_hit, best_ndcg = self.load_checkpoint(args)
            print 'Results from best checkpoints ...'
            t1 = time.time()
            hits, ndcgs = my_evaluator.evaluate(self, testRatings, testNegatives, topN)
            t2 = time.time()
            eval_time = t2-t1
            best_hit, best_ndcg = hits, ndcgs
            print('| Eval time: %d '
                  '| Test hits@%d = %.3f | Test ndcg@%d = %.3f |'
                  % (eval_time, topN, hits, topN, ndcgs))
            topN = 10
            print 'End!'

        if args.eval:
            print 'Evaluation using the saved checkpoint done!'
            return

        if self._has_params():
            for epoch in range(self._n_iters):

                self._lr_schedule.step(epoch)

                self._net.train()  # set training environment

                users, items = my_utils.shuffle(user_ids,
                                                item_ids,
                                                random_state=self._random_state)
                users = np.asarray(users)
                items = np.asarray(items)
                neg_items = self._sampler.random_neg_items(users, num_neg=args.num_neg)


                # copy to GPU:
                user_vars = Variable(my_utils.gpu(my_utils.numpy2tensor(users).type(torch.LongTensor),
                                                  use_cuda=self._use_cuda))
                item_vars = Variable(my_utils.gpu(my_utils.numpy2tensor(items).type(torch.LongTensor),
                                                  use_cuda=self._use_cuda))
                neg_item_vars = Variable(my_utils.gpu(my_utils.numpy2tensor(neg_items).type(torch.LongTensor),
                                                           use_cuda=self._use_cuda))

                context_vars = None
                #if args.model != 'sdp':
                contexts = interactions.get_batch_seqs(users, items,
                                                            max_seq_len=self._max_user_seq_len)
                context_vars = Variable(my_utils.gpu(my_utils.numpy2tensor(contexts).type(torch.LongTensor),
                                                     self._use_cuda), requires_grad=False)





                epoch_loss = 0.0

                t1 = time.time()
                total_interactions = 0
                for (minibatch_idx, (batch_users, batch_items, batch_neg_items, batch_contexts )) in enumerate(
                                                                                        my_utils.minibatch(
                                                                                            user_vars,
                                                                                            item_vars,
                                                                                            neg_item_vars,
                                                                                            context_vars,
                                                                                            batch_size=self._batch_size)):
                    total_interactions += len(batch_users)  # or batch_size
                    if args.model == 'sdp':
                        batch_contexts = None

                    positive_prediction = self._net(batch_contexts, batch_users, batch_items)

                    negative_prediction = self._get_neg_pred(batch_contexts, batch_users, batch_neg_items)
                    self._optimizer.zero_grad()

                    loss = self._loss_func(positive_prediction,
                                           negative_prediction
                                           )


                    epoch_loss += my_utils.cpu(loss).data.numpy()

                    loss.backward()

                    self._optimizer.step()


                epoch_loss = epoch_loss / total_interactions
                t2 = time.time()
                epoch_train_time = t2 - t1

                t1 = time.time()

                hits, ndcgs = my_evaluator.evaluate(self, testRatings, testNegatives, topN)
                t2 = time.time()
                eval_time = t2 - t1
                print('|Epoch %d | Train time: %d | Train loss: %.3f | Eval time: %d '
                      '| Test hits@%d = %.3f | Test ndcg@%d = %.3f |'
                      % (epoch, epoch_train_time, epoch_loss, eval_time, topN, hits, topN, ndcgs))
                if hits > best_hit or (hits == best_hit and ndcgs >= best_ndcg):
                    best_hit, best_ndcg, best_epoch = hits, ndcgs, epoch
                    if args.out:
                        self.save_checkpoint(args, hits, ndcgs, epoch)  # save best params

                if np.isnan(epoch_loss) or epoch_loss == 0.0:
                    raise ValueError('Degenerate epoch loss: {}'
                                     .format(epoch_loss))

            print ('Best result: '
                   '| test hits@%d = %.3f | test ndcg@%d = %.3f | epoch = %d' % (topN,  best_hit, topN, best_ndcg,
                                                                                 best_epoch))