前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >pytorch学习笔记(二十一): 使用 pack_padded_sequence

pytorch学习笔记(二十一): 使用 pack_padded_sequence

作者头像
ke1th
发布2019-05-26 12:24:42
4.9K0
发布2019-05-26 12:24:42
举报

下面附上一张 pack_padded_sequence 原理图(其实只是将三维的输入去掉PAD的部分搞成了二维的。在RNN前向的时候,根据batch_sizes参数取对应的时间步计算。)

在这里插入图片描述
在这里插入图片描述

在使用 pytorch 的 RNN 模块的时候, 有时会不可避免的使用到 pack_padded_sequencepad_packed_sequence, 当使用双向RNN的时候, 必须要使用 pack_padded_sequence !! .否则的话, pytorch 是无法获得 序列的长度, 这样也无法正确的计算双向 RNN/GRU/LSTM 的结果.

但是在使用 pack_padded_sequence 时有个问题, 即输入 mini-batch 序列的长度必须是从长到短排序好的, 当mini-batch 中的样本的顺序非常的重要的话, 这就有点棘手了. 比如说, 每个 sample 是个 单词的 字母级表示, 一个 mini-batch 保存了一句话的 words. 例如:[['p', 'y', 't', 'o', 'r', 'c', 'h'], ['i', 's'], ['g'. 'o', 'o', 'd']] 为一个 mini-batch。这种情况在char-level 的模型中非常常见,先对 char-sequence进行编码,然后再对word-sequence 进行编码。

在这种情况下, 我们依然要使用 pack_padded_sequence, 所以需要先将 mini-batch 中样本排序, 之后输入到 RNN/LSTM/GRU 计算,最后再恢复成以前的顺序.

下面的代码将用来实现这种方法:

代码语言:javascript
复制
import torch
from torch import nn
from torch.autograd import Variable

def rnn_forwarder(rnn, inputs, seq_lengths):
    """
    :param rnn: RNN instance
    :param inputs: FloatTensor, shape [batch, time, dim] if rnn.batch_first else [time, batch, dim]
    :param seq_lengths: LongTensor shape [batch]
    :return: the result of rnn layer,
    """
    batch_first = rnn.batch_first
    # assume seq_lengths = [3, 5, 2]
	# 对序列长度进行排序(降序), sorted_seq_lengths = [5, 3, 2]
    # indices 为 [1, 0, 2], indices 的值可以这么用语言表述
    # 原来 batch 中在 0 位置的值, 现在在位置 1 上.
    # 原来 batch 中在 1 位置的值, 现在在位置 0 上.
    # 原来 batch 中在 2 位置的值, 现在在位置 2 上.
    sorted_seq_lengths, indices = torch.sort(seq_lengths, descending=True)
	
	# 如果我们想要将计算的结果恢复排序前的顺序的话, 
    # 只需要对 indices 再次排序(升序),会得到 [0, 1, 2],  
    # desorted_indices 的结果就是 [1, 0, 2]
    # 使用 desorted_indices 对计算结果进行索引就可以了.
    _, desorted_indices = torch.sort(indices, descending=False)
	
	# 对原始序列进行排序
    if batch_first:
        inputs = inputs[indices]
    else:
        inputs = inputs[:, indices]
    packed_inputs = nn.utils.rnn.pack_padded_sequence(inputs,
                                                      sorted_seq_lengths.cpu().numpy(),
                                                      batch_first=batch_first)

    res, state = rnn(packed_inputs)

    padded_res, _ = nn.utils.rnn.pad_packed_sequence(res, batch_first=batch_first)
	
	# 恢复排序前的样本顺序
    if batch_first:
        desorted_res = padded_res[desorted_indices]
    else:
        desorted_res = padded_res[:, desorted_indices]
    return desorted_res

if __name__ == "__main__":
    bs = 3
    max_time_step = 5
    feat_size = 15
    hidden_size = 7
    seq_lengths = [3, 5, 2]

    rnn = nn.GRU(input_size=feat_size, 
                 hidden_size=hidden_size, batch_first=True, bidirectional=True)
    x = Variable(torch.FloatTensor(bs, max_time_step, feat_size).normal_())
	
    using_packed_res = rnn_forwarder(rnn, x, seq_lengths)
    print(using_packed_res)
	
    # 不使用 pack_paded, 用来和上面的结果对比一下.
    not_packed_res, _ = rnn(x)
    print(not_packed_res)
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年03月29日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
批量计算
批量计算(BatchCompute,Batch)是为有大数据计算业务的企业、科研单位等提供高性价比且易用的计算服务。批量计算 Batch 可以根据用户提供的批处理规模,智能地管理作业和调动其所需的最佳资源。有了 Batch 的帮助,您可以将精力集中在如何分析和处理数据结果上。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档