Ejemplo n.º 1
0
    def __init__(self, data_set, exp_settings, forward_only=False):
        """Create the model.
    
        Args:
            data_set: (Raw_data) The dataset used to build the input layer.
            exp_settings: (dictionary) The dictionary containing the model settings.
            forward_only: Set true to conduct prediction only, false to conduct training.
        """

        self.hparams = tf.contrib.training.HParams(
            propensity_estimator_type=
            'utils.propensity_estimator.RandomizedPropensityEstimator',
            propensity_estimator_json=
            './example/PropensityEstimator/randomized_pbm_0.1_1.0_4_1.0.json',  # the setting file for the predefined click models.
            learning_rate=0.05,  # Learning rate.
            max_gradient_norm=5.0,  # Clip gradients to this norm.
            loss_func=
            'click_weighted_softmax_cross_entropy',  # Select Loss function
            l2_loss=0.0,  # Set strength for L2 regularization.
            grad_strategy='ada',  # Select gradient strategy
        )
        print(exp_settings['learning_algorithm_hparams'])
        self.hparams.parse(exp_settings['learning_algorithm_hparams'])
        self.exp_settings = exp_settings
        self.propensity_estimator = utils.find_class(
            self.hparams.propensity_estimator_type)(
                self.hparams.propensity_estimator_json)

        self.max_candidate_num = exp_settings['max_candidate_num']
        self.feature_size = data_set.feature_size
        self.learning_rate = tf.Variable(float(self.hparams.learning_rate),
                                         trainable=False)
        self.global_step = tf.Variable(0, trainable=False)

        # Feeds for inputs.
        self.is_training = tf.placeholder(tf.bool, name="is_train")
        self.docid_inputs = []  # a list of top documents
        self.letor_features = tf.placeholder(
            tf.float32, shape=[None, self.feature_size],
            name="letor_features")  # the letor features for the documents
        self.labels = []  # the labels for the documents (e.g., clicks)
        for i in range(self.max_candidate_num):
            self.docid_inputs.append(
                tf.placeholder(tf.int64,
                               shape=[None],
                               name="docid_input{0}".format(i)))
            self.labels.append(
                tf.placeholder(tf.float32,
                               shape=[None],
                               name="label{0}".format(i)))
        self.PAD_embed = tf.zeros([1, self.feature_size], dtype=tf.float32)

        # Build model
        self.output = self.ranking_model(self.max_candidate_num,
                                         scope='ranking_model')
        reshaped_labels = tf.transpose(
            tf.convert_to_tensor(self.labels)
        )  # reshape from [max_candidate_num, ?] to [?, max_candidate_num]
        pad_removed_output = self.remove_padding_for_metric_eval(
            self.docid_inputs, self.output)
        for metric in self.exp_settings['metrics']:
            for topn in self.exp_settings['metrics_topn']:
                metric_value = utils.make_ranking_metric_fn(metric, topn)(
                    reshaped_labels, pad_removed_output, None)
                tf.summary.scalar('%s_%d' % (metric, topn),
                                  metric_value,
                                  collections=['eval'])

        # Gradients and SGD update operation for training the model.
        if not forward_only:
            # Training outputs and losses.
            self.rank_list_size = exp_settings['train_list_cutoff']
            train_output = self.ranking_model(self.rank_list_size,
                                              scope='ranking_model')
            train_labels = self.labels[:self.rank_list_size]
            self.propensity_weights = []
            for i in range(self.rank_list_size):
                self.propensity_weights.append(
                    tf.placeholder(tf.float32,
                                   shape=[None],
                                   name="propensity_weights{0}".format(i)))
                tf.summary.scalar('Propensity weights %d' % i,
                                  tf.reduce_max(self.propensity_weights[i]),
                                  collections=['train'])

            print('Loss Function is ' + self.hparams.loss_func)
            self.loss = None
            reshaped_train_labels = tf.transpose(
                tf.convert_to_tensor(train_labels)
            )  # reshape from [rank_list_size, ?] to [?, rank_list_size]
            reshaped_propensity = tf.transpose(
                tf.convert_to_tensor(self.propensity_weights)
            )  # reshape from [rank_list_size, ?] to [?, rank_list_size]
            if self.hparams.loss_func == 'softmax':
                self.loss = self.softmax_loss(train_output,
                                              reshaped_train_labels,
                                              reshaped_propensity)
            elif self.hparams.loss_func == 'click_weighted_softmax_cross_entropy':
                self.loss = self.click_weighted_softmax_loss(
                    train_output, reshaped_train_labels, reshaped_propensity)
            elif self.hparams.loss_func == 'click_weighted_pairwise_loss':
                self.loss = self.click_weighted_pairwise_loss(
                    train_output, reshaped_train_labels, reshaped_propensity)
            else:
                self.loss = self.sigmoid_loss(train_output,
                                              reshaped_train_labels,
                                              reshaped_propensity)

            params = tf.trainable_variables()
            if self.hparams.l2_loss > 0:
                for p in params:
                    self.loss += self.hparams.l2_loss * tf.nn.l2_loss(p)

            # Select optimizer
            self.optimizer_func = tf.train.AdagradOptimizer
            if self.hparams.grad_strategy == 'sgd':
                self.optimizer_func = tf.train.GradientDescentOptimizer

            opt = self.optimizer_func(self.hparams.learning_rate)
            self.gradients = tf.gradients(self.loss, params)
            if self.hparams.max_gradient_norm > 0:
                self.clipped_gradients, self.norm = tf.clip_by_global_norm(
                    self.gradients, self.hparams.max_gradient_norm)
                self.updates = opt.apply_gradients(
                    zip(self.clipped_gradients, params),
                    global_step=self.global_step)
            else:
                self.norm = None
                self.updates = opt.apply_gradients(
                    zip(self.gradients, params), global_step=self.global_step)
            tf.summary.scalar('Learning Rate',
                              self.learning_rate,
                              collections=['train'])
            tf.summary.scalar('Loss',
                              tf.reduce_mean(self.loss),
                              collections=['train'])

            clipped_labels = tf.clip_by_value(reshaped_train_labels,
                                              clip_value_min=0,
                                              clip_value_max=1)
            pad_removed_train_output = self.remove_padding_for_metric_eval(
                self.docid_inputs, train_output)
            for metric in self.exp_settings['metrics']:
                for topn in self.exp_settings['metrics_topn']:
                    list_weights = tf.reduce_mean(reshaped_propensity *
                                                  clipped_labels,
                                                  axis=1,
                                                  keep_dims=True)
                    metric_value = utils.make_ranking_metric_fn(metric, topn)(
                        reshaped_train_labels, pad_removed_train_output, None)
                    tf.summary.scalar('%s_%d' % (metric, topn),
                                      metric_value,
                                      collections=['train'])
                    weighted_metric_value = utils.make_ranking_metric_fn(
                        metric, topn)(reshaped_train_labels,
                                      pad_removed_train_output, list_weights)
                    tf.summary.scalar('Weighted_%s_%d' % (metric, topn),
                                      weighted_metric_value,
                                      collections=['train'])

        self.train_summary = tf.summary.merge_all(key='train')
        self.eval_summary = tf.summary.merge_all(key='eval')
        self.saver = tf.train.Saver(tf.global_variables())
Ejemplo n.º 2
0
Archivo: na.py Proyecto: kiminh/ULTRA
    def __init__(self, data_set, exp_settings, forward_only=False):
        """Create the model.
    
        Args:
            data_set: (Raw_data) The dataset used to build the input layer.
            exp_settings: (dictionary) The dictionary containing the model settings.
            forward_only: Set true to conduct prediction only, false to conduct training.
        """
        print('Build NavieAlgorithm')

        self.hparams = tf.contrib.training.HParams(
            learning_rate=0.05,  # Learning rate.
            max_gradient_norm=5.0,  # Clip gradients to this norm.
            loss_func='softmax_cross_entropy',  # Select Loss function
            l2_loss=0.0,  # Set strength for L2 regularization.
            grad_strategy='ada',  # Select gradient strategy
        )
        print(exp_settings['learning_algorithm_hparams'])
        self.hparams.parse(exp_settings['learning_algorithm_hparams'])
        self.exp_settings = exp_settings

        self.max_candidate_num = exp_settings['max_candidate_num']
        self.feature_size = data_set.feature_size
        self.learning_rate = tf.Variable(float(self.hparams.learning_rate),
                                         trainable=False)

        # Feeds for inputs.
        self.is_training = tf.placeholder(tf.bool, name="is_train")
        self.docid_inputs = []  # a list of top documents
        self.letor_features = tf.placeholder(
            tf.float32, shape=[None, self.feature_size],
            name="letor_features")  # the letor features for the documents
        self.labels = []  # the labels for the documents (e.g., clicks)
        for i in range(self.max_candidate_num):
            self.docid_inputs.append(
                tf.placeholder(tf.int64,
                               shape=[None],
                               name="docid_input{0}".format(i)))
            self.labels.append(
                tf.placeholder(tf.float32,
                               shape=[None],
                               name="label{0}".format(i)))

        self.global_step = tf.Variable(0, trainable=False)

        # Build model
        self.output = self.ranking_model(self.max_candidate_num,
                                         scope='ranking_model')

        reshaped_labels = tf.transpose(
            tf.convert_to_tensor(self.labels)
        )  # reshape from [max_candidate_num, ?] to [?, max_candidate_num]
        pad_removed_output = self.remove_padding_for_metric_eval(
            self.docid_inputs, self.output)
        for metric in self.exp_settings['metrics']:
            for topn in self.exp_settings['metrics_topn']:
                metric_value = utils.make_ranking_metric_fn(metric, topn)(
                    reshaped_labels, pad_removed_output, None)
                tf.summary.scalar('%s_%d' % (metric, topn),
                                  metric_value,
                                  collections=['eval'])

        if not forward_only:
            # Build model
            self.rank_list_size = exp_settings['train_list_cutoff']
            train_output = self.ranking_model(self.rank_list_size,
                                              scope='ranking_model')
            train_labels = self.labels[:self.rank_list_size]
            reshaped_train_labels = tf.transpose(
                tf.convert_to_tensor(train_labels)
            )  # reshape from [rank_list_size, ?] to [?, rank_list_size]

            self.loss = None
            if self.hparams.loss_func == 'sigmoid_cross_entropy':
                self.loss = self.sigmoid_loss(train_output,
                                              reshaped_train_labels)
            elif self.hparams.loss_func == 'pairwise_loss':
                self.loss = self.pairwise_loss(train_output,
                                               reshaped_train_labels)
            else:
                self.loss = self.softmax_loss(train_output,
                                              reshaped_train_labels)
            params = tf.trainable_variables()
            if self.hparams.l2_loss > 0:
                for p in params:
                    self.loss += self.hparams.l2_loss * tf.nn.l2_loss(p)

            # Select optimizer
            self.optimizer_func = tf.train.AdagradOptimizer
            if self.hparams.grad_strategy == 'sgd':
                self.optimizer_func = tf.train.GradientDescentOptimizer

            # Gradients and SGD update operation for training the model.
            opt = self.optimizer_func(self.hparams.learning_rate)
            self.gradients = tf.gradients(self.loss, params)
            if self.hparams.max_gradient_norm > 0:
                self.clipped_gradients, self.norm = tf.clip_by_global_norm(
                    self.gradients, self.hparams.max_gradient_norm)
                self.updates = opt.apply_gradients(
                    zip(self.clipped_gradients, params),
                    global_step=self.global_step)
                tf.summary.scalar('Gradient Norm',
                                  self.norm,
                                  collections=['train'])
            else:
                self.norm = None
                self.updates = opt.apply_gradients(
                    zip(self.gradients, params), global_step=self.global_step)
            tf.summary.scalar('Learning Rate',
                              self.learning_rate,
                              collections=['train'])
            tf.summary.scalar('Loss',
                              tf.reduce_mean(self.loss),
                              collections=['train'])
            pad_removed_train_output = self.remove_padding_for_metric_eval(
                self.docid_inputs, train_output)
            for metric in self.exp_settings['metrics']:
                for topn in self.exp_settings['metrics_topn']:
                    metric_value = utils.make_ranking_metric_fn(metric, topn)(
                        reshaped_train_labels, pad_removed_train_output, None)
                    tf.summary.scalar('%s_%d' % (metric, topn),
                                      metric_value,
                                      collections=['train'])

        self.train_summary = tf.summary.merge_all(key='train')
        self.eval_summary = tf.summary.merge_all(key='eval')
        self.saver = tf.train.Saver(tf.global_variables())
Ejemplo n.º 3
0
    def __init__(self, data_set, exp_settings, forward_only=False):
        """Create the model.
    
        Args:
            data_set: (Raw_data) The dataset used to build the input layer.
            exp_settings: (dictionary) The dictionary containing the model settings.
            forward_only: Set true to conduct prediction only, false to conduct training.
        """
        print('Build Regression-based EM algorithm.')

        self.hparams = tf.contrib.training.HParams(
            EM_step_size=0.05,  # Step size for EM algorithm.
            learning_rate=0.05,  # Learning rate.
            max_gradient_norm=5.0,  # Clip gradients to this norm.
            l2_loss=0.0,  # Set strength for L2 regularization.
            grad_strategy='ada',  # Select gradient strategy
        )
        print(exp_settings['learning_algorithm_hparams'])
        self.hparams.parse(exp_settings['learning_algorithm_hparams'])
        self.exp_settings = exp_settings

        self.max_candidate_num = exp_settings['max_candidate_num']
        self.feature_size = data_set.feature_size
        self.learning_rate = tf.Variable(float(self.hparams.learning_rate),
                                         trainable=False)

        # Feeds for inputs.
        self.is_training = tf.placeholder(tf.bool, name="is_train")
        self.docid_inputs = []  # a list of top documents
        self.letor_features = tf.placeholder(
            tf.float32, shape=[None, self.feature_size],
            name="letor_features")  # the letor features for the documents
        self.labels = []  # the labels for the documents (e.g., clicks)
        for i in range(self.max_candidate_num):
            self.docid_inputs.append(
                tf.placeholder(tf.int64,
                               shape=[None],
                               name="docid_input{0}".format(i)))
            self.labels.append(
                tf.placeholder(tf.float32,
                               shape=[None],
                               name="label{0}".format(i)))

        self.global_step = tf.Variable(0, trainable=False)

        # Build model
        self.output = self.ranking_model(self.max_candidate_num,
                                         scope='ranking_model')

        reshaped_labels = tf.transpose(
            tf.convert_to_tensor(self.labels)
        )  # reshape from [max_candidate_num, ?] to [?, max_candidate_num]
        pad_removed_output = self.remove_padding_for_metric_eval(
            self.docid_inputs, self.output)
        for metric in self.exp_settings['metrics']:
            for topn in self.exp_settings['metrics_topn']:
                metric_value = utils.make_ranking_metric_fn(metric, topn)(
                    reshaped_labels, pad_removed_output, None)
                tf.summary.scalar('%s_%d' % (metric, topn),
                                  metric_value,
                                  collections=['eval'])

        if not forward_only:
            # Build EM graph only when it is training
            self.rank_list_size = exp_settings['train_list_cutoff']
            sigmoid_prob_b = tf.Variable(tf.ones([1]) - 1.0)
            train_output = self.ranking_model(self.rank_list_size,
                                              scope='ranking_model')
            train_output = train_output + sigmoid_prob_b
            train_labels = self.labels[:self.rank_list_size]
            self.propensity = tf.Variable(tf.ones([1, self.rank_list_size]) *
                                          0.9,
                                          trainable=False)

            self.splitted_propensity = tf.split(self.propensity,
                                                self.rank_list_size,
                                                axis=1)
            for i in range(self.rank_list_size):
                tf.summary.scalar('Examination Probability %d' % i,
                                  tf.reduce_max(self.splitted_propensity[i]),
                                  collections=['train'])

            # Conduct estimation step.
            gamma = tf.sigmoid(train_output)
            reshaped_train_labels = tf.transpose(
                tf.convert_to_tensor(train_labels)
            )  # reshape from [rank_list_size, ?] to [?, rank_list_size]
            p_e1_r1_c1 = 1
            p_e1_r0_c0 = self.propensity * (1 - gamma) / (
                1 - self.propensity * gamma)
            p_e0_r1_c0 = (1 - self.propensity) * gamma / (
                1 - self.propensity * gamma)
            p_e0_r0_c0 = (1 - self.propensity) * (1 - gamma) / (
                1 - self.propensity * gamma)
            p_e1 = p_e1_r0_c0 + p_e1_r1_c1
            p_r1 = reshaped_train_labels + (1 -
                                            reshaped_train_labels) * p_e0_r1_c0

            # Conduct maximization step
            self.update_propensity_op = self.propensity.assign(
                (1 - self.hparams.EM_step_size) * self.propensity +
                self.hparams.EM_step_size *
                tf.reduce_mean(reshaped_train_labels +
                               (1 - reshaped_train_labels) * p_e1_r0_c0,
                               axis=0,
                               keep_dims=True)  #
            )

            # Get Bernoulli samples and compute rank loss
            self.ranker_labels = get_bernoulli_sample(p_r1)
            self.loss = tf.reduce_mean(
                tf.reduce_sum(tf.nn.sigmoid_cross_entropy_with_logits(
                    labels=self.ranker_labels, logits=train_output),
                              axis=1))
            # record additional positive instance from sampling
            split_ranker_labels = tf.split(self.ranker_labels,
                                           self.rank_list_size,
                                           axis=1)
            for i in range(self.rank_list_size):
                additional_postive_instance = (
                    tf.reduce_sum(split_ranker_labels[i]) -
                    tf.reduce_sum(train_labels[i])) / (
                        tf.reduce_sum(tf.ones_like(train_labels[i])) -
                        tf.reduce_sum(train_labels[i]))
                tf.summary.scalar('Additional pseudo clicks %d' % i,
                                  additional_postive_instance,
                                  collections=['train'])

            self.propensity_weights = 1.0 / self.propensity
            params = tf.trainable_variables()
            if self.hparams.l2_loss > 0:
                for p in params:
                    self.loss += self.hparams.l2_loss * tf.nn.l2_loss(p)

            # Select optimizer
            self.optimizer_func = tf.train.AdagradOptimizer
            if self.hparams.grad_strategy == 'sgd':
                self.optimizer_func = tf.train.GradientDescentOptimizer

            # Gradients and SGD update operation for training the model.
            opt = self.optimizer_func(self.hparams.learning_rate)
            self.gradients = tf.gradients(self.loss, params)
            if self.hparams.max_gradient_norm > 0:
                self.clipped_gradients, self.norm = tf.clip_by_global_norm(
                    self.gradients, self.hparams.max_gradient_norm)
                self.updates = opt.apply_gradients(
                    zip(self.clipped_gradients, params),
                    global_step=self.global_step)
                tf.summary.scalar('Gradient Norm',
                                  self.norm,
                                  collections=['train'])
            else:
                self.norm = None
                self.updates = opt.apply_gradients(
                    zip(self.gradients, params), global_step=self.global_step)
            tf.summary.scalar('Learning Rate',
                              self.learning_rate,
                              collections=['train'])
            tf.summary.scalar('Loss',
                              tf.reduce_mean(self.loss),
                              collections=['train'])
            clipped_labels = tf.clip_by_value(reshaped_train_labels,
                                              clip_value_min=0,
                                              clip_value_max=1)
            pad_removed_train_output = self.remove_padding_for_metric_eval(
                self.docid_inputs, train_output)
            for metric in self.exp_settings['metrics']:
                for topn in self.exp_settings['metrics_topn']:
                    list_weights = tf.reduce_mean(self.propensity_weights *
                                                  clipped_labels,
                                                  axis=1,
                                                  keep_dims=True)
                    metric_value = utils.make_ranking_metric_fn(metric, topn)(
                        reshaped_train_labels, pad_removed_train_output, None)
                    tf.summary.scalar('%s_%d' % (metric, topn),
                                      metric_value,
                                      collections=['train'])
                    weighted_metric_value = utils.make_ranking_metric_fn(
                        metric, topn)(reshaped_train_labels,
                                      pad_removed_train_output, list_weights)
                    tf.summary.scalar('Weighted_%s_%d' % (metric, topn),
                                      weighted_metric_value,
                                      collections=['train'])

        self.train_summary = tf.summary.merge_all(key='train')
        self.eval_summary = tf.summary.merge_all(key='eval')
        self.saver = tf.train.Saver(tf.global_variables())
Ejemplo n.º 4
0
    def __init__(self, data_set, exp_settings, forward_only=False):
        """Create the model.
    
        Args:
            data_set: (Raw_data) The dataset used to build the input layer.
            exp_settings: (dictionary) The dictionary containing the model settings.
            forward_only: Set true to conduct prediction only, false to conduct training.
        """
        print('Build Dueling Bandit Gradient Descent (DBGD) algorithm.')

        self.hparams = tf.contrib.training.HParams(
            noise_rate=0.5,  # The update rate for randomly sampled weights.
            learning_rate=0.01,  # Learning rate.
            max_gradient_norm=5.0,  # Clip gradients to this norm.
            l2_loss=0.01,  # Set strength for L2 regularization.
            grad_strategy='ada',  # Select gradient strategy
        )
        print(exp_settings['learning_algorithm_hparams'])
        self.hparams.parse(exp_settings['learning_algorithm_hparams'])
        self.exp_settings = exp_settings

        self.max_candidate_num = exp_settings['max_candidate_num']
        self.feature_size = data_set.feature_size
        self.learning_rate = tf.Variable(float(self.hparams.learning_rate),
                                         trainable=False)

        # Feeds for inputs.
        self.is_training = tf.placeholder(tf.bool, name="is_train")
        self.docid_inputs = []  # a list of top documents
        self.letor_features = tf.placeholder(
            tf.float32, shape=[None, self.feature_size],
            name="letor_features")  # the letor features for the documents
        self.labels = []  # the labels for the documents (e.g., clicks)
        for i in range(self.max_candidate_num):
            self.docid_inputs.append(
                tf.placeholder(tf.int64,
                               shape=[None],
                               name="docid_input{0}".format(i)))
            self.labels.append(
                tf.placeholder(tf.float32,
                               shape=[None],
                               name="label{0}".format(i)))

        self.global_step = tf.Variable(0, trainable=False)
        self.output = tf.concat(
            self.get_ranking_scores(self.docid_inputs,
                                    is_training=self.is_training,
                                    scope='ranking_model'), 1)
        reshaped_labels = tf.transpose(
            tf.convert_to_tensor(self.labels)
        )  # reshape from [max_candidate_num, ?] to [?, max_candidate_num]
        pad_removed_output = self.remove_padding_for_metric_eval(
            self.docid_inputs, self.output)
        for metric in self.exp_settings['metrics']:
            for topn in self.exp_settings['metrics_topn']:
                metric_value = utils.make_ranking_metric_fn(metric, topn)(
                    reshaped_labels, pad_removed_output, None)
                tf.summary.scalar('%s_%d' % (metric, topn),
                                  metric_value,
                                  collections=['eval'])

        # Build model
        if not forward_only:
            self.rank_list_size = exp_settings['train_list_cutoff']
            train_output = tf.concat(
                self.get_ranking_scores(
                    self.docid_inputs[:self.rank_list_size],
                    is_training=self.is_training,
                    scope='ranking_model'), 1)
            train_labels = self.labels[:self.rank_list_size]
            # Create random gradients and apply it to get new ranking scores
            new_output_list, noise_list = self.get_ranking_scores_with_noise(
                self.docid_inputs[:self.rank_list_size],
                is_training=self.is_training,
                scope='ranking_model')

            # Compute NDCG for the old ranking scores and new ranking scores
            reshaped_train_labels = tf.transpose(
                tf.convert_to_tensor(train_labels)
            )  # reshape from [rank_list_size, ?] to [?, rank_list_size]
            self.new_output = tf.concat(new_output_list, 1)
            previous_ndcg = utils.make_ranking_metric_fn(
                'ndcg', self.rank_list_size)(reshaped_train_labels,
                                             train_output, None)
            new_ndcg = utils.make_ranking_metric_fn(
                'ndcg', self.rank_list_size)(reshaped_train_labels,
                                             self.new_output, None)
            update_or_not = tf.ceil(new_ndcg - previous_ndcg)
            self.loss = 1.0 - new_ndcg

            # Compute gradients
            params = [p[1] for p in noise_list]
            self.gradients = [p[0] * update_or_not for p in noise_list]

            # Select optimizer
            self.optimizer_func = tf.train.AdagradOptimizer
            if self.hparams.grad_strategy == 'sgd':
                self.optimizer_func = tf.train.GradientDescentOptimizer

            # Gradients and SGD update operation for training the model.
            opt = self.optimizer_func(self.hparams.learning_rate)
            if self.hparams.max_gradient_norm > 0:
                self.clipped_gradients, self.norm = tf.clip_by_global_norm(
                    self.gradients, self.hparams.max_gradient_norm)
                self.updates = opt.apply_gradients(
                    zip(self.clipped_gradients, params),
                    global_step=self.global_step)
                tf.summary.scalar('Gradient Norm',
                                  self.norm,
                                  collections=['train'])
            else:
                self.norm = None
                self.updates = opt.apply_gradients(
                    zip(update_or_not * self.gradients, params),
                    global_step=self.global_step)
            tf.summary.scalar('Learning Rate',
                              self.learning_rate,
                              collections=['train'])
            tf.summary.scalar('Loss', self.loss, collections=['train'])
            pad_removed_train_output = self.remove_padding_for_metric_eval(
                self.docid_inputs, train_output)
            for metric in self.exp_settings['metrics']:
                for topn in self.exp_settings['metrics_topn']:
                    metric_value = utils.make_ranking_metric_fn(metric, topn)(
                        reshaped_train_labels, pad_removed_train_output, None)
                    tf.summary.scalar('%s_%d' % (metric, topn),
                                      metric_value,
                                      collections=['train'])

        self.train_summary = tf.summary.merge_all(key='train')
        self.eval_summary = tf.summary.merge_all(key='eval')
        self.saver = tf.train.Saver(tf.global_variables())
Ejemplo n.º 5
0
    def __init__(self, data_set, exp_settings, forward_only=False):
        """Create the model.
    
        Args:
            data_set: (Raw_data) The dataset used to build the input layer.
            exp_settings: (dictionary) The dictionary containing the model settings.
            forward_only: Set true to conduct prediction only, false to conduct training.
        """
        print('Build DLA')

        self.hparams = tf.contrib.training.HParams(
            learning_rate=0.05,  # Learning rate.
            max_gradient_norm=5.0,  # Clip gradients to this norm.
            loss_func=
            'click_weighted_softmax_cross_entropy',  # Select Loss function
            logits_to_prob=
            'softmax',  # the function used to convert logits to probability distributions
            ranker_learning_rate=
            -1.0,  # The learning rate for ranker (-1 means same with learning_rate).
            ranker_loss_weight=1.0,  # Set the weight of unbiased ranking loss
            l2_loss=0.0,  # Set strength for L2 regularization.
            max_propensity_weight=-1,  # Set maximum value for propensity weights
            constant_propensity_initialization=
            False,  # Set true to initialize propensity with constants.
            grad_strategy='ada',  # Select gradient strategy
        )
        print(exp_settings['learning_algorithm_hparams'])
        self.hparams.parse(exp_settings['learning_algorithm_hparams'])
        self.exp_settings = exp_settings

        self.max_candidate_num = exp_settings['max_candidate_num']
        self.feature_size = data_set.feature_size
        if self.hparams.ranker_learning_rate < 0:
            self.ranker_learning_rate = tf.Variable(float(
                self.hparams.learning_rate),
                                                    trainable=False)
        else:
            self.ranker_learning_rate = tf.Variable(float(
                self.hparams.ranker_learning_rate),
                                                    trainable=False)
        self.learning_rate = self.ranker_learning_rate

        # Feeds for inputs.
        self.is_training = tf.placeholder(tf.bool, name="is_train")
        self.docid_inputs = []  # a list of top documents
        self.letor_features = tf.placeholder(
            tf.float32, shape=[None, self.feature_size],
            name="letor_features")  # the letor features for the documents
        self.labels = []  # the labels for the documents (e.g., clicks)
        for i in range(self.max_candidate_num):
            self.docid_inputs.append(
                tf.placeholder(tf.int64,
                               shape=[None],
                               name="docid_input{0}".format(i)))
            self.labels.append(
                tf.placeholder(tf.float32,
                               shape=[None],
                               name="label{0}".format(i)))

        self.global_step = tf.Variable(0, trainable=False)

        # Select logits to prob function
        self.logits_to_prob = tf.nn.softmax
        if self.hparams.logits_to_prob == 'sigmoid':
            self.logits_to_prob = sigmoid_prob

        self.output = self.ranking_model(self.max_candidate_num,
                                         scope='ranking_model')
        pad_removed_output = self.remove_padding_for_metric_eval(
            self.docid_inputs, self.output)
        reshaped_labels = tf.transpose(
            tf.convert_to_tensor(self.labels)
        )  # reshape from [max_candidate_num, ?] to [?, max_candidate_num]
        for metric in self.exp_settings['metrics']:
            for topn in self.exp_settings['metrics_topn']:
                metric_value = utils.make_ranking_metric_fn(metric, topn)(
                    reshaped_labels, pad_removed_output, None)
                tf.summary.scalar('%s_%d' % (metric, topn),
                                  metric_value,
                                  collections=['eval'])

        if not forward_only:
            # Build model
            self.rank_list_size = exp_settings['train_list_cutoff']
            train_output = self.ranking_model(self.rank_list_size,
                                              scope='ranking_model')
            self.propensity = self.DenoisingNet(self.rank_list_size,
                                                forward_only)
            train_labels = self.labels[:self.rank_list_size]

            print('Loss Function is ' + self.hparams.loss_func)
            # Select loss function
            self.loss_func = None
            if self.hparams.loss_func == 'click_weighted_softmax_cross_entropy':
                self.loss_func = self.click_weighted_softmax_cross_entropy_loss
            elif self.hparams.loss_func == 'click_weighted_log_loss':
                self.loss_func = self.click_weighted_log_loss
            elif self.hparams.loss_func == 'click_weighted_pairwise_loss':
                self.loss_func = self.click_weighted_pairwise_loss
            else:  # softmax loss without weighting
                self.loss_func = self.softmax_loss

            # Compute rank loss
            reshaped_train_labels = tf.transpose(
                tf.convert_to_tensor(train_labels)
            )  # reshape from [rank_list_size, ?] to [?, rank_list_size]
            self.propensity_weights = self.get_normalized_weights(
                self.logits_to_prob(self.propensity))
            self.rank_loss = self.loss_func(train_output,
                                            reshaped_train_labels,
                                            self.propensity_weights)
            pw_list = tf.unstack(self.propensity_weights,
                                 axis=1)  # Compute propensity weights
            for i in range(len(pw_list)):
                tf.summary.scalar('Inverse Propensity weights %d' % i,
                                  tf.reduce_mean(pw_list[i]),
                                  collections=['train'])
            tf.summary.scalar('Rank Loss',
                              tf.reduce_mean(self.rank_loss),
                              collections=['train'])

            # Compute examination loss
            self.relevance_weights = self.get_normalized_weights(
                self.logits_to_prob(train_output))
            self.exam_loss = self.loss_func(self.propensity,
                                            reshaped_train_labels,
                                            self.relevance_weights)
            rw_list = tf.unstack(self.relevance_weights,
                                 axis=1)  # Compute propensity weights
            for i in range(len(rw_list)):
                tf.summary.scalar('Relevance weights %d' % i,
                                  tf.reduce_mean(rw_list[i]),
                                  collections=['train'])
            tf.summary.scalar('Exam Loss',
                              tf.reduce_mean(self.exam_loss),
                              collections=['train'])

            # Gradients and SGD update operation for training the model.
            self.loss = self.exam_loss + self.hparams.ranker_loss_weight * self.rank_loss

            # Select optimizer
            self.optimizer_func = tf.train.AdagradOptimizer
            if self.hparams.grad_strategy == 'sgd':
                self.optimizer_func = tf.train.GradientDescentOptimizer

            self.separate_gradient_update()

            tf.summary.scalar('Gradient Norm',
                              self.norm,
                              collections=['train'])
            tf.summary.scalar('Learning Rate',
                              self.ranker_learning_rate,
                              collections=['train'])
            tf.summary.scalar('Final Loss',
                              tf.reduce_mean(self.loss),
                              collections=['train'])

            clipped_labels = tf.clip_by_value(reshaped_train_labels,
                                              clip_value_min=0,
                                              clip_value_max=1)
            pad_removed_train_output = self.remove_padding_for_metric_eval(
                self.docid_inputs, train_output)
            for metric in self.exp_settings['metrics']:
                for topn in self.exp_settings['metrics_topn']:
                    list_weights = tf.reduce_mean(self.propensity_weights *
                                                  clipped_labels,
                                                  axis=1,
                                                  keep_dims=True)
                    metric_value = utils.make_ranking_metric_fn(metric, topn)(
                        reshaped_train_labels, pad_removed_train_output, None)
                    tf.summary.scalar('%s_%d' % (metric, topn),
                                      metric_value,
                                      collections=['train'])
                    weighted_metric_value = utils.make_ranking_metric_fn(
                        metric, topn)(reshaped_train_labels,
                                      pad_removed_train_output, list_weights)
                    tf.summary.scalar('Weighted_%s_%d' % (metric, topn),
                                      weighted_metric_value,
                                      collections=['train'])

        self.train_summary = tf.summary.merge_all(key='train')
        self.eval_summary = tf.summary.merge_all(key='eval')
        self.saver = tf.train.Saver(tf.global_variables())
Ejemplo n.º 6
0
    def __init__(self, data_set, exp_settings, forward_only=False):
        """Create the model.
    
        Args:
            data_set: (Raw_data) The dataset used to build the input layer.
            exp_settings: (dictionary) The dictionary containing the model settings.
            forward_only: Set true to conduct prediction only, false to conduct training.
        """
        print('Build Pairwise Debiasing algorithm.')

        self.hparams = tf.contrib.training.HParams(
            EM_step_size=0.05,  # Step size for EM algorithm.
            learning_rate=0.005,  # Learning rate.
            max_gradient_norm=5.0,  # Clip gradients to this norm.
            regulation_p=1,  # An int specify the regularization term.
            l2_loss=0.0,  # Set strength for L2 regularization.
            grad_strategy='ada',  # Select gradient strategy
        )
        print(exp_settings['learning_algorithm_hparams'])
        self.hparams.parse(exp_settings['learning_algorithm_hparams'])
        self.exp_settings = exp_settings

        self.max_candidate_num = exp_settings['max_candidate_num']
        self.feature_size = data_set.feature_size
        self.learning_rate = tf.Variable(float(self.hparams.learning_rate),
                                         trainable=False)

        # Feeds for inputs.
        self.is_training = tf.placeholder(tf.bool, name="is_train")
        self.docid_inputs = []  # a list of top documents
        self.letor_features = tf.placeholder(
            tf.float32, shape=[None, self.feature_size],
            name="letor_features")  # the letor features for the documents
        self.labels = []  # the labels for the documents (e.g., clicks)
        for i in range(self.max_candidate_num):
            self.docid_inputs.append(
                tf.placeholder(tf.int64,
                               shape=[None],
                               name="docid_input{0}".format(i)))
            self.labels.append(
                tf.placeholder(tf.float32,
                               shape=[None],
                               name="label{0}".format(i)))

        self.global_step = tf.Variable(0, trainable=False)

        self.output = self.ranking_model(self.max_candidate_num,
                                         scope='ranking_model')
        reshaped_labels = tf.transpose(
            tf.convert_to_tensor(self.labels)
        )  # reshape from [max_candidate_num, ?] to [?, max_candidate_num]
        pad_removed_output = self.remove_padding_for_metric_eval(
            self.docid_inputs, self.output)
        for metric in self.exp_settings['metrics']:
            for topn in self.exp_settings['metrics_topn']:
                metric_value = utils.make_ranking_metric_fn(metric, topn)(
                    reshaped_labels, pad_removed_output, None)
                tf.summary.scalar('%s_%d' % (metric, topn),
                                  metric_value,
                                  collections=['eval'])

        # Build unbiased pairwise loss only when it is training
        if not forward_only:
            self.rank_list_size = exp_settings['train_list_cutoff']
            train_output = self.ranking_model(self.rank_list_size,
                                              scope='ranking_model')
            train_labels = self.labels[:self.rank_list_size]
            # Build propensity parameters
            self.t_plus = tf.Variable(tf.ones([1, self.rank_list_size]),
                                      trainable=False)
            self.t_minus = tf.Variable(tf.ones([1, self.rank_list_size]),
                                       trainable=False)
            self.splitted_t_plus = tf.split(self.t_plus,
                                            self.rank_list_size,
                                            axis=1)
            self.splitted_t_minus = tf.split(self.t_minus,
                                             self.rank_list_size,
                                             axis=1)
            for i in range(self.rank_list_size):
                tf.summary.scalar('t_plus Probability %d' % i,
                                  tf.reduce_max(self.splitted_t_plus[i]),
                                  collections=['train'])
                tf.summary.scalar('t_minus Probability %d' % i,
                                  tf.reduce_max(self.splitted_t_minus[i]),
                                  collections=['train'])

            # Build pairwise loss based on clicks (0 for unclick, 1 for click)
            output_list = tf.split(train_output, self.rank_list_size, axis=1)
            t_plus_loss_list = [0.0 for _ in range(self.rank_list_size)]
            t_minus_loss_list = [0.0 for _ in range(self.rank_list_size)]
            self.loss = 0.0
            for i in range(self.rank_list_size):
                for j in range(self.rank_list_size):
                    if i == j:
                        continue
                    valid_pair_mask = tf.math.minimum(
                        tf.ones_like(self.labels[i]),
                        tf.nn.relu(self.labels[i] - self.labels[j]))
                    pair_loss = tf.reduce_sum(
                        valid_pair_mask * self.pairwise_cross_entropy_loss(
                            output_list[i], output_list[j]))
                    t_plus_loss_list[i] += pair_loss / self.splitted_t_minus[j]
                    t_minus_loss_list[j] += pair_loss / self.splitted_t_plus[i]
                    self.loss += pair_loss / self.splitted_t_plus[
                        i] / self.splitted_t_minus[j]

            # Update propensity
            self.update_propensity_op = tf.group(
                self.t_plus.assign((1 - self.hparams.EM_step_size) *
                                   self.t_plus +
                                   self.hparams.EM_step_size * tf.pow(
                                       tf.concat(t_plus_loss_list, axis=1) /
                                       t_plus_loss_list[0], 1 /
                                       (self.hparams.regulation_p + 1))),
                self.t_minus.assign((1 - self.hparams.EM_step_size) *
                                    self.t_minus +
                                    self.hparams.EM_step_size * tf.pow(
                                        tf.concat(t_minus_loss_list, axis=1) /
                                        t_minus_loss_list[0], 1 /
                                        (self.hparams.regulation_p + 1))))

            # Add l2 loss
            params = tf.trainable_variables()
            if self.hparams.l2_loss > 0:
                for p in params:
                    self.loss += self.hparams.l2_loss * tf.nn.l2_loss(p)

            # Select optimizer
            self.optimizer_func = tf.train.AdagradOptimizer
            if self.hparams.grad_strategy == 'sgd':
                self.optimizer_func = tf.train.GradientDescentOptimizer

            # Gradients and SGD update operation for training the model.
            opt = self.optimizer_func(self.hparams.learning_rate)
            self.gradients = tf.gradients(self.loss, params)
            if self.hparams.max_gradient_norm > 0:
                self.clipped_gradients, self.norm = tf.clip_by_global_norm(
                    self.gradients, self.hparams.max_gradient_norm)
                self.updates = opt.apply_gradients(
                    zip(self.clipped_gradients, params),
                    global_step=self.global_step)
                tf.summary.scalar('Gradient Norm',
                                  self.norm,
                                  collections=['train'])
            else:
                self.norm = None
                self.updates = opt.apply_gradients(
                    zip(self.gradients, params), global_step=self.global_step)
            tf.summary.scalar('Learning Rate',
                              self.learning_rate,
                              collections=['train'])
            tf.summary.scalar('Loss',
                              tf.reduce_mean(self.loss),
                              collections=['train'])

            reshaped_train_labels = tf.transpose(
                tf.convert_to_tensor(train_labels)
            )  # reshape from [rank_list_size, ?] to [?, rank_list_size]
            pad_removed_train_output = self.remove_padding_for_metric_eval(
                self.docid_inputs, train_output)
            for metric in self.exp_settings['metrics']:
                for topn in self.exp_settings['metrics_topn']:
                    metric_value = utils.make_ranking_metric_fn(metric, topn)(
                        reshaped_train_labels, pad_removed_train_output, None)
                    tf.summary.scalar('%s_%d' % (metric, topn),
                                      metric_value,
                                      collections=['train'])

        self.train_summary = tf.summary.merge_all(key='train')
        self.eval_summary = tf.summary.merge_all(key='eval')
        self.saver = tf.train.Saver(tf.global_variables())