コード例 #1
0
ファイル: implicit.py プロジェクト: AlexMikhalev/spotlight
    def _get_negative_prediction(self, shape, user_representation):

        negative_items = sample_items(
            self._num_items,
            shape,
            random_state=self._random_state)
        negative_var = Variable(
            gpu(torch.from_numpy(negative_items), self._use_cuda)
        )
        negative_prediction = self._net(user_representation, negative_var)

        return negative_prediction
コード例 #2
0
ファイル: implicit.py プロジェクト: AlexMikhalev/spotlight
    def _get_negative_prediction(self, user_ids):

        negative_items = sample_items(
            self._num_items,
            len(user_ids),
            random_state=self._random_state)
        negative_var = Variable(
            gpu(torch.from_numpy(negative_items), self._use_cuda)
        )
        negative_prediction = self._net(user_ids, negative_var)

        return negative_prediction
コード例 #3
0
ファイル: implicit.py プロジェクト: AlexMikhalev/spotlight
    def predict(self, sequences, item_ids=None):
        """
        Make predictions: given a sequence of interactions, predict
        the next item in the sequence.

        Parameters
        ----------

        sequences: array, (1 x max_sequence_length)
            Array containing the indices of the items in the sequence.
        item_ids: array (num_items x 1), optional
            Array containing the item ids for which prediction scores
            are desired. If not supplied, predictions for all items
            will be computed.

        Returns
        -------

        predictions: array
            Predicted scores for all items in item_ids.
        """

        self._net.train(False)

        sequences = np.atleast_2d(sequences)

        if item_ids is None:
            item_ids = np.arange(self._num_items).reshape(-1, 1)

        sequences = torch.from_numpy(sequences.astype(np.int64).reshape(1, -1))
        item_ids = torch.from_numpy(item_ids.astype(np.int64))

        sequence_var = Variable(gpu(sequences, self._use_cuda))
        item_var = Variable(gpu(item_ids, self._use_cuda))

        _, sequence_representations = self._net.user_representation(sequence_var)
        out = self._net(sequence_representations.repeat(len(item_var), 1),
                        item_var)

        return cpu(out.data).numpy().flatten()
コード例 #4
0
ファイル: implicit.py プロジェクト: AlexMikhalev/spotlight
    def predict(self, user_ids, item_ids=None):
        """
        Make predictions: given a user id, compute the recommendation
        scores for items.

        Parameters
        ----------

        user_ids: int or array
           If int, will predict the recommendation scores for this
           user for all items in item_ids. If an array, will predict
           scores for all (user, item) pairs defined by user_ids and
           item_ids.
        item_ids: array, optional
            Array containing the item ids for which prediction scores
            are desired. If not supplied, predictions for all items
            will be computed.

        Returns
        -------

        predictions: np.array
            Predicted scores for all items in item_ids.
        """

        if item_ids is None:
            item_ids = np.arange(self._num_items)

        if isinstance(user_ids, int):
            user_ids = np.repeat(user_ids, len(item_ids))

        user_ids = torch.from_numpy(user_ids.reshape(-1, 1).astype(np.int64))
        item_ids = torch.from_numpy(item_ids.reshape(-1, 1).astype(np.int64))

        user_var = Variable(gpu(user_ids, self._use_cuda))
        item_var = Variable(gpu(item_ids, self._use_cuda))

        out = self._net(user_var, item_var)

        return cpu(out.data).numpy().flatten()
コード例 #5
0
ファイル: explicit.py プロジェクト: xuChenSJTU/spotlight
    def fit(self, interactions, verbose=False):
        """
        Fit the model.

        When called repeatedly, model fitting will resume from
        the point at which training stopped in the previous fit
        call.

        Parameters
        ----------

        interactions: :class:`spotlight.interactions.Interactions`
            The input dataset. Must have ratings.
        """

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

        if not self._initialized:
            self._initialize(interactions)

        self._check_input(user_ids, item_ids)

        for epoch_num in range(self._n_iter):

            users, items, ratings = shuffle(user_ids,
                                            item_ids,
                                            interactions.ratings,
                                            random_state=self._random_state)

            user_ids_tensor = gpu(torch.from_numpy(users),
                                  self._use_cuda)
            item_ids_tensor = gpu(torch.from_numpy(items),
                                  self._use_cuda)
            ratings_tensor = gpu(torch.from_numpy(ratings),
                                 self._use_cuda)

            epoch_loss = 0.0

            for (minibatch_num,
                 (batch_user,
                  batch_item,
                  batch_ratings)) in enumerate(minibatch(user_ids_tensor,
                                                         item_ids_tensor,
                                                         ratings_tensor,
                                                         batch_size=self._batch_size)):

                user_var = Variable(batch_user)
                item_var = Variable(batch_item)
                ratings_var = Variable(batch_ratings)

                predictions = self._net(user_var, item_var)

                if self._loss == 'poisson':
                    predictions = torch.exp(predictions)

                self._optimizer.zero_grad()

                loss = self._loss_func(ratings_var, predictions)
                epoch_loss += loss.data[0]

                loss.backward()
                self._optimizer.step()

            epoch_loss /= minibatch_num + 1

            if verbose:
                print('Epoch {}: loss {}'.format(epoch_num, epoch_loss))
コード例 #6
0
    def fit(self, interactions, verbose=False, return_loss=False):
        """
        Fit the model.

        When called repeatedly, model fitting will resume from
        the point at which training stopped in the previous fit
        call.

        Parameters
        ----------

        interactions: :class:`spotlight.interactions.Interactions`
            The input dataset.

        verbose: bool
            Output additional information about current epoch and loss.
        """

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

        if not self._initialized:
            self._initialize(interactions)

        self._check_input(user_ids, item_ids)

        for epoch_num in range(self._n_iter):

            users, items = shuffle(user_ids,
                                   item_ids,
                                   random_state=self._random_state)

            user_ids_tensor = gpu(torch.from_numpy(users), self._use_cuda)
            item_ids_tensor = gpu(torch.from_numpy(items), self._use_cuda)

            epoch_loss = 0.0
            epoch_cov_norm = 0.0

            for (minibatch_num, (batch_user, batch_item)) in enumerate(
                    minibatch(user_ids_tensor,
                              item_ids_tensor,
                              batch_size=self._batch_size)):

                positive_prediction = self._net(batch_user, batch_item)

                if self._loss in ('warp', 'adaptive_hinge'):
                    negative_prediction = self._get_multiple_negative_predictions(
                        batch_user, n=self._num_negative_samples)
                else:
                    negative_prediction = self._get_negative_prediction(
                        batch_user)

                self._optimizer.zero_grad()

                if self._margin is not None:
                    loss = self._loss_func(positive_prediction,
                                           negative_prediction,
                                           m=self._margin)
                else:
                    loss = self._loss_func(positive_prediction,
                                           negative_prediction)

                epoch_loss += loss.item()

                if self._cov_reg is not None:
                    cov_loss = self._covariance_loss()
                    loss += cov_loss * self._cov_reg
                    epoch_cov_norm += cov_loss.item()

                loss.backward()
                self._optimizer.step()

            epoch_loss /= minibatch_num + 1
            epoch_cov_norm /= minibatch_num + 1

            if verbose:
                print('Epoch {}: loss {}, cov_norm {}'.format(
                    epoch_num, epoch_loss, epoch_cov_norm))

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

        if return_loss:
            return epoch_loss, epoch_cov_norm
コード例 #7
0
ファイル: explicit.py プロジェクト: AlexMikhalev/spotlight
    def fit(self, interactions, verbose=False):
        """
        Fit the model.

        Parameters
        ----------

        interactions: :class:`spotlight.interactions.Interactions`
            The input dataset. Must have ratings.
        """

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

        (self._num_users,
         self._num_items) = (interactions.num_users,
                             interactions.num_items)

        self._net = gpu(
            BilinearNet(self._num_users,
                        self._num_items,
                        self._embedding_dim,
                        sparse=self._sparse),
            self._use_cuda
        )

        if self._optimizer_func is None:
            self._optimizer = optim.Adam(
                self._net.parameters(),
                weight_decay=self._l2,
                lr=self._learning_rate
            )
        else:
            self._optimizer = self._optimizer_func(self._net.parameters())

        if self._loss == 'regression':
            loss_fnc = regression_loss
        elif self._loss == 'poisson':
            loss_fnc = poisson_loss
        else:
            raise ValueError('Unknown loss: {}'.format(self._loss))

        for epoch_num in range(self._n_iter):

            users, items, ratings = shuffle(user_ids,
                                            item_ids,
                                            interactions.ratings,
                                            random_state=self._random_state)

            user_ids_tensor = gpu(torch.from_numpy(users),
                                  self._use_cuda)
            item_ids_tensor = gpu(torch.from_numpy(items),
                                  self._use_cuda)
            ratings_tensor = gpu(torch.from_numpy(ratings),
                                 self._use_cuda)

            epoch_loss = 0.0

            for (minibatch_num,
                 (batch_user,
                  batch_item,
                  batch_ratings)) in enumerate(minibatch(user_ids_tensor,
                                                         item_ids_tensor,
                                                         ratings_tensor,
                                                         batch_size=self._batch_size)):

                user_var = Variable(batch_user)
                item_var = Variable(batch_item)
                ratings_var = Variable(batch_ratings)

                predictions = self._net(user_var, item_var)

                if self._loss == 'poisson':
                    predictions = torch.exp(predictions)

                self._optimizer.zero_grad()

                loss = loss_fnc(ratings_var, predictions)
                epoch_loss += loss.data[0]

                loss.backward()
                self._optimizer.step()

            epoch_loss /= minibatch_num + 1

            if verbose:
                print('Epoch {}: loss {}'.format(epoch_num, epoch_loss))
コード例 #8
0
    def fit(self, interactions, validation_interactions=None, verbose=False):
        """
        Fit the model.

        When called repeatedly, model fitting will resume from
        the point at which training stopped in the previous fit
        call.

        Parameters
        ----------

        interactions: :class:`spotlight.interactions.SequenceInteractions`
            The input sequence dataset.
        """
        train_loss = np.zeros(self._n_iter)
        val_loss = np.zeros(self._n_iter)

        sequences = interactions.sequences.astype(np.int64)
        weights = interactions.weights.astype(np.float32)

        if not self._initialized:
            self._initialize(interactions)

        self._check_input(sequences)

        if validation_interactions is not None:
            validation_sequences = validation_interactions.sequences.astype(
                np.int64)
            validation_weights = validation_interactions.weights.astype(
                np.float32)
            self._check_input(validation_sequences)

        for epoch_num in range(self._n_iter):

            sequences, weights = shuffle(sequences,
                                         weights,
                                         random_state=self._random_state)

            sequences_tensor = gpu(torch.from_numpy(sequences), self._use_cuda)
            weights_tensor = gpu(torch.from_numpy(weights), self._use_cuda)

            epoch_loss = 0.0

            for minibatch_num, (batch_sequence, batch_weights) in enumerate(
                    minibatch(sequences_tensor,
                              weights_tensor,
                              batch_size=self._batch_size)):

                sequence_var = batch_sequence
                weights_var = batch_weights

                user_representation, _ = self._net.user_representation(
                    sequence_var)

                positive_prediction = self._net(user_representation,
                                                sequence_var)

                if self._loss == 'adaptive_hinge':
                    negative_prediction = self._get_multiple_negative_predictions(
                        sequence_var.size(),
                        user_representation,
                        n=self._num_negative_samples)
                else:
                    negative_prediction = self._get_negative_prediction(
                        sequence_var.size(), user_representation)

                self._optimizer.zero_grad()

                loss = self._loss_func(positive_prediction,
                                       negative_prediction,
                                       mask=(sequence_var != PADDING_IDX),
                                       weights=weights_var)
                epoch_loss += loss.item()

                loss.backward()

                self._optimizer.step()

            train_loss[epoch_num] = epoch_loss / (minibatch_num + 1)

            if validation_interactions is not None:
                val_loss[epoch_num] = self._get_validation_loss(
                    validation_sequences, validation_weights)

            if verbose and validation_interactions is not None:
                print('Epoch {}: loss {} \t val-loss {}'.format(
                    epoch_num, train_loss[epoch_num], val_loss[epoch_num]))
            else:
                print('Epoch {}: loss {}'.format(epoch_num,
                                                 train_loss[epoch_num]))

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

        return train_loss, val_loss
コード例 #9
0
    def fit(self, interactions, verbose=False):
        """
        Fit the model.

        Parameters
        ----------

        interactions: :class:`spotlight.interactions.Interactions`
            The input dataset. Must have ratings.
        """

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

        (self._num_users,
         self._num_items) = (interactions.num_users,
                             interactions.num_items)

        self._net = gpu(
            BilinearNet(self._num_users,
                        self._num_items,
                        self._embedding_dim,
                        sparse=self._sparse),
            self._use_cuda
        )

        if self._optimizer is None:
            self._optimizer = optim.Adam(
                self._net.parameters(),
                weight_decay=self._l2,
                lr=self._learning_rate
            )

        if self._loss == 'regression':
            loss_fnc = regression_loss
        elif self._loss == 'poisson':
            loss_fnc = poisson_loss
        else:
            raise ValueError('Unknown loss: {}'.format(self._loss))

        for epoch_num in range(self._n_iter):

            users, items, ratings = shuffle(user_ids,
                                            item_ids,
                                            interactions.ratings,
                                            random_state=self._random_state)

            user_ids_tensor = gpu(torch.from_numpy(users),
                                  self._use_cuda)
            item_ids_tensor = gpu(torch.from_numpy(items),
                                  self._use_cuda)
            ratings_tensor = gpu(torch.from_numpy(ratings),
                                 self._use_cuda)

            epoch_loss = 0.0

            for (minibatch_num,
                 (batch_user,
                  batch_item,
                  batch_ratings)) in enumerate(minibatch(user_ids_tensor,
                                                         item_ids_tensor,
                                                         ratings_tensor,
                                                         batch_size=self._batch_size)):

                user_var = Variable(batch_user)
                item_var = Variable(batch_item)
                ratings_var = Variable(batch_ratings)

                predictions = self._net(user_var, item_var)

                if self._loss == 'poisson':
                    predictions = torch.exp(predictions)

                self._optimizer.zero_grad()

                loss = loss_fnc(ratings_var, predictions)
                epoch_loss += loss.data[0]

                loss.backward()
                self._optimizer.step()

            epoch_loss /= minibatch_num + 1

            if verbose:
                print('Epoch {}: loss {}'.format(epoch_num, epoch_loss))
コード例 #10
0
ファイル: implicit.py プロジェクト: zgsxwsdxg/spotlight
    def fit(self, interactions, verbose=False):
        """
        Fit the model.

        Parameters
        ----------

        interactions: :class:`spotlight.interactions.SequenceInteractions`
            The input sequence dataset.
        """

        sequences = interactions.sequences.astype(np.int64)

        self._num_items = interactions.num_items

        if self._representation == 'pooling':
            self._net = PoolNet(self._num_items,
                                self._embedding_dim,
                                sparse=self._sparse)
        elif self._representation == 'cnn':
            self._net = CNNNet(self._num_items,
                               self._embedding_dim,
                               sparse=self._sparse)
        elif self._representation == 'lstm':
            self._net = LSTMNet(self._num_items,
                                self._embedding_dim,
                                sparse=self._sparse)
        else:
            self._net = self._representation

        self._net = gpu(self._net, self._use_cuda)

        if self._optimizer is None:
            self._optimizer = optim.Adam(self._net.parameters(),
                                         weight_decay=self._l2,
                                         lr=self._learning_rate)

        if self._loss == 'pointwise':
            loss_fnc = pointwise_loss
        elif self._loss == 'bpr':
            loss_fnc = bpr_loss
        elif self._loss == 'hinge':
            loss_fnc = hinge_loss
        else:
            loss_fnc = adaptive_hinge_loss

        for epoch_num in range(self._n_iter):

            sequences = shuffle(sequences, random_state=self._random_state)

            sequences_tensor = gpu(torch.from_numpy(sequences), self._use_cuda)

            epoch_loss = 0.0

            for minibatch_num, batch_sequence in enumerate(
                    minibatch(sequences_tensor, batch_size=self._batch_size)):

                sequence_var = Variable(batch_sequence)

                user_representation, _ = self._net.user_representation(
                    sequence_var)

                positive_prediction = self._net(user_representation,
                                                sequence_var)

                if self._loss == 'adaptive_hinge':
                    negative_prediction = [
                        self._get_negative_prediction(sequence_var.size(),
                                                      user_representation)
                        for __ in range(5)
                    ]
                else:
                    negative_prediction = self._get_negative_prediction(
                        sequence_var.size(), user_representation)

                self._optimizer.zero_grad()

                loss = loss_fnc(positive_prediction,
                                negative_prediction,
                                mask=(sequence_var != PADDING_IDX))
                epoch_loss += loss.data[0]

                loss.backward()
                self._optimizer.step()

            epoch_loss /= minibatch_num + 1

            if verbose:
                print('Epoch {}: loss {}'.format(epoch_num, epoch_loss))
コード例 #11
0
    def fit(self,
            interactions,
            verbose=False,
            calc_map=False,
            neg_mode="original"):
        """
        Fit the model.

        When called repeatedly, model fitting will resume from
        the point at which training stopped in the previous fit
        call.

        Parameters
        ----------

        interactions: :class:`spotlight.interactions.SequenceInteractions`
            The input sequence dataset.
        """

        sequences = interactions.sequences.astype(np.int64)
        user_ids = interactions.user_ids

        if not self._initialized:
            self._initialize(interactions)

        self._check_input(sequences)
        best_map = 0
        np.random.seed(0)
        random_state = np.random.RandomState()
        for epoch_num in range(self._n_iter):

            start_time = time.time()
            shuffle_indices = np.arange(sequences.shape[0])
            random_state.shuffle(shuffle_indices)
            sequences = sequences[shuffle_indices]
            user_ids = user_ids[shuffle_indices]

            #sequences = shuffle(sequences,
            #                    random_state=self._random_state)

            sequences_tensor = gpu(torch.from_numpy(sequences), self._use_cuda)

            epoch_loss = 0.0

            #for minibatch_num, batch_sequence in enumerate(minibatch(sequences_tensor,
            #                                                         batch_size=self._batch_size)):
            for minibatch_num in range(sequences.shape[0] // self._batch_size):
                sequence_var = sequences_tensor[minibatch_num *
                                                self._batch_size:
                                                (minibatch_num + 1) *
                                                self._batch_size]
                mini_user_ids = user_ids[minibatch_num *
                                         self._batch_size:(minibatch_num + 1) *
                                         self._batch_size]

                #sequence_var = batch_sequence

                user_representation, _ = self._net.user_representation(
                    sequence_var)

                positive_prediction = self._net(user_representation,
                                                sequence_var)

                if neg_mode == "original":
                    if self._loss == 'adaptive_hinge':
                        negative_prediction = self._get_multiple_negative_predictions(
                            sequence_var.size(),
                            user_representation,
                            n=self._num_negative_samples)
                    else:
                        negative_prediction = self._get_negative_prediction(
                            sequence_var.size(), user_representation)
                elif neg_mode == "mine":
                    '''
                    example:
                        sequence = [1,4,2,48,999,8], userid = 0
                        use neg_prob of user 0 to pick a food 'x'
                        replace the 8 with 'x'
                        negative sequence = [1,4,2,48,999,x]
                    '''
                    if self._loss == 'adaptive_hinge' or self._loss == 'mine':
                        negative_prediction = self.my_get_multiple_negative_predictions2(
                            sequence_var.cpu().data,
                            mini_user_ids,
                            user_representation,
                            n=self._num_negative_samples)
                        #tmp = np.zeros((self._batch_size * self._num_negative_samples, negative_prediction.size(1)))
                        #tmp[:, -1] = 1
                        #tmp = gpu(torch.from_numpy(tmp).float(), self._use_cuda)
                        #negative_prediction *= tmp
                    else:
                        negative_prediction = self.my_get_negative_prediction2(
                            sequence_var.cpu().data, mini_user_ids,
                            user_representation)
                        #tmp = np.zeros((self._batch_size, negative_prediction.size(1)))
                        #tmp[:, -1] = 1
                        #tmp = gpu(torch.from_numpy(tmp).float(), self._use_cuda)
                        #negative_prediction *= tmp

                self._optimizer.zero_grad()

                #loss = self._loss_func(positive_prediction,
                #                       negative_prediction,
                #                       mask=(sequence_var != PADDING_IDX))
                loss = torch.nn.CrossEntropyLoss()(positive_prediction,
                                                   sequence_var[:, -1])
                epoch_loss += loss.item()

                loss.backward()

                self._optimizer.step()

            epoch_loss /= minibatch_num + 1

            if calc_map:  # takes too much time, about 20 mins, so set as an option
                print("calculating map")
                self._net.train(False)
                map_start = time.time()
                ap = NewAveragePrecision(self, self.test_data, 20)
                print("calculate map time", time.time() - map_start)
                self._net.train(True)
            else:
                ap = np.zeros(10)

            if verbose:
                print('Epoch {}: loss {} map: {}; time: {}'.format(
                    epoch_num, epoch_loss, ap.mean(),
                    time.time() - start_time))

            if np.isnan(epoch_loss) or epoch_loss == 0.0:
                raise ValueError(
                    'Degenerate epoch loss: {}'.format(epoch_loss))
コード例 #12
0
    def fit(self, interactions, verbose=False):
        """
        Fit the model.

        When called repeatedly, model fitting will resume from
        the point at which training stopped in the previous fit
        call.

        Parameters
        ----------

        interactions: :class:`spotlight.interactions.Interactions`
            The input dataset.

        verbose: bool
            Output additional information about current epoch and loss.
        """

        user_ids = interactions.user_ids.astype(np.int64)
        item_ids = interactions.item_ids.astype(np.int64)
        ratings =  interactions.ratings.astype(np.int64)


        user_ids = user_ids[0:self.inputSample]
        item_ids = item_ids[0:self.inputSample]
        ratings = ratings[0:self.inputSample]

        # pdb.Pdb.complete = rlcompleter.Completer(locals()).complete
        # pdb.set_trace()

        if not self._initialized:
            self._initialize(interactions)

        self._check_input(user_ids, item_ids)

        for epoch_num in range(self._n_iter):

            users, items = shuffle(user_ids,
                                   item_ids,
                                   random_state=self._random_state)

            user_ids_tensor = gpu(torch.from_numpy(users),
                                  self._use_cuda)
            item_ids_tensor = gpu(torch.from_numpy(items),
                                  self._use_cuda)

            rating_ids_tensor = gpu(torch.from_numpy(ratings),
                                  self._use_cuda)

            epoch_loss = 0.0

            for (minibatch_num,
                 (batch_user,
                  batch_item, batch_rating)) in enumerate(minibatch(user_ids_tensor,
                                                      item_ids_tensor, rating_ids_tensor,
                                                      batch_size=self._batch_size)):

                user_var = Variable(batch_user)
                pos_item = Variable(batch_item)
                rating = Variable(batch_rating)
                neg_item = self._get_negative_items(user_var)

                x, target = self._rankDataPrepSwapping(user_var, pos_item, rating, neg_item)

                pred_prob = self._net(x)
                self._optimizer.zero_grad()
                loss = self.bceLoss(pred_prob, target)
                # loss = self._loss_func(pred_prob, target)
                '''
                if random > 0.5:
                    pred = self._net(user_var, pos_item, neg_item)
                else:
                    pred = self._net(user_var, neg_item, pos_item)
                pred = self._net(user_var, item_var, neg_item)
                self._optimizer.zero_grad()
                loss = self._loss_func(positive_prediction, negative_prediction)
                '''
                epoch_loss += loss.data[0]
                loss.backward()
                self._optimizer.step()

            epoch_loss /= minibatch_num + 1

            if verbose:
                print('Epoch {}: loss {}'.format(epoch_num, epoch_loss))

            if np.isnan(epoch_loss) or epoch_loss == 0.0:
                raise ValueError('Degenerate epoch loss: {}'
                                 .format(epoch_loss))
コード例 #13
0
ファイル: implicit.py プロジェクト: AlexMikhalev/spotlight
    def fit(self, interactions, verbose=False):
        """
        Fit the model.

        Parameters
        ----------

        interactions: :class:`spotlight.interactions.SequenceInteractions`
            The input sequence dataset.
        """

        sequences = interactions.sequences.astype(np.int64)

        self._num_items = interactions.num_items

        if self._representation == 'pooling':
            self._net = PoolNet(self._num_items,
                                self._embedding_dim,
                                sparse=self._sparse)
        elif self._representation == 'cnn':
            self._net = CNNNet(self._num_items,
                               self._embedding_dim,
                               sparse=self._sparse)
        elif self._representation == 'lstm':
            self._net = LSTMNet(self._num_items,
                                self._embedding_dim,
                                sparse=self._sparse)
        else:
            self._net = self._representation

        self._net = gpu(self._net, self._use_cuda)

        if self._optimizer is None:
            self._optimizer = optim.Adam(
                self._net.parameters(),
                weight_decay=self._l2,
                lr=self._learning_rate
            )
        else:
            self._optimizer = self._optimizer_func(self._net.parameters())

        if self._loss == 'pointwise':
            loss_fnc = pointwise_loss
        elif self._loss == 'bpr':
            loss_fnc = bpr_loss
        elif self._loss == 'hinge':
            loss_fnc = hinge_loss
        else:
            loss_fnc = adaptive_hinge_loss

        for epoch_num in range(self._n_iter):

            sequences = shuffle(sequences,
                                random_state=self._random_state)

            sequences_tensor = gpu(torch.from_numpy(sequences),
                                   self._use_cuda)

            epoch_loss = 0.0

            for minibatch_num, batch_sequence in enumerate(minibatch(sequences_tensor,
                                                                     batch_size=self._batch_size)):

                sequence_var = Variable(batch_sequence)

                user_representation, _ = self._net.user_representation(
                    sequence_var
                )

                positive_prediction = self._net(user_representation,
                                                sequence_var)

                if self._loss == 'adaptive_hinge':
                    negative_prediction = [self._get_negative_prediction(sequence_var.size(),
                                                                         user_representation)
                                           for __ in range(5)]
                else:
                    negative_prediction = self._get_negative_prediction(sequence_var.size(),
                                                                        user_representation)

                self._optimizer.zero_grad()

                loss = loss_fnc(positive_prediction,
                                negative_prediction,
                                mask=(sequence_var != PADDING_IDX))
                epoch_loss += loss.data[0]

                loss.backward()
                self._optimizer.step()

            epoch_loss /= minibatch_num + 1

            if verbose:
                print('Epoch {}: loss {}'.format(epoch_num, epoch_loss))
コード例 #14
0
    def fit(self, interactions, verbose=False):
        """
        Fit the model.

        When called repeatedly, model fitting will resume from
        the point at which training stopped in the previous fit
        call.

        Parameters
        ----------

        interactions: :class:`spotlight.interactions.SequenceInteractions`
            The input sequence dataset.
        """

        # genereate list of short sequences from a long sequence
        # + window_size is max_sequence_length: length of short sequences
        # + step_size for number of short sequences.
        #       + For example: long sequence with length 10 with step_size = 3
        #         will generate 3 short sequences.
        sequences = interactions.sequences.astype(np.int64)

        if not self._initialized:
            self._initialize(interactions)

        self._check_input(sequences)

        for epoch_num in range(self._n_iter):

            sequences = shuffle(sequences, random_state=self._random_state)

            sequences_tensor = gpu(torch.from_numpy(sequences), self._use_cuda)

            epoch_loss = 0.0

            for minibatch_num, batch_sequence in enumerate(
                    minibatch(sequences_tensor, batch_size=self._batch_size)):

                # sequence_var is list of short sequences, size of this list equal batch_size
                # sequence_var shape: torch.Size([batch_size, window_size])
                sequence_var = batch_sequence

                # user_presentation shape:  torch.Size([batch_size, embedding_size, window_size])
                user_representation, _ = self._net.user_representation(
                    sequence_var)

                positive_prediction = self._net(user_representation,
                                                sequence_var)

                if self._loss == 'adaptive_hinge':
                    negative_prediction = self._get_multiple_negative_predictions(
                        sequence_var.size(),
                        user_representation,
                        n=self._num_negative_samples)
                else:
                    negative_prediction = self._get_negative_prediction(
                        sequence_var.size(), user_representation)

                self._optimizer.zero_grad()

                loss = self._loss_func(positive_prediction,
                                       negative_prediction,
                                       mask=(sequence_var != PADDING_IDX))
                epoch_loss += loss.item()

                loss.backward()

                self._optimizer.step()

            epoch_loss /= minibatch_num + 1

            if verbose:
                print('Epoch {}: loss {}'.format(epoch_num, epoch_loss))

            if np.isnan(epoch_loss) or epoch_loss == 0.0:
                raise ValueError(
                    'Degenerate epoch loss: {}'.format(epoch_loss))
コード例 #15
0
ファイル: implicit.py プロジェクト: euwen/spotlight
    def fit(self, interactions, verbose=False):
        """
        Fit the model.

        When called repeatedly, model fitting will resume from
        the point at which training stopped in the previous fit
        call.

        Parameters
        ----------

        interactions: :class:`spotlight.interactions.Interactions`
            The input dataset.
        """

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

        if not self._initialized:
            self._initialize(interactions)

        self._check_input(user_ids, item_ids)

        for epoch_num in range(self._n_iter):

            users, items = shuffle(user_ids,
                                   item_ids,
                                   random_state=self._random_state)

            user_ids_tensor = gpu(torch.from_numpy(users), self._use_cuda)
            item_ids_tensor = gpu(torch.from_numpy(items), self._use_cuda)

            epoch_loss = 0.0

            for (minibatch_num, (batch_user, batch_item)) in enumerate(
                    minibatch(user_ids_tensor,
                              item_ids_tensor,
                              batch_size=self._batch_size)):

                user_var = Variable(batch_user)
                item_var = Variable(batch_item)
                positive_prediction = self._net(user_var, item_var)

                if self._loss == 'adaptive_hinge':
                    negative_prediction = self._get_multiple_negative_predictions(
                        user_var, n=self._num_negative_samples)
                else:
                    negative_prediction = self._get_negative_prediction(
                        user_var)

                self._optimizer.zero_grad()

                loss = self._loss_func(positive_prediction,
                                       negative_prediction)
                epoch_loss += loss.data[0]

                loss.backward()
                self._optimizer.step()

            epoch_loss /= minibatch_num + 1

            if verbose:
                print('Epoch {}: loss {}'.format(epoch_num, epoch_loss))

            if np.isnan(epoch_loss) or epoch_loss == 0.0:
                raise ValueError(
                    'Degenerate epoch loss: {}'.format(epoch_loss))
コード例 #16
0
ファイル: implicit.py プロジェクト: snemistry/spotlight
    def fit(self, interactions, verbose=False):
        """
        Fit the model.

        When called repeatedly, model fitting will resume from
        the point at which training stopped in the previous fit
        call.

        Parameters
        ----------

        interactions: :class:`spotlight.interactions.Interactions`
            The input dataset.

        verbose: bool
            Output additional information about current epoch and loss.
        """

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

        if not self._initialized:
            self._initialize(interactions)

        self._check_input(user_ids, item_ids)
        time_step = 0

        for epoch_num in range(self._n_iter):

            users, items = shuffle(user_ids,
                                   item_ids,
                                   random_state=self._random_state)

            user_ids_tensor = gpu(torch.from_numpy(users), self._use_cuda)
            item_ids_tensor = gpu(torch.from_numpy(items), self._use_cuda)

            epoch_loss = 0.0
            interval_loss = 0.0
            interval_batches = 0.0
            epoch_batches = 0.0

            for (minibatch_num, (batch_user, batch_item)) in enumerate(
                    minibatch(user_ids_tensor,
                              item_ids_tensor,
                              batch_size=self._batch_size)):
                self._net.train(True)
                positive_prediction = self._net(batch_user, batch_item)

                if self._loss == 'adaptive_hinge':
                    negative_prediction = self._get_multiple_negative_predictions(
                        batch_user, n=self._num_negative_samples)
                else:
                    negative_prediction = self._get_negative_prediction(
                        batch_user)

                self._optimizer.zero_grad()

                loss = self._loss_func(positive_prediction,
                                       negative_prediction)
                loss_val = loss.item()
                epoch_loss += loss_val
                interval_loss += loss_val

                loss.backward()
                self._optimizer.step()
                interval_batches += 1

                if time_step % self._log_loss_interval == 0:
                    if self._notify_loss_completion:
                        self._notify_loss_completion(
                            epoch_num, time_step,
                            interval_loss / interval_batches, self._net, self)

                if time_step % self._log_eval_interval == 0:
                    if self._notify_batch_eval_completion:
                        self._notify_batch_eval_completion(
                            epoch_num, time_step,
                            interval_loss / interval_batches, self._net, self)

                if time_step % self._log_loss_interval == 0:
                    interval_loss = 0.0
                    interval_batches = 0.0

                time_step += 1

            epoch_batches += 1
            epoch_loss /= epoch_batches

            if verbose:
                print('Epoch {}: loss {}'.format(epoch_num, epoch_loss))

            if self._notify_epoch_completion:
                self._notify_epoch_completion(epoch_num, epoch_loss, self._net,
                                              self)

            if np.isnan(epoch_loss) or epoch_loss == 0.0:
                raise ValueError(
                    'Degenerate epoch loss: {}'.format(epoch_loss))
コード例 #17
0
ファイル: implicit.py プロジェクト: zacbayhan/spotlight
    def fit(self, interactions, verbose=False):
        """
        Fit the model.

        When called repeatedly, model fitting will resume from
        the point at which training stopped in the previous fit
        call.

        Parameters
        ----------

        interactions: :class:`spotlight.interactions.SequenceInteractions`
            The input sequence dataset.
        """

        sequences = interactions.sequences.astype(np.int64)

        if not self._initialized:
            self._initialize(interactions)

        self._check_input(sequences)

        for epoch_num in range(self._n_iter):

            sequences = shuffle(sequences,
                                random_state=self._random_state)

            sequences_tensor = gpu(torch.from_numpy(sequences),
                                   self._use_cuda)

            epoch_loss = 0.0

            for minibatch_num, batch_sequence in enumerate(minibatch(sequences_tensor,
                                                                     batch_size=self._batch_size)):

                sequence_var = Variable(batch_sequence)

                user_representation, _ = self._net.user_representation(
                    sequence_var
                )

                positive_prediction = self._net(user_representation,
                                                sequence_var)

                if self._loss == 'adaptive_hinge':
                    negative_prediction = [self._get_negative_prediction(sequence_var.size(),
                                                                         user_representation)
                                           for __ in range(5)]
                else:
                    negative_prediction = self._get_negative_prediction(sequence_var.size(),
                                                                        user_representation)

                self._optimizer.zero_grad()

                loss = self._loss_func(positive_prediction,
                                       negative_prediction,
                                       mask=(sequence_var != PADDING_IDX))
                epoch_loss += loss.data[0]

                loss.backward()
                self._optimizer.step()

            epoch_loss /= minibatch_num + 1

            if verbose:
                print('Epoch {}: loss {}'.format(epoch_num, epoch_loss))
コード例 #18
0
ファイル: implicit.py プロジェクト: timkersch/spotlight
    def fit(self, interactions, validation_interactions=None, verbose=False):
        """
        Fit the model.

        When called repeatedly, model fitting will resume from
        the point at which training stopped in the previous fit
        call.

        Parameters
        ----------

        interactions: :class:`spotlight.interactions.Interactions`
            The input dataset.

        verbose: bool
            Output additional information about current epoch and loss.
        """

        train_loss = np.zeros(self._n_iter)
        val_loss = np.zeros(self._n_iter)

        user_ids = interactions.user_ids.astype(np.int64)
        item_ids = interactions.item_ids.astype(np.int64)
        weights = interactions.weights.astype(np.float32)

        if not self._initialized:
            self._initialize(interactions)

        self._check_input(user_ids, item_ids)

        for epoch_num in range(self._n_iter):

            users, items, weights = shuffle(user_ids,
                                            item_ids,
                                            weights,
                                            random_state=self._random_state)

            user_ids_tensor = gpu(torch.from_numpy(users), self._use_cuda)
            item_ids_tensor = gpu(torch.from_numpy(items), self._use_cuda)
            weights_tensor = gpu(torch.from_numpy(weights), self._use_cuda)

            epoch_loss = 0.0

            for (minibatch_num, (batch_user, batch_item,
                                 batch_weight)) in enumerate(
                                     minibatch(user_ids_tensor,
                                               item_ids_tensor,
                                               weights_tensor,
                                               batch_size=self._batch_size)):

                positive_prediction = self._net(batch_user, batch_item)

                if self._loss == 'adaptive_hinge':
                    negative_prediction = self._get_multiple_negative_predictions(
                        batch_user, n=self._num_negative_samples)
                else:
                    negative_prediction = self._get_negative_prediction(
                        batch_user)

                self._optimizer.zero_grad()

                loss = self._loss_func(positive_prediction,
                                       negative_prediction,
                                       weights=batch_weight)
                epoch_loss += loss.item()

                loss.backward()
                self._optimizer.step()

            train_loss[epoch_num] = epoch_loss / (minibatch_num + 1)

            if validation_interactions is not None:
                val_loss[epoch_num] = self._get_validation_loss(
                    validation_interactions)

            if verbose and validation_interactions is not None:
                print('Epoch {}: loss {} \t val-loss {}'.format(
                    epoch_num, train_loss[epoch_num], val_loss[epoch_num]))
            else:
                print('Epoch {}: loss {}'.format(epoch_num,
                                                 train_loss[epoch_num]))

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

        return train_loss, val_loss
コード例 #19
0
    def fit(self, interactions, verbose=False):
        """
        Fit the model.

        Parameters
        ----------

        interactions: :class:`spotlight.interactions.Interactions`
            The input dataset.
        """

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

        (self._num_users, self._num_items) = (interactions.num_users,
                                              interactions.num_items)

        self._net = gpu(
            BilinearNet(self._num_users,
                        self._num_items,
                        self._embedding_dim,
                        sparse=self._sparse), self._use_cuda)

        if self._optimizer is None:
            self._optimizer = optim.Adam(self._net.parameters(),
                                         weight_decay=self._l2,
                                         lr=self._learning_rate)
        else:
            self._optimizer = self._optimizer_func(self._net.parameters())

        if self._loss == 'pointwise':
            loss_fnc = pointwise_loss
        elif self._loss == 'bpr':
            loss_fnc = bpr_loss
        elif self._loss == 'hinge':
            loss_fnc = hinge_loss
        else:
            loss_fnc = adaptive_hinge_loss

        for epoch_num in range(self._n_iter):

            users, items = shuffle(user_ids,
                                   item_ids,
                                   random_state=self._random_state)

            user_ids_tensor = gpu(torch.from_numpy(users), self._use_cuda)
            item_ids_tensor = gpu(torch.from_numpy(items), self._use_cuda)

            epoch_loss = 0.0

            for (minibatch_num, (batch_user, batch_item)) in enumerate(
                    minibatch(user_ids_tensor,
                              item_ids_tensor,
                              batch_size=self._batch_size)):

                user_var = Variable(batch_user)
                item_var = Variable(batch_item)
                positive_prediction = self._net(user_var, item_var)

                if self._loss == 'adaptive_hinge':
                    negative_prediction = [
                        self._get_negative_prediction(user_var)
                        for _ in range(5)
                    ]
                else:
                    negative_prediction = self._get_negative_prediction(
                        user_var)

                self._optimizer.zero_grad()

                loss = loss_fnc(positive_prediction, negative_prediction)
                epoch_loss += loss.data[0]

                loss.backward()
                self._optimizer.step()

            epoch_loss /= minibatch_num + 1

            if verbose:
                print('Epoch {}: loss {}'.format(epoch_num, epoch_loss))
コード例 #20
0
ファイル: implicit.py プロジェクト: AlexMikhalev/spotlight
    def fit(self, interactions, verbose=False):
        """
        Fit the model.

        Parameters
        ----------

        interactions: :class:`spotlight.interactions.Interactions`
            The input dataset.
        """

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

        (self._num_users,
         self._num_items) = (interactions.num_users,
                             interactions.num_items)

        self._net = gpu(
            BilinearNet(self._num_users,
                        self._num_items,
                        self._embedding_dim,
                        sparse=self._sparse),
            self._use_cuda
        )

        if self._optimizer is None:
            self._optimizer = optim.Adam(
                self._net.parameters(),
                weight_decay=self._l2,
                lr=self._learning_rate
            )
        else:
            self._optimizer = self._optimizer_func(self._net.parameters())

        if self._loss == 'pointwise':
            loss_fnc = pointwise_loss
        elif self._loss == 'bpr':
            loss_fnc = bpr_loss
        elif self._loss == 'hinge':
            loss_fnc = hinge_loss
        else:
            loss_fnc = adaptive_hinge_loss

        for epoch_num in range(self._n_iter):

            users, items = shuffle(user_ids,
                                   item_ids,
                                   random_state=self._random_state)

            user_ids_tensor = gpu(torch.from_numpy(users),
                                  self._use_cuda)
            item_ids_tensor = gpu(torch.from_numpy(items),
                                  self._use_cuda)

            epoch_loss = 0.0

            for (minibatch_num,
                 (batch_user,
                  batch_item)) in enumerate(minibatch(user_ids_tensor,
                                                      item_ids_tensor,
                                                      batch_size=self._batch_size)):

                user_var = Variable(batch_user)
                item_var = Variable(batch_item)
                positive_prediction = self._net(user_var, item_var)

                if self._loss == 'adaptive_hinge':
                    negative_prediction = [self._get_negative_prediction(user_var)
                                           for _ in range(5)]
                else:
                    negative_prediction = self._get_negative_prediction(user_var)

                self._optimizer.zero_grad()

                loss = loss_fnc(positive_prediction, negative_prediction)
                epoch_loss += loss.data[0]

                loss.backward()
                self._optimizer.step()

            epoch_loss /= minibatch_num + 1

            if verbose:
                print('Epoch {}: loss {}'.format(epoch_num, epoch_loss))