input 长度设置_PyTorch 训练 RNN 时,序列长度不固定怎么办?

当每个训练数据为 sequence 的时候,我们第一反应是采用 RNN 以及其各种变体。这时新手们(我也是刚弄明白)往往会遇到这样的问题:训练数据 sequence 长度是变化的,难以采用 mini-batch 训练,这时应该怎么办,难道只能一个 sequence 一个 sequence 地训练吗?针对这一问题,本文记录 PyTorch 给出的解决方案。

需要用到的函数如下:

torch.nn.utils.rnn.pad_sequence()
torch.nn.utils.rnn.pack_padded_sequence()
torch.nn.utils.rnn.pad_packed_sequence()

pad_sequence

我们构造如下的训练数据,其中每条训练数据长度都不同。

import torch
from torch import nn
import torch.nn.utils.rnn as rnn_utils

train_x = [torch.tensor([1, 1, 1, 1, 1, 1, 1]),
           torch.tensor([2, 2, 2, 2, 2, 2]),
           torch.tensor([3, 3, 3, 3, 3]),
           torch.tensor([4, 4, 4, 4]),
           torch.tensor([5, 5, 5]),
           torch.tensor([6, 6]),
           torch.tensor([7])]


x = rnn_utils.pad_sequence(train_x, batch_first=True)

x 将变成:

tensor([[1, 1, 1, 1, 1, 1, 1],
        [2, 2, 2, 2, 2, 2, 0],
        [3, 3, 3, 3, 3, 0, 0],
        [4, 4, 4, 4, 0, 0, 0],
        [5, 5, 5, 0, 0, 0, 0],
        [6, 6, 0, 0, 0, 0, 0],
        [7, 0, 0, 0, 0, 0, 0]])

我们发现,这个函数会把长度小于最大长度的 sequences 用 0 填充,并且把 list 中所有的元素拼成一个 tensor。这样做的主要目的是为了让 DataLoader 可以返回 batch,因为 batch 是一个高维的 tensor,其中每个元素的数据必须长度相同。

为了证明这一点,我们完整地写一个数据类,用 dataloader 按 batch 的形式读取数据,代码如下:

import torch
from torch import nn
import torch.nn.utils.rnn as rnn_utils
from torch.utils.data import DataLoader
import torch.utils.data as data

train_x = [torch.tensor([1, 1, 1, 1, 1, 1, 1]),
           torch.tensor([2, 2, 2, 2, 2, 2]),
           torch.tensor([3, 3, 3, 3, 3]),
           torch.tensor([4, 4, 4, 4]),
           torch.tensor([5, 5, 5]),
           torch.tensor([6, 6]),
           torch.tensor([7])]

x = rnn_utils.pad_sequence(train_x, batch_first=True)


class MyData(data.Dataset):
    def __init__(self, data_seq):
        self.data_seq = data_seq

    def __len__(self):
        return len(self.data_seq)

    def __getitem__(self, idx):
        return self.data_seq[idx]


if __name__=='__main__':
    data = MyData(train_x)
    data_loader = DataLoader(data, batch_size=2, shuffle=True)
    batch_x = iter(data_loader).next()
    print('END')

我们将会收到如下报错:

RuntimeError: invalid argument 0: Sizes of tensors must match except in dimension
0. Got 3 and 7 in dimension 1 at 
/pytorch/aten/src/TH/generic/THTensorMoreMath.cpp:1333

报错的原因是,不同的数据长度不同,无法组成一个 batch tensor。

DataLoader中有个参数 collate_fn,专门用来把 Dataset 类的返回值拼接成 tensor,我们不

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是一个使用PyTorch实现RNN训练的代码样例,包括数据处理、模型定义、训练和测试四个部分: ```python import torch import torch.nn as nn import numpy as np # 数据处理部分 input_size = 1 output_size = 1 sequence_length = 10 data_size = 1000 inputs = np.random.randn(data_size, sequence_length, input_size) targets = np.random.randn(data_size, output_size) inputs = torch.from_numpy(inputs).float() targets = torch.from_numpy(targets).float() # 模型定义部分 class RNN(nn.Module): def __init__(self, input_size, hidden_size, output_size): super(RNN, self).__init__() self.hidden_size = hidden_size self.rnn = nn.RNN(input_size, hidden_size, batch_first=True) self.linear = nn.Linear(hidden_size, output_size) def forward(self, x): h0 = torch.zeros(1, x.size(0), self.hidden_size) out, hn = self.rnn(x, h0) out = self.linear(out[:, -1, :]) return out # 训练部分 num_epochs = 100 learning_rate = 0.01 model = RNN(input_size, hidden_size=16, output_size=output_size) criterion = nn.MSELoss() optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate) for epoch in range(num_epochs): outputs = model(inputs) loss = criterion(outputs, targets) optimizer.zero_grad() loss.backward() optimizer.step() if (epoch+1) % 10 == 0: print("Epoch [{}/{}], Loss: {:.4f}".format(epoch+1, num_epochs, loss.item())) # 测试部分 with torch.no_grad(): inputs_test = np.random.randn(1, sequence_length, input_size) inputs_test = torch.from_numpy(inputs_test).float() outputs_test = model(inputs_test) print("Input: {}".format(inputs_test)) print("Output: {}".format(outputs_test)) ``` 这个代码样例实现了一个RNN模型,用于预测一个长度为10的序列的最后一个值。在训练部分中,使用MSE(Mean Squared Error)作为损失函数,使用Adam优化算法进行参数更新。在测试部分中,随机生成一个长度为10的序列输入数据,将其输入训练好的模型中,得到模型的输出结果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值