Paddle 如何遍历序列数据里每一个时间步

cdmah0mi  于 2021-11-29  发布在  Java
关注(0)|答案(5)|浏览(215)

program里面定义的data长这样:
image_lod = fluid.layers.data(name = 'image_lod', dtype = 'float32', shape = [1], lod_level = 1) label_lod = fluid.layers.data(name = 'label_lod', dtype = 'int64', shape = [1], lod_level = 1) last_label_lod = fluid.layers.data(name = 'last_label_lod', dtype = 'int64', shape = [1], lod_level = 1)
都是长度为50的list。
我需要在训练的时候分步处理每一个时间步的数据,了解到有种方法是用lod tensor array。先将lod tensor转换成lod tensor array,然后用while_op和array_read来遍历。但是了解到lod_tensor_to_array只在dynamicRNN里面用到,Python接口并没有对用户暴露,不太了解array = lod_tensor_to_array(x, table)里面rank_table是什么东西。
有没有遍历序列数据的什么实现方法?或者能解释一下lod_tensor_to_array的用法么?

kcugc4gi

kcugc4gi1#

输入数据使用LODTensor的话,对于分步处理每一个时间步的数据的需求,大部分情况应该都可以直接使用DynamicRNN,可以尝试使用下,这里有示例 https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/fluid/tests/book/test_machine_translation.py#L69 ,其中rnn.step_input即是每一个时间步的数据,rnn.memory是需要更新的rnn的hidden state,另外还有个rnn.static_input是rnn外部的数据在DynamicRNN内的表示(如encoder的output),可以利用这三种数据完成所需操作,可以试下是否能满足需求

rank_table记录了每个sequence的长度,DynamicRNN中调用了lod_tensor_to_array在产生array时按照rank_table做了特殊处理(sequence从长到短排序后从前到后进行slice),每个时间步数据的batch size可能会缩小(短的sequence结束时),这是Fluid DynamicRNN的一些特殊之处

另外对于非LoDTensor的数据,可以试下使用StaticRNN,用法与上面的类似,这里有个语言模型的例子 https://github.com/PaddlePaddle/models/blob/develop/fluid/PaddleNLP/language_model/lstm/lm_model.py#L261

7jmck4yq

7jmck4yq2#

我采用了这个方案来搭建网络,但是用dynamic rnn训练的速度十分慢,我的基线模型是rnn,跑一个batch只需要0.12s,但是用dynamic rnn得花2s。请问这个可以优化一下吗。

20jt8wwn

20jt8wwn3#

好的,我们排期支持下

zdwk9cvp

zdwk9cvp4#

可以提供下更多的描述信息吗,我们定位下性能哪儿出了问题

628mspwn

628mspwn5#

drnn = fluid.layers.DynamicRNN()
with drnn.block():
    input_t = drnn.step_input(recent_feature_emb_concat)
    label_t_1 = drnn.step_input(last_target)
    offset = drnn.static_input(offset)
    read_mem_t_1 = drnn.memory(
            shape=[self.conf.nb_reads * self.conf.memory_shape[1]], dtype='float32', value=0)
    h_t_1 = drnn.memory(shape=[self.conf.cell_size], dtype='float32', value=0)
    c_t_1 = drnn.memory(shape=[self.conf.cell_size], dtype='float32', value=0)
    u_w_t_1 = drnn.memory(shape=[self.conf.memory_shape[0]], dtype='float32', value=0)
    r_w_t_1 = drnn.memory(shape=[self.conf.nb_reads, self.conf.memory_shape[0]], dtype='float32', value=0)
    mem_t_1 = drnn.memory(
            shape=[self.conf.memory_shape[0], self.conf.memory_shape[1]], dtype='float32', value=0)
    read_mem_t, h_t, c_t, u_w_t, r_w_t, mem_t = self.forward_onestep(
            input_t, label_t_1, read_mem_t_1, h_t_1, c_t_1,
            u_w_t_1, offset, r_w_t_1, mem_t_1)
    #fluid.layers.Print(input=read_mem_t, print_tensor_type=False, print_tensor_shape=False, print_tensor_lod=False, message='read_mem_t', summarize=0)
    drnn.update_memory(ex_mem = read_mem_t_1, new_mem = read_mem_t)
    drnn.update_memory(ex_mem = h_t_1, new_mem = h_t)
    drnn.update_memory(ex_mem = c_t_1, new_mem = c_t)
    drnn.update_memory(ex_mem = u_w_t_1, new_mem = u_w_t)
    drnn.update_memory(ex_mem = r_w_t_1, new_mem = r_w_t)
    drnn.update_memory(ex_mem = mem_t_1, new_mem = mem_t)
    loss_input = \
        fluid.layers.fc(
                input=h_t,
                size=self.conf.cell_size,
                param_attr=fluid.ParamAttr(name = 'out_fc_param'),
                bias_attr=fluid.ParamAttr(name = 'out_fc_bias')) \
        + fluid.layers.fc(
                input=read_mem_t,
                size=self.conf.cell_size,
                param_attr=fluid.ParamAttr(name = 'state_fc_param_attr'),
                bias_attr = fluid.ParamAttr(name = 'state_fc_bias_attr')) \
        + fluid.layers.fc(input=c_t, size=self.conf.cell_size) * 0 \
        + fluid.layers.fc(input=u_w_t, size=self.conf.cell_size) * 0 \
        + fluid.layers.fc(input=r_w_t, size=self.conf.cell_size) * 0 \
        + fluid.layers.fc(input=mem_t, size=self.conf.cell_size) * 0
    drnn.output(loss_input)
recent_ntm = fluid.layers.sequence_last_step(input=drnn())

主要是这一段的耗时多

相关问题