Example #1
0
    def dynamic_rnn(self, item_fc, h_0, output_type=None, double_type=None, double_id=None):
        drnn = fluid.layers.DynamicRNN()
        pos = fluid_sequence_get_pos(item_fc)
        with drnn.block():
            cur_item_fc = drnn.step_input(item_fc)
            cur_h_0 = drnn.memory(init=h_0, need_reorder=True)

            cur_item_fc = layers.lod_reset(cur_item_fc, cur_h_0)
            next_h_0 = self.simple_step_rnn(cur_item_fc, h_0=cur_h_0)

            if output_type == 'c_Q':
                Q = self.out_Q_fc2_op(self.out_Q_fc1_op(next_h_0))
                drnn.output(Q)

            elif output_type in ['max_Q', 'double_Q']:
                # batch_size = 2
                # item_fc: lod = [0,4,7]
                # cur_h_0: lod = [0,1,2]
                item_fc = drnn.static_input(item_fc)
                pos = drnn.static_input(pos)
                cur_step = drnn.memory(shape=[1], dtype='int64', value=0)

                expand_h_0 = layers.sequence_expand(cur_h_0, item_fc)               # lod = [0,1,2,3,4,5,6,7]
                new_item_fc = layers.lod_reset(item_fc, expand_h_0)                 # lod = [0,1,2,3,4,5,6,7]
                next_expand_h_0 = self.simple_step_rnn(new_item_fc, expand_h_0)     # lod = [0,1,2,3,4,5,6,7]
                next_expand_h_0 = layers.lod_reset(next_expand_h_0, item_fc)        # lod = [0,4,7]

                expand_Q = self.out_Q_fc2_op(self.out_Q_fc1_op(next_expand_h_0))
                cur_step_id = layers.slice(cur_step, axes=[0, 1], starts=[0, 0], ends=[1, 1])
                mask = layers.cast(pos >= cur_step_id, 'float32')
                expand_Q = expand_Q * mask

                if output_type == 'max_Q':
                    max_Q = layers.sequence_pool(expand_Q, 'max')                       # lod = [0,1,2]
                    drnn.output(max_Q)
                elif output_type == 'double_Q':
                    if double_type == 'max_id':
                        max_id = self.eps_greedy_sampling(expand_Q, mask, eps=0)
                        drnn.output(max_id)
                    elif double_type == 'double_Q':
                        cur_double_id = drnn.step_input(double_id)

                        double_Q = fluid_sequence_index(expand_Q, cur_double_id)
                        drnn.output(double_Q)

                # update
                next_step = cur_step + 1
                drnn.update_memory(cur_step, next_step)

            elif output_type == 'hidden':
                drnn.output(next_h_0)                

            else:
                raise NotImplementedError(output_type)

            # update
            drnn.update_memory(cur_h_0, next_h_0)

        drnn_output = drnn()
        return drnn_output
Example #2
0
    def sampling_rnn(self,
                     item_fc,
                     h_0,
                     pos_embed,
                     forward_func,
                     sampling_type,
                     eps=0,
                     eta=1):
        mask = layers.reduce_sum(item_fc, dim=1, keep_dim=True) * 0 + 1
        drnn = fluid.layers.DynamicRNN()
        with drnn.block():
            # e.g. batch_size = 2
            _ = drnn.step_input(item_fc)
            cur_pos_embed = drnn.step_input(pos_embed)  # lod = []
            cur_h_0 = drnn.memory(init=h_0, need_reorder=True)  # lod = [0,1,2]
            item_fc = drnn.static_input(item_fc)
            mask = drnn.memory(init=mask, need_reorder=True)

            # step_input will remove lod info
            cur_pos_embed = layers.lod_reset(cur_pos_embed, cur_h_0)

            # expand
            expand_h_0 = layers.sequence_expand(
                cur_h_0, item_fc)  # lod = [0,1,2,3,4,5,6,7]
            expand_pos_embed = layers.sequence_expand(
                cur_pos_embed, item_fc)  # lod = [0,1,2,3,4,5,6,7]
            expand_item_fc = layers.lod_reset(item_fc, expand_h_0)
            # forward
            expand_next_h_0, expand_scores = forward_func(
                expand_item_fc, expand_h_0, expand_pos_embed)
            # reset result lod
            expand_next_h_0 = layers.lod_reset(expand_next_h_0,
                                               item_fc)  # lod = [0,4,7]
            expand_scores = layers.lod_reset(expand_scores,
                                             item_fc)  # lod = [0,4,7]

            if sampling_type == 'eps_greedy':
                selected_index = self.eps_greedy_sampling(expand_scores,
                                                          mask,
                                                          eps=eps)
            elif sampling_type == 'softmax':
                selected_index = self.softmax_sampling(expand_scores,
                                                       mask,
                                                       eta=eta)

            drnn.output(selected_index)

            next_h_0 = fluid_sequence_index(expand_next_h_0, selected_index)
            next_mask = fluid_sequence_scatter(
                mask, layers.reshape(selected_index, [-1]), 0.0)

            # update
            drnn.update_memory(cur_h_0, next_h_0)
            drnn.update_memory(mask, next_mask)

        drnn_output = drnn()
        return drnn_output
Example #3
0
    def train_rnn(self,
                  item_fc,
                  atten_item_fc,
                  h_0,
                  pos,
                  pos_embed,
                  output_type=''):
        shifted_item_fc = fluid_sequence_advance(item_fc, OOV=0)
        drnn = fluid.layers.DynamicRNN()
        with drnn.block():
            cur_item_fc = drnn.step_input(shifted_item_fc)
            cur_pos_embed = drnn.step_input(pos_embed)
            cur_h_0 = drnn.memory(init=h_0, need_reorder=True)

            # step_input will remove lod info
            cur_item_fc = layers.lod_reset(cur_item_fc, cur_h_0)
            cur_pos_embed = layers.lod_reset(cur_pos_embed, cur_h_0)

            next_h_0, hidden_fc = self.sampling_rnn_forward(
                cur_item_fc, cur_h_0, cur_pos_embed)

            if output_type == 'c_Q':
                cur_atten_item_fc = drnn.step_input(atten_item_fc)
                cur_atten_item_fc = layers.lod_reset(cur_atten_item_fc,
                                                     cur_h_0)

                Q = layers.reduce_sum(hidden_fc * cur_atten_item_fc,
                                      dim=1,
                                      keep_dim=True)
                drnn.output(Q)

            elif output_type == 'max_Q':
                cur_pos = drnn.step_input(pos)
                pos = drnn.static_input(pos)
                atten_item_fc = drnn.static_input(atten_item_fc)

                expand_Q = self._dot_attention(hidden_fc, atten_item_fc)

                cur_step_id = layers.slice(cur_pos,
                                           axes=[0, 1],
                                           starts=[0, 0],
                                           ends=[1, 1])
                mask = layers.cast(pos >= cur_step_id, 'float32')
                expand_Q = expand_Q * mask
                max_Q = layers.sequence_pool(expand_Q, 'max')
                drnn.output(max_Q)

            else:
                raise NotImplementedError(output_type)

            # update
            drnn.update_memory(cur_h_0, next_h_0)

        drnn_output = drnn()
        return drnn_output
Example #4
0
    def train_rnn(self, item_fc, h_0, pos, pos_embed, output_type=''):
        drnn = fluid.layers.DynamicRNN()
        with drnn.block():
            cur_item_fc = drnn.step_input(item_fc)
            cur_pos_embed = drnn.step_input(pos_embed)
            cur_h_0 = drnn.memory(init=h_0, need_reorder=True)

            # step_input will remove lod info
            cur_item_fc = layers.lod_reset(cur_item_fc, cur_h_0)
            cur_pos_embed = layers.lod_reset(cur_pos_embed, cur_h_0)

            next_h_0, Q = self.sampling_rnn_forward(cur_item_fc, cur_h_0,
                                                    cur_pos_embed)

            if output_type == 'c_Q':
                drnn.output(Q)

            elif output_type == 'max_Q':
                # e.g. batch_size = 2
                # cur_h_0: lod = [0,1,2]
                cur_pos = drnn.step_input(pos)
                pos = drnn.static_input(pos)  # lod = [0,4,7]
                item_fc = drnn.static_input(item_fc)  # lod = [0,4,7]

                # expand
                expand_h_0 = layers.sequence_expand(
                    cur_h_0, item_fc)  # lod = [0,1,2,3,4,5,6,7]
                expand_pos_embed = layers.sequence_expand(
                    cur_pos_embed, item_fc)  # lod = [0,1,2,3,4,5,6,7]
                expand_item_fc = layers.lod_reset(item_fc, expand_h_0)
                # forward
                _, expand_scores = self.sampling_rnn_forward(
                    expand_item_fc, expand_h_0, expand_pos_embed)
                # reset result lod
                expand_Q = layers.lod_reset(expand_scores,
                                            item_fc)  # lod = [0,4,7]

                cur_step_id = layers.slice(cur_pos,
                                           axes=[0, 1],
                                           starts=[0, 0],
                                           ends=[1, 1])
                mask = layers.cast(pos >= cur_step_id, 'float32')
                expand_Q = expand_Q * mask
                max_Q = layers.sequence_pool(expand_Q, 'max')  # lod = [0,1,2]
                drnn.output(max_Q)

            else:
                raise NotImplementedError(output_type)

            # update
            drnn.update_memory(cur_h_0, next_h_0)

        drnn_output = drnn()
        return drnn_output
Example #5
0
    def sampling_rnn(self,
                     item_fc,
                     atten_item_fc,
                     h_0,
                     pos_embed,
                     sampling_type,
                     eps=0,
                     eta=1):
        oov_item_fc = layers.fill_constant_batch_size_like(item_fc,
                                                           shape=item_fc.shape,
                                                           value=0,
                                                           dtype='float32')
        oov_item_fc = layers.lod_reset(oov_item_fc, h_0)
        mask = layers.reduce_sum(item_fc, dim=1, keep_dim=True) * 0 + 1
        drnn = fluid.layers.DynamicRNN()
        with drnn.block():
            _ = drnn.step_input(item_fc)
            cur_pos_embed = drnn.step_input(pos_embed)
            cur_item_fc = drnn.memory(init=oov_item_fc, need_reorder=True)
            cur_h_0 = drnn.memory(init=h_0, need_reorder=True)
            mask = drnn.memory(init=mask, need_reorder=True)
            item_fc = drnn.static_input(item_fc)
            atten_item_fc = drnn.static_input(atten_item_fc)

            # step_input will remove lod info
            cur_pos_embed = layers.lod_reset(cur_pos_embed, cur_h_0)

            next_h_0, hidden_fc = self.sampling_rnn_forward(
                cur_item_fc, cur_h_0, cur_pos_embed)
            expand_Q = self._dot_attention(hidden_fc, atten_item_fc)

            if sampling_type == 'eps_greedy':
                selected_index = self.eps_greedy_sampling(expand_Q,
                                                          mask,
                                                          eps=eps)
            elif sampling_type == 'softmax':
                selected_index = self.softmax_sampling(expand_Q, mask, eta=eta)

            drnn.output(selected_index)

            next_item_fc = fluid_sequence_index(item_fc, selected_index)
            next_mask = fluid_sequence_scatter(
                mask, layers.reshape(selected_index, [-1]), 0.0)

            # update
            drnn.update_memory(cur_item_fc, next_item_fc)
            drnn.update_memory(cur_h_0, next_h_0)
            drnn.update_memory(mask, next_mask)

        drnn_output = drnn()
        return drnn_output
Example #6
0
    def sampling(self, inputs, sampling_type):
        decode_len = inputs['decode_len']
        user_feature = self.user_encode(inputs)
        item_embedding = self._build_embeddings(inputs, self.item_slot_names)
        item_fc = self.item_fc_op(item_embedding)
        pos = fluid_sequence_get_pos(item_fc)
        pos_embed = self.dict_data_embed_op['pos'](pos)

        if self._candidate_encode:
            cand_encoding = self.candidate_encode(item_fc)
            init_hidden = self.candidate_encode_fc_op(
                layers.concat([user_feature, cand_encoding], 1))
        else:
            init_hidden = user_feature
        eps = inputs['eps'] if sampling_type == 'eps_greedy' else None
        eta = inputs['eta'] if sampling_type == 'softmax' else None
        sampled_id = self.sampling_rnn(item_fc,
                                       h_0=init_hidden,
                                       pos_embed=pos_embed,
                                       forward_func=self.sampling_rnn_forward,
                                       sampling_type=sampling_type,
                                       eps=eps,
                                       eta=eta)
        sampled_id = self._cut_by_decode_len(
            layers.lod_reset(sampled_id, item_fc), decode_len)
        return sampled_id
Example #7
0
 def user_encode(self, recent_embedding):
     """user encode part"""
     recent_concat_fc = self.recent_fc_op(recent_embedding)
     recent_feature_gru = self.recent_gru_op(recent_concat_fc)
     recent_feature_gru_last = layers.sequence_pool(input=recent_feature_gru, pool_type="last")
     lod_reference = fluid_sequence_first_step(recent_feature_gru)
     lod_reference.stop_gradient = True
     recent_feature_gru_last = layers.lod_reset(recent_feature_gru_last, lod_reference)
     user_feature = self.user_feature_fc_op(recent_feature_gru_last)
     return user_feature
Example #8
0
    def train_rnn(self, item_fc, last_click_embedding, h_0, output_type=''):
        """
        BUG: will crash.
        """
        shifted_item_fc = fluid_sequence_advance(item_fc, OOV=0)
        drnn = fluid.layers.DynamicRNN()
        with drnn.block():
            last_item_fc = drnn.step_input(shifted_item_fc)
            last_click_embedding = drnn.step_input(last_click_embedding)
            cur_h_0 = drnn.memory(init=h_0, need_reorder=True)

            # step_input will remove lod info
            last_item_fc = layers.lod_reset(last_item_fc, cur_h_0)
            last_click_embedding = layers.lod_reset(last_click_embedding,
                                                    cur_h_0)

            next_h_0 = self.simple_step_rnn(last_item_fc,
                                            last_click_embedding,
                                            h_0=cur_h_0)

            if output_type == 'c_Q':
                cur_item_fc = drnn.step_input(item_fc)
                cur_item_fc = layers.lod_reset(cur_item_fc, cur_h_0)
                Q = self.critic_value(next_h_0, cur_item_fc)
                drnn.output(Q)

            elif output_type == 'max_Q':
                action_hat = self.actor_policy(next_h_0)
                max_Q = self.critic_value(next_h_0, action_hat)
                drnn.output(max_Q)

            else:
                raise NotImplementedError(output_type)

            # update
            drnn.update_memory(cur_h_0, next_h_0)

        drnn_output = drnn()
        return drnn_output
Example #9
0
 def _dot_attention(self, input, atten_items):
     """
     args:
         input: (batch, dim), lod_level = 0
         atten_items: (batch*seq_len, dim), lod_level = 1
     return:
         atten_weights: (batch*seq_len, 1), lod_level = 1
     """
     expand_input = layers.sequence_expand(
         input, atten_items)  #(batch*seq_len, dim), lod_level = 0
     expand_input = layers.lod_reset(
         expand_input, atten_items)  #(batch*seq_len, dim), lod_level = 1
     if self._attention_type == 'concat_fc':
         atten_weights = self.atten_fc_op(
             layers.concat([expand_input, atten_items], 1))
     elif self._attention_type == 'dot':
         atten_weights = layers.reduce_sum(
             expand_input * atten_items, dim=1,
             keep_dim=True)  #(batch*seq_len, 1), lod_level = 1
     return atten_weights
Example #10
0
    def forward(self, inputs, output_type):
        """forward"""
        decode_len = inputs['decode_len']
        user_feature = self.user_encode(inputs)
        item_embedding = self._build_embeddings(inputs, self.item_slot_names)
        item_fc = self.item_fc_op(item_embedding)
        atten_item_fc = self.atten_item_fc_op(item_embedding)
        cand_encoding = self.candidate_encode(item_fc)
        pos = fluid_sequence_get_pos(item_fc)
        pos_embed = self.dict_data_embed_op['pos'](pos)

        init_hidden = self.candidate_encode_fc_op(
            layers.concat([user_feature, cand_encoding], 1))
        item_Q = self.train_rnn(item_fc,
                                atten_item_fc,
                                init_hidden,
                                pos,
                                pos_embed,
                                output_type=output_type)
        item_Q = self._cut_by_decode_len(layers.lod_reset(item_Q, item_fc),
                                         decode_len)
        return item_Q