Ejemplo n.º 1
0
def train_mfips(sess: tf.Session, model: MFIPS, data: str,
                train: np.ndarray, val: np.ndarray, test: np.ndarray,
                max_iters: int = 500, batch_size: int = 2**9,
                model_name: str = 'mf', seed: int = 0) -> Tuple:
    """Train and evaluate the MF-IPS model."""
    train_loss_list = []
    val_loss_list = []
    test_mse_list = []
    test_mae_list = []

    # initialise all the TF variables
    init_op = tf.global_variables_initializer()
    sess.run(init_op)

    # count the num of training data and estimate the propensity scores.
    num_train = train.shape[0]
    train_mcar, test = train_test_split(test, test_size=0.95, random_state=12345)
    pscore_train, pscore_val = estimate_pscore(train=train, train_mcar=train_mcar,
                                               val=val, model_name=model_name)
    labels_train = np.expand_dims(train[:, 2], 1)
    labels_val = np.expand_dims(val[:, 2], 1)
    labels_test = np.expand_dims(test[:, 2], 1)

    # start running training a recommender
    np.random.seed(12345)
    for iter_ in np.arange(max_iters):
        # mini-batch sampling
        idx = np.random.choice(np.arange(num_train), size=batch_size)
        train_batch, pscore_batch, labels_batch = train[idx], pscore_train[idx], labels_train[idx]
        # update user-item latent factors
        _, loss = sess.run([model.apply_grads, model.loss],
                           feed_dict={model.users: train_batch[:, 0], model.items: train_batch[:, 1],
                                      model.labels: labels_batch, model.scores: pscore_batch})
        train_loss_list.append(loss)
        # calculate validation loss
        val_loss = sess.run(model.weighted_mse,
                            feed_dict={model.users: val[:, 0], model.items: val[:, 1],
                                       model.labels: labels_val, model.scores: pscore_val})
        val_loss_list.append(val_loss)
        # calculate test loss
        mse_score, mae_score = sess.run([model.mse, model.mae],
                                        feed_dict={model.users: test[:, 0],
                                                   model.items: test[:, 1],
                                                   model.labels: labels_test})
        test_mse_list.append(mse_score)
        test_mae_list.append(mae_score)

    u_emb, i_emb, i_bias = sess.run([model.user_embeddings, model.item_embeddings, model.item_bias])

    sess.close()

    return (np.min(val_loss_list),
            test_mse_list[np.argmin(val_loss_list)],
            test_mae_list[np.argmin(val_loss_list)],
            u_emb, i_emb, i_bias)
Ejemplo n.º 2
0
Archivo: Base.py Proyecto: xeren/OpenKE
class ModelClass(object):
    '''Properties and behaviour that different embedding models share.'''
    def fit(self, head, tail, label, score):
        '''Trains the model on a batch of weighted statements.'''
        feed = {
            self.batch_h: head,
            self.batch_t: tail,
            self.batch_l: label,
            self.batch_y: score
        }
        return self.__session.run([self.__training, self.__loss], feed)[1]

    def predict(self, head, tail, label):
        '''Evaluates the model's scores on a batch of statements.'''
        from numpy import arange, full

        # transform wildcard parameters
        # require otherwise scalar parameters
        E, R = self.base
        if head is None:
            if tail is None:
                if label is None:
                    raise NotImplementedError('universal prediction')
                raise NotImplementedError('full-relation prediction')
            elif label is None:
                raise NotImplementedError('full-tail prediction')
            head, tail, label = arange(E), full([E], tail), full([E], label)
        elif tail is None:
            if label is None:
                raise NotImplementedError('full-head prediction')
            head, tail, label = full([E], head), arange(E), full([E], label)
        elif label is None:
            head, tail, label = full([R], head), full([R], tail), arange(R)

        # perform prediction
        feed = {
            self.predict_h: head,
            self.predict_t: tail,
            self.predict_l: label
        }
        return self.__session.run(self.__prediction, feed)

    def relation(self, label=None):
        '''Embeds a batch of predicates.'''
        if head is None:
            with self.__graph.as_default():
                with self.__session.as_default():
                    return self.__session.run(self._rel_embeddings)
        feed = {self.predict_l: label}
        return self.__session.run(self._relation, feed)

    def entity(self, head=None):
        '''Embeds a batch of subjects.'''
        if head is None:
            with self.__session.as_default():
                return self.__session.run(self._ent_embeddings)
        feed = {self.predict_h: head}
        return self.__session.run(self._entity, feed)

    def save(self, fileprefix):
        '''Writes the model's state into persistent memory.'''
        self.__saver.save(self.__session, fileprefix)

    def restore(self, fileprefix):
        '''Reads a model from persistent memory.'''
        self.__saver.restore(self.__session, fileprefix)

    def __iter__(self):
        '''Iterates all parameter fields of the model.'''
        return iter(self.__parameters)

    def __getitem__(self, key):
        '''Retrieves the values of a parameter field.'''
        return self.__session.run(self.__parameters[key])

    def __setitem__(self, key, value):
        '''Updates the values of a parameter field.'''
        with self.__graph.as_default():
            with self.__session.as_default():
                self.__parameters[key].assign(value).eval()

    def embedding_def(self):
        pass

    def loss_def(self):
        raise NotImplementedError('loss impossible without model')

    def predict_def(self):
        raise NotImplementedError('prediction impossible without model')

    def __init__(self, baseshape, batchshape=None, optimizer=None, norm=None):
        '''Creates a new model.

	baseshape
A pair of numbers describing the amount of entities and relations.

	batchshape
A pair of numbers describing the amount of training statements per iteration and the amount of variants per statement.
The first variant is considered true while the rest is considered false.
default: Model not intended for training

	optimizer
The optimization algorithm used to approximate the optimal model in each iteration.
default: Stochastic Gradient Descent with learning factor of 1%.

	norm
The used vector norm to compute a scalar score from the model's prediction.
default: L1 norm (sum of absolute features).'''

        from tensorflow import name_scope, transpose, reshape, placeholder, int64, float32, Session, Graph, global_variables_initializer, variable_scope, nn, AUTO_REUSE
        from tensorflow.contrib.layers import xavier_initializer
        from tensorflow.python.training.saver import Saver
        self.base = baseshape
        if batchshape is None:
            batchshape = 0, 0
        self.batchsize = batchshape[0]
        self.negatives = batchshape[1] - 1
        self.__parameters = dict()
        if optimizer is None:
            import tensorflow
            optimizer = tensorflow.train.GradientDescentOptimizer(.01)
        if norm is None:
            from .norm import l1
            norm = l1
        self._norm = norm
        B, N = self.batchsize, self.negatives
        S = B * (N + 1)
        self.__graph = Graph()
        with self.__graph.as_default():
            self.__session = Session()
            with self.__session.as_default():
                initializer = xavier_initializer(uniform=True)
                with variable_scope('model',
                                    reuse=AUTO_REUSE,
                                    initializer=initializer):
                    with name_scope('input'):
                        self.batch_h = placeholder(int64, [S])
                        self.batch_t = placeholder(int64, [S])
                        self.batch_l = placeholder(int64, [S])
                        self.batch_y = placeholder(float32, [S])
                        self.all_h = transpose(
                            reshape(self.batch_h, [1 + N, -1]), [1, 0])
                        self.all_t = transpose(
                            reshape(self.batch_t, [1 + N, -1]), [1, 0])
                        self.all_l = transpose(
                            reshape(self.batch_l, [1 + N, -1]), [1, 0])
                        self.all_y = transpose(
                            reshape(self.batch_y, [1 + N, -1]), [1, 0])
                        self.postive_h = transpose(
                            reshape(self.batch_h[:B], [1, -1]), [1, 0])
                        self.postive_t = transpose(
                            reshape(self.batch_t[:B], [1, -1]), [1, 0])
                        self.postive_l = transpose(
                            reshape(self.batch_l[:B], [1, -1]), [1, 0])
                        self.negative_h = transpose(
                            reshape(self.batch_h[B:], [N, -1]), [1, 0])
                        self.negative_t = transpose(
                            reshape(self.batch_t[B:], [N, -1]), [1, 0])
                        self.negative_l = transpose(
                            reshape(self.batch_l[B:], [N, -1]), [1, 0])
                        self.predict_h = placeholder(int64, [None])
                        self.predict_t = placeholder(int64, [None])
                        self.predict_l = placeholder(int64, [None])
                    with name_scope('embedding'):
                        for k, v in self._embedding_def():
                            self.__parameters[k] = v
                    with name_scope('loss'):
                        self.__loss = self._loss_def()
                    with name_scope('predict'):
                        self.__prediction = self._predict_def()
                    grads_and_vars = optimizer.compute_gradients(self.__loss)
                    self.__training = optimizer.apply_gradients(grads_and_vars)
                self.__saver = Saver()
                self.__session.run(global_variables_initializer())

    def _positive_instance(self, in_batch=True):
        if in_batch:
            return self.postive_h, self.postive_t, self.postive_l
        B = self.batchsize
        return self.batch_h[:B], self.batch_t[:B], self.batch_l[:B]

    def _negative_instance(self, in_batch=True):
        if in_batch:
            return self.negative_h, self.negative_t, self.negative_l
        B = self.batchsize
        return self.batch_h[B:], self.batch_t[B:], self.batch_l[B:]

    def _all_instance(self, in_batch=False):
        if in_batch:
            return self.all_h, self.all_t, self.all_l
        return self.batch_h, self.batch_t, self.batch_l

    def _all_labels(self, in_batch=False):
        if in_batch:
            return self.all_y
        return self.batch_y

    def _predict_instance(self):
        return [self.predict_h, self.predict_t, self.predict_l]

    def __del__(self):
        self.__session.close()
Ejemplo n.º 3
0
def pairwise_trainer(sess: tf.Session,
                     data: str,
                     model: PairwiseRecommender,
                     train: np.ndarray,
                     train_point: np.ndarray,
                     test_point: np.ndarray,
                     max_iters: int = 1000,
                     batch_size: int = 2**12,
                     model_name: str = 'bpr') -> None:
    """Train and evaluate implicit pairwise recommenders."""
    train_loss_list = []

    # initialise all the TF variables
    init_op = tf.global_variables_initializer()
    sess.run(init_op)

    # count the num of training data.
    num_train = train.shape[0]
    # train the given implicit recommender
    np.random.seed(12345)
    for i in np.arange(max_iters):
        # mini-batch samples
        idx = np.random.choice(np.arange(num_train, dtype=int),
                               size=np.int(batch_size))
        train_batch = train[idx]

        # update user-item latent factors
        if model_name in 'bpr':
            scores = np.ones((batch_size, 1))
            labels2 = np.zeros((batch_size, 1))
            _, loss = sess.run(
                [model.apply_grads, model.loss],
                feed_dict={
                    model.users: train_batch[:, 0],
                    model.pos_items: train_batch[:, 1],
                    model.scores1: scores,
                    model.items2: train_batch[:, 2],
                    model.labels2: labels2,
                    model.scores2: scores
                })
        elif 'ubpr' in model_name:
            _, loss = sess.run(
                [model.apply_grads, model.loss],
                feed_dict={
                    model.users: train_batch[:, 0],
                    model.pos_items: train_batch[:, 1],
                    model.scores1: np.expand_dims(train_batch[:, 4], 1),
                    model.items2: train_batch[:, 2],
                    model.labels2: np.expand_dims(train_batch[:, 3], 1),
                    model.scores2: np.expand_dims(train_batch[:, 5], 1)
                })
        train_loss_list.append(loss)

    # save embeddings.
    u_emb, i_emb = sess.run([model.user_embeddings, model.item_embeddings])
    np.save(file=f'../logs/{model_name}/embeds/user_embed.npy', arr=u_emb)
    np.save(file=f'../logs/{model_name}/embeds/item_embed.npy', arr=i_emb)
    # save train and val loss curves.
    np.save(file=f'../logs/{model_name}/loss/train.npy',
            arr=np.array(train_loss_list))

    sess.close()
Ejemplo n.º 4
0
def pointwise_trainer(sess: tf.Session,
                      data: str,
                      model: PointwiseRecommender,
                      train: np.ndarray,
                      test: np.ndarray,
                      propensity: np.ndarray,
                      max_iters: int = 1000,
                      batch_size: int = 2**12,
                      model_name: str = 'relmf') -> None:
    """Train and evaluate implicit pointwise recommender."""
    train_loss_list = []

    # initialise all the TF variables
    init_op = tf.global_variables_initializer()
    sess.run(init_op)

    # propensity for train
    propensity = propensity[train[:, 1].astype(np.int)]
    # positive and unlabeled data for training set
    pos_train = train[train[:, 2] == 1]
    prop_pos_train = propensity[train[:, 2] == 1]
    num_pos = np.sum(train[:, 2])
    unlabeled_train = train[train[:, 2] == 0]
    prop_unlabeled_train = propensity[train[:, 2] == 0]
    num_unlabeled = np.sum(1 - train[:, 2])
    # train the given implicit recommender
    np.random.seed(12345)
    for i in np.arange(max_iters):
        # positive mini-batch sampling
        # the same num. of postive and negative samples are used in each batch
        # for the pointwise training
        pos_idx = np.random.choice(np.arange(num_pos, dtype=int),
                                   size=np.int(batch_size / 2))
        unlabeled_idx = np.random.choice(np.arange(num_unlabeled, dtype=int),
                                         size=np.int(batch_size / 2))
        # mini-batch samples
        train_batch = np.r_[pos_train[pos_idx], unlabeled_train[unlabeled_idx]]
        train_label = train_batch[:, 2]
        # define propensity score
        prop_ = np.r_[prop_pos_train[pos_idx],
                      prop_unlabeled_train[unlabeled_idx]]
        train_score = np.expand_dims(prop_, 1)

        # update user-item latent factors and calculate training loss
        _, loss = sess.run(
            [model.apply_grads, model.weighted_mse],
            feed_dict={
                model.users: train_batch[:, 0],
                model.items: train_batch[:, 1],
                model.labels: np.expand_dims(train_label, 1),
                model.scores: train_score
            })
        train_loss_list.append(loss)

    # save embeddings.
    u_emb, i_emb = sess.run([model.user_embeddings, model.item_embeddings])
    np.save(file=f'../logs/{model_name}/embeds/user_embed.npy', arr=u_emb)
    np.save(file=f'../logs/{model_name}/embeds/item_embed.npy', arr=i_emb)
    # save train and val loss curves.
    np.save(file=f'../logs/{model_name}/loss/train.npy',
            arr=np.array(train_loss_list))

    sess.close()
Ejemplo n.º 5
0
                                        blocksize]  #.astype(precision)
                                    t = time()
                                    noisy[0, :-blocksize,
                                          0] = noisy[0, blocksize:, 0]
                                    noisy[0, -blocksize:, 0] = data
                                    clean = G_loaded.predict(noisy)
                                    data = overlap * (
                                        cleanb +
                                        clean[0, buffer_blocksize -
                                              blocksize:buffer_blocksize, 0])
                                    cleanb = clean[0, buffer_blocksize:, 0]
                                    t_total1 += time() - t
                                mean_time = t_total1 / ie
                                t_total += mean_time
                            mean_time = 1000 * t_total / args.iterations
                print('Average processing time: %f ms' % mean_time)
                if save_flag:
                    f = open('processing_times_' + frontend + '.txt', 'a')
                    f.write('Buffersize = ' + str(buffersize) + '\n')
                    f.write('Overlap = ' + str(overlap) + '\n')
                    f.write(str(mean_time) + '\n')
                    f.close()

                if frontend == 'tensorflow':
                    sess.close()
                    tf.reset_default_graph()
                else:
                    clear_session()
                command = 'killall jackd'
                check_call(command.split())
Ejemplo n.º 6
0
 def _close_session(self, session: tf.Session):
     session.probe_stream.close()
     session.close()
Ejemplo n.º 7
0
def train_mfips_with_at(sess: tf.Session, model: MFIPS, mfips1: MFIPS, mfips2: MFIPS, data: str,
                        train: np.ndarray, val: np.ndarray, test: np.ndarray,
                        epsilon: float, pre_iters: int = 500, post_iters: int = 50, post_steps: int = 5,
                        batch_size: int = 2**9, model_name: str = 'naive-at', seed: int = 0) -> Tuple:
    """Train and evaluate the MF-IPS model with asymmetric tri-training."""
    train_loss_list = []
    val_loss_list = []
    test_mse_list = []
    test_mae_list = []

    # initialise all the TF variables
    init_op = tf.global_variables_initializer()
    sess.run(init_op)

    # count the num of training data and estimate the propensity scores.
    num_train = train.shape[0]
    train_mcar, test = train_test_split(test, test_size=0.95, random_state=12345)
    pscore_train, pscore_val = estimate_pscore(train=train, train_mcar=train_mcar,
                                               val=val, model_name=model_name)
    labels_train = np.expand_dims(train[:, 2], 1)
    labels_val = np.expand_dims(val[:, 2], 1)
    labels_test = np.expand_dims(test[:, 2], 1)
    pscore_model = np.ones((batch_size, 1))

    # start training a recommender
    np.random.seed(12345)
    # start pre-training step
    for i in np.arange(pre_iters):
        # mini-batch sampling
        idx = np.random.choice(np.arange(num_train), size=batch_size)
        idx1 = np.random.choice(np.arange(num_train), size=batch_size)
        idx2 = np.random.choice(np.arange(num_train), size=batch_size)
        train_batch, train_batch1, train_batch2 = train[idx], train[idx1], train[idx2]
        labels_batch, labels_batch1, labels_batch2 = labels_train[idx], labels_train[idx1], labels_train[idx2]
        pscore_batch1, pscore_batch2 = pscore_train[idx1], pscore_train[idx2]
        # update user-item latent factors
        _, train_loss = sess.run([model.apply_grads, model.loss],
                                 feed_dict={model.users: train_batch[:, 0], model.items: train_batch[:, 1],
                                            model.labels: labels_batch, model.scores: pscore_model})
        _ = sess.run(mfips1.apply_grads,
                     feed_dict={mfips1.users: train_batch1[:, 0], mfips1.items: train_batch1[:, 1],
                                mfips1.labels: labels_batch1, mfips1.scores: pscore_batch1})
        _ = sess.run(mfips2.apply_grads,
                     feed_dict={mfips2.users: train_batch2[:, 0], mfips2.items: train_batch2[:, 1],
                                mfips2.labels: labels_batch2, mfips2.scores: pscore_batch2})
    # start psuedo-labeling and final prediction steps
    all_data = pd.DataFrame(np.zeros((train[:, 0].max() + 1, train[:, 1].max() + 1)))
    all_data = all_data.stack().reset_index().values[:, :2]
    for k in np.arange(post_iters):
        for j in np.arange(post_steps):
            idx = np.random.choice(np.arange(all_data.shape[0]), size=num_train * 5)
            batch_data = all_data[idx]
            # create psuedo-labeled dataset (i.e., \tilde{\mathcal{D}})
            preds1, preds2 = sess.run([mfips1.preds, mfips2.preds],
                                      feed_dict={mfips1.users: batch_data[:, 0],
                                                 mfips1.items: batch_data[:, 1],
                                                 mfips2.users: batch_data[:, 0],
                                                 mfips2.items: batch_data[:, 1]})
            idx = np.array(np.abs(preds1 - preds2) <= epsilon).flatten()
            target_users, target_items, pseudo_labels = batch_data[idx, 0], batch_data[idx, 1], preds1[idx]
            target_data = np.c_[target_users, target_items, pseudo_labels]
            # store information during the pseudo-labeleing step
            num_target = target_data.shape[0]
            # mini-batch sampling for the pseudo-labeleing step
            idx = np.random.choice(np.arange(num_target), size=batch_size)
            idx1 = np.random.choice(np.arange(num_target), size=batch_size)
            idx2 = np.random.choice(np.arange(num_target), size=batch_size)
            train_batch, train_batch1, train_batch2 = target_data[idx], target_data[idx1], target_data[idx2]
            # update user-item latent factors of the final prediction model
            _, train_loss = sess.run([model.apply_grads, model.mse],
                                     feed_dict={model.users: train_batch[:, 0],
                                                model.items: train_batch[:, 1],
                                                model.labels: np.expand_dims(train_batch[:, 2], 1),
                                                model.scores: np.ones((np.int(batch_size), 1))})
            # calculate validation loss during the psuedo-labeleing step
            val_loss = sess.run(model.weighted_mse,
                                feed_dict={model.users: val[:, 0],
                                           model.items: val[:, 1],
                                           model.scores: pscore_val,
                                           model.labels: labels_val})
            # calculate test losses during the psuedo-labeleing step
            mse_score, mae_score = sess.run([model.mse, model.mae],
                                            feed_dict={model.users: test[:, 0], model.items: test[:, 1],
                                                       model.labels: labels_test})
            train_loss_list.append(train_loss)
            val_loss_list.append(val_loss)
            test_mse_list.append(mse_score)
            test_mae_list.append(mae_score)
            # re-update the model parameters of pre-trained models using pseudo-labeled data
            _ = sess.run(mfips1.apply_grads,
                         feed_dict={mfips1.users: train_batch1[:, 0],
                                    mfips1.items: train_batch1[:, 1],
                                    mfips1.labels: np.expand_dims(train_batch1[:, 2], 1),
                                    mfips1.scores: np.ones((batch_size, 1))})
            _ = sess.run(mfips2.apply_grads,
                         feed_dict={mfips2.users: train_batch2[:, 0],
                                    mfips2.items: train_batch2[:, 1],
                                    mfips2.labels: np.expand_dims(train_batch2[:, 2], 1),
                                    mfips2.scores: np.ones((batch_size, 1))})

    # obtain user-item embeddings
    u_emb, i_emb, i_bias = sess.run([model.user_embeddings, model.item_embeddings, model.item_bias])

    sess.close()

    return (np.min(val_loss_list),
            test_mse_list[np.argmin(val_loss_list)],
            test_mae_list[np.argmin(val_loss_list)],
            u_emb, i_emb, i_bias)
Ejemplo n.º 8
0
def pointwise_trainer(sess: tf.Session,
                      model: PointwiseRecommender,
                      train: np.ndarray,
                      test: np.ndarray,
                      pscore: np.ndarray,
                      max_iters: int = 1000,
                      batch_size: int = 2**12,
                      model_name: str = 'rmf') -> None:
    """Train and Evaluate Implicit Recommender."""
    train_loss_list = []
    test_dcg_list = []
    test_map_list = []
    test_recall_list = []

    embed_path = Path(f'../logs/{model_name}/embeds/')
    embed_path.mkdir(parents=True, exist_ok=True)
    loss_path = Path(f'../logs/{model_name}/loss/')
    loss_path.mkdir(parents=True, exist_ok=True)
    ret_path = Path(f'../logs/{model_name}/results/')
    ret_path.mkdir(parents=True, exist_ok=True)

    # initialise all the TF variables
    init_op = tf.global_variables_initializer()
    sess.run(init_op)

    # specify model type
    ips = 'rmf' in model_name
    # all positive data
    pos_data = np.r_[train[train[:, 2] == 1], test[test[:, 2] == 1]]
    # pscore for train
    pscore = pscore[train[:, 1].astype(np.int)]
    # positive and unlabeled data for training set
    pos_train = train[train[:, 2] == 1]
    pscore_pos_train = pscore[train[:, 2] == 1]
    num_pos = np.sum(train[:, 2])
    unlabeled_train = train[train[:, 2] == 0]
    pscore_unlabeled_train = pscore[train[:, 2] == 0]
    num_unlabeled = np.sum(1 - train[:, 2])
    # train the given implicit recommender
    np.random.seed(12345)
    for i in np.arange(max_iters):
        # positive mini-batch sampling
        # the same num. of postive and negative samples are used in each batch
        pos_idx = np.random.choice(np.arange(num_pos),
                                   size=np.int(batch_size / 2))
        unlabeled_idx = np.random.choice(np.arange(num_unlabeled),
                                         size=np.int(batch_size / 2))
        # mini-batch samples
        train_batch = np.r_[pos_train[pos_idx], unlabeled_train[unlabeled_idx]]
        train_label = train_batch[:, 2]
        # define pscore score
        pscore_ = np.r_[pscore_pos_train[pos_idx],
                        pscore_unlabeled_train[unlabeled_idx]]
        train_score = pscore_ if ips else np.ones(batch_size)

        # update user-item latent factors and calculate training loss
        _, loss = sess.run(
            [model.apply_grads, model.weighted_mse],
            feed_dict={
                model.users: train_batch[:, 0],
                model.items: train_batch[:, 1],
                model.labels: np.expand_dims(train_label, 1),
                model.scores: np.expand_dims(train_score, 1)
            })
        train_loss_list.append(loss)
        # calculate ranking metrics
        if i % 25 == 0:
            u_emb, i_emb = sess.run(
                [model.user_embeddings, model.item_embeddings])
            np.save(file=str(embed_path / 'user_embed.npy'), arr=u_emb)
            np.save(file=str(embed_path / 'item_embed.npy'), arr=i_emb)
            evaluator = AverageOverAllEvaluator(test=test,
                                                pos_data=pos_data,
                                                model_name=model_name,
                                                save=True)
            evaluator.evaluate(k=[5], rare='all')
            ret = pd.read_csv(str(ret_path / 'aoa_all.csv'), index_col=0)
            test_dcg_list.append(ret.loc['DCG@5', model_name])
            test_map_list.append(ret.loc['MAP@5', model_name])
            test_recall_list.append(ret.loc['Recall@5', model_name])

    # save embeddings.
    u_emb, i_emb = sess.run([model.user_embeddings, model.item_embeddings])
    np.save(file=str(embed_path / 'user_embed.npy'), arr=u_emb)
    np.save(file=str(embed_path / 'item_embed.npy'), arr=i_emb)
    # save train and val loss curves.
    np.save(file=str(loss_path / 'train.npy'), arr=train_loss_list)
    np.save(file=str(loss_path / 'dcg.npy'), arr=test_dcg_list)
    np.save(file=str(loss_path / 'recall.npy'), arr=test_recall_list)
    np.save(file=str(loss_path / 'map.npy'), arr=test_map_list)

    # close the session.
    sess.close()
Ejemplo n.º 9
0
class TfModel(NonAtomicOp):
    def __init__(self,
                 overlap=None,
                 aggregate=None,
                 tile_size=1024,
                 *args,
                 verbose=VERBOSE,
                 **kwargs):
        super().__init__(overlap=overlap,
                         aggregate=aggregate,
                         tile_size=tile_size,
                         *args,
                         verbose=verbose,
                         **kwargs)
        self.model = None

    def __call__(self, func):
        def wrapper(inputs,
                    model: str,
                    overlap=None,
                    gpu=True,
                    *args,
                    **kwargs):  # multi-input ops work with tuples of inputs
            model_dir = model
            model = Model(model_dir)
            overlap = self.overlap if overlap is None else overlap
            if overlap is None:
                overlap = model.padding
            if overlap is None:
                raise ValueError('Overlap must be defined for this operation.')
            if gpu is False or self.con.env.has_gpu:
                inputs, stat = pack_list(inputs)
                if model.is_tf1():
                    res = self._handle_tf1(model, model_dir, func, inputs,
                                           overlap, gpu, args, kwargs)
                elif model.is_tf2():
                    raise NotImplementedError('Tf2 not supported yet.')
                else:
                    raise ValueError('Unknown framework')
                res = unpack_list(res, stat)
            else:
                res = None
            return res

        return wrapper

    def _handle_tf1(self, model, model_dir, func, inputs, overlap, gpu, args,
                    kwargs):
        self._start_tf1(model.directory, gpu)
        kwargs.update({
            "model": model_dir,
            "_session": self.session,
            "_input_tensor": model.inputs_str,
            "_output_tensor": model.outputs_str,
            "_preprocessing": model.preprocessing,
        })
        res = self.con(callback=func,
                       i_objects=inputs,
                       overlap=overlap,
                       args=args,
                       kwargs=kwargs,
                       aggregate=self.aggregate,
                       tile_size=self.tile_size,
                       gpu=gpu)
        if self.con.has_gpu:
            self._stop_tf1()
        return res

    def _start_tf1(self, checkpoint, gpu):
        try:
            from tensorflow import Session, saved_model, ConfigProto
            config = ConfigProto()
            config.gpu_options.allow_growth = True
            if gpu is False or self.con.has_gpu is False:
                config.gpu_options.visible_device_list = ''
            else:
                config.gpu_options.visible_device_list = str(
                    self.con.local_gpu_rank)
            print(
                f"Node {self.con.node_rank} rank {self.con.rank_gpu} starts session with GPU-ID:",
                config.gpu_options.visible_device_list)
        except ModuleNotFoundError:
            raise ModuleNotFoundError('Could not import from TensorFlow 1.X')

        self.session = Session(config=config)
        saved_model.loader.load(self.session, ['serve'], checkpoint)

    def _stop_tf1(self):
        if self.session is not None:
            self.session.close()
            self.session = None
Ejemplo n.º 10
0
def train_pointwise(sess: tf.Session, model: PointwiseRecommender, data: str,
                    train: np.ndarray, val: np.ndarray, test: np.ndarray, pscore: np.ndarray,
                    max_iters: int = 1000, batch_size: int = 256,
                    model_name: str = 'wmf', is_optuna: bool = False) -> Tuple:
    """Train and evaluate implicit recommender."""
    train_loss_list = []
    test_loss_list = []

    # initialise all the TF variables
    init_op = tf.global_variables_initializer()
    sess.run(init_op)

    ips = model_name == 'relmf'
    # pscore for train
    pscore = pscore[train[:, 1].astype(int)]
    # positive and unlabeled data for training set
    pos_train = train[train[:, 2] == 1]
    pscore_pos_train = pscore[train[:, 2] == 1]
    num_pos = np.sum(train[:, 2])
    unlabeled_train = train[train[:, 2] == 0]
    pscore_unlabeled_train = pscore[train[:, 2] == 0]
    num_unlabeled = np.sum(1 - train[:, 2])
    # train the given implicit recommender
    np.random.seed(12345)
    for i in np.arange(max_iters):
        # positive mini-batch sampling
        # the same num. of postive and negative samples are used in each batch
        sample_size = np.int(batch_size / 2)
        pos_idx = np.random.choice(np.arange(num_pos), size=sample_size)
        unl_idx = np.random.choice(np.arange(num_unlabeled), size=sample_size)
        # mini-batch samples
        train_batch = np.r_[pos_train[pos_idx], unlabeled_train[unl_idx]]
        pscore_ = np.r_[pscore_pos_train[pos_idx], pscore_unlabeled_train[unl_idx]] if ips else np.ones(batch_size)
        # update user-item latent factors and calculate training loss
        _, train_loss = sess.run([model.apply_grads, model.unbiased_loss],
                                 feed_dict={model.users: train_batch[:, 0],
                                            model.items: train_batch[:, 1],
                                            model.labels: np.expand_dims(train_batch[:, 2], 1),
                                            model.scores: np.expand_dims(pscore_, 1)})
        train_loss_list.append(train_loss)
    # calculate a validation score
    unl_idx = np.random.choice(np.arange(num_unlabeled), size=val.shape[0])
    val_batch = np.r_[val, unlabeled_train[unl_idx]]
    pscore_ = np.r_[pscore[val[:, 1].astype(int)], pscore_unlabeled_train[unl_idx]]
    val_loss = sess.run(model.unbiased_loss,
                        feed_dict={model.users: val_batch[:, 0],
                                   model.items: val_batch[:, 1],
                                   model.labels: np.expand_dims(val_batch[:, 2], 1),
                                   model.scores: np.expand_dims(pscore_, 1)})

    u_emb, i_emb = sess.run([model.user_embeddings, model.item_embeddings])
    if ~is_optuna:
        path = Path(f'../logs/{data}/{model_name}')
        (path / 'loss').mkdir(parents=True, exist_ok=True)
        np.save(file=str(path / 'loss/train.npy'), arr=train_loss_list)
        np.save(file=str(path / 'loss/test.npy'), arr=test_loss_list)
        (path / 'emb').mkdir(parents=True, exist_ok=True)
        np.save(file=str(path / 'emb/user_embed.npy'), arr=u_emb)
        np.save(file=str(path / 'emb/item_embed.npy'), arr=i_emb)
    sess.close()

    return u_emb, i_emb, val_loss
Ejemplo n.º 11
0
def train_pairwise(sess: tf.Session, model: PairwiseRecommender, data: str,
                   train: np.ndarray, val: np.ndarray, test: np.ndarray,
                   max_iters: int = 1000, batch_size: int = 1024,
                   model_name: str = 'bpr', is_optuna: bool = False) -> Tuple:
    """Train and evaluate pairwise recommenders."""
    train_loss_list = []
    test_loss_list = []

    # initialise all the TF variables
    init_op = tf.global_variables_initializer()
    sess.run(init_op)

    # count the num of training data.
    num_train, num_val = train.shape[0], val.shape[0]
    np.random.seed(12345)
    for i in np.arange(max_iters):
        idx = np.random.choice(np.arange(num_train), size=batch_size)
        train_batch = train[idx]
        # update user-item latent factors
        if model_name in 'bpr':
            _, loss = sess.run([model.apply_grads, model.loss],
                               feed_dict={model.users: train_batch[:, 0],
                                          model.pos_items: train_batch[:, 1],
                                          model.scores1: np.ones((batch_size, 1)),
                                          model.items2: train_batch[:, 2],
                                          model.labels2: np.zeros((batch_size, 1)),
                                          model.scores2: np.ones((batch_size, 1))})
        elif 'ubpr' in model_name:
            _, loss = sess.run([model.apply_grads, model.loss],
                               feed_dict={model.users: train_batch[:, 0],
                                          model.pos_items: train_batch[:, 1],
                                          model.scores1: np.expand_dims(train_batch[:, 4], 1),
                                          model.items2: train_batch[:, 2],
                                          model.labels2: np.expand_dims(train_batch[:, 3], 1),
                                          model.scores2: np.expand_dims(train_batch[:, 5], 1)})
        train_loss_list.append(loss)
        # calculate a test loss
        test_loss = sess.run(model.ideal_loss,
                             feed_dict={model.users: test[:, 0],
                                        model.pos_items: test[:, 1],
                                        model.rel1: np.expand_dims(test[:, 3], 1),
                                        model.items2: test[:, 2],
                                        model.rel2: np.expand_dims(test[:, 4], 1)})
        test_loss_list.append(test_loss)
    # calculate a validation loss
    if model_name in 'bpr':
        val_loss = sess.run(model.unbiased_loss,
                            feed_dict={model.users: val[:, 0],
                                       model.pos_items: val[:, 1],
                                       model.scores1: np.ones((num_val, 1)),
                                       model.items2: val[:, 2],
                                       model.labels2: np.zeros((num_val, 1)),
                                       model.scores2: np.ones((num_val, 1))})
    elif 'ubpr' in model_name:
        val_loss = sess.run(model.unbiased_loss,
                            feed_dict={model.users: val[:, 0],
                                       model.pos_items: val[:, 1],
                                       model.scores1: np.expand_dims(val[:, 4], 1),
                                       model.items2: val[:, 2],
                                       model.labels2: np.expand_dims(val[:, 3], 1),
                                       model.scores2: np.expand_dims(val[:, 5], 1)})

    u_emb, i_emb = sess.run([model.user_embeddings, model.item_embeddings])
    if ~is_optuna:
        path = Path(f'../logs/{data}/{model_name}')
        (path / 'loss').mkdir(parents=True, exist_ok=True)
        np.save(file=str(path / 'loss/train.npy'), arr=train_loss_list)
        np.save(file=str(path / 'loss/test.npy'), arr=test_loss_list)
        (path / 'emb').mkdir(parents=True, exist_ok=True)
        np.save(file=str(path / 'emb/user_embed.npy'), arr=u_emb)
        np.save(file=str(path / 'emb/item_embed.npy'), arr=i_emb)
    sess.close()

    return u_emb, i_emb, val_loss
def pointwise_trainer(sess: tf.Session,
                      data: str,
                      model: PointwiseRecommender,
                      train: np.ndarray,
                      val: np.ndarray,
                      test: np.ndarray,
                      num_users,
                      num_items,
                      pscore: np.ndarray,
                      inv_pscore: np.ndarray,
                      item_freq: np.ndarray,
                      max_iters: int = 1000,
                      batch_size: int = 2**12,
                      model_name: str = 'rel-mf',
                      date_now: str = '1'):
    """Train and Evaluate Implicit Recommender."""
    train_loss_list = []
    test_dcg_list = []
    test_map_list = []
    test_recall_list = []

    # initialise all the TF variables
    init_op = tf.global_variables_initializer()
    sess.run(init_op)

    # pscore for train
    pscore = pscore[train[:, 1].astype(np.int)]

    # train the given implicit recommender
    max_score = 0
    er_stop_count = 0
    best_u_emb = []
    best_i_emb = []

    all_tr = np.arange(len(train))
    batch_size = batch_size
    early_stop = 5

    for i in np.arange(max_iters):
        np.random.RandomState(12345).shuffle(all_tr)
        batch_num = int(len(all_tr) / batch_size) + 1
        for b in range(batch_num):
            # mini-batch samples
            train_batch = train[all_tr[b * batch_size:(b + 1) * batch_size]]
            train_label = train_batch[:, 2]
            train_score = pscore[all_tr[b * batch_size:(b + 1) * batch_size]]
            train_inv_score = inv_pscore[train_batch[:, 1]]

            # update user-item latent factors and calculate training loss
            _, loss = sess.run(
                [model.apply_grads, model.mse],
                feed_dict={
                    model.users: train_batch[:, 0],
                    model.items: train_batch[:, 1],
                    model.labels: np.expand_dims(train_label, 1),
                    model.scores: np.expand_dims(train_score, 1),
                    model.inv_scores: np.expand_dims(train_inv_score, 1),
                    # model.scores_normalization: np.expand_dims(train_score, 1), ################
                    # model.inv_scores_normalization: np.expand_dims(train_inv_score, 1) ################
                })
        ############### evaluation
        if i % 1 == 0:
            print(i, ":  ", loss)

            u_emb, i_emb = sess.run(
                [model.user_embeddings, model.item_embeddings])

            # validation
            at_k = 3

            # We need an unbiased evaluation for validating
            val_ret = unbiased_evaluator(user_embed=u_emb,
                                         item_embed=i_emb,
                                         train=train,
                                         val=val,
                                         test=val,
                                         num_users=num_users,
                                         num_items=num_items,
                                         pscore=item_freq,
                                         model_name=model_name,
                                         at_k=[at_k],
                                         flag_test=False,
                                         flag_unbiased=True)

            dim = u_emb.shape[1]
            best_score = val_ret.loc[f'MAP@{at_k}', f'{model_name}_{dim}']

            if max_score < best_score:
                max_score = best_score
                print(f"best_val_MAP@{at_k}: ", max_score)
                er_stop_count = 0

                best_u_emb = u_emb
                best_i_emb = i_emb

            else:
                er_stop_count += 1
                if er_stop_count > early_stop:
                    print("stopped!")
                    break

    sess.close()
    return best_u_emb, best_i_emb