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
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
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
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
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
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
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
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
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
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