首页 > 解决方案 > 使用 128 的 Batch 大小为 Pytorch-LSTM 提供时间序列输入

问题描述

我有一个包含 n 个训练样本的数据集(其中 X 矩阵 = n * 30 * 20),其中 30 是序列数,20 是特征数。我正在使用分类交叉熵损失,因为这是一项分类任务。我的输入矩阵的形状是 10000 *30 * 20,目标矩阵是 1000 * 1。我想知道将输入提供给 LSTM 的正确方法是什么。我的整个代码附在下面。

import torch.nn as nn
import torch.nn.functional as F
import torch.utils.data as data
import torch.backends.cudnn as cudnn
import torch.optim as optim
import torchvision.transforms as transforms
import torch.utils.data as utils
from torch.utils.data import DataLoader
import torch
from torch.autograd import Variable

class MyData(data.Dataset):
    def __init__(self,X,y,transform=None, target_transform=None):
        self.data = X
        self.targets = y
        self.transform = transform
        self.target_transform= target_transform
    def __getitem__(self, index):
        item, target = self.data[index], self.targets[index]
        item = torch.FloatTensor(item)
        target = torch.LongTensor([target])
        return item, target

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

class MyPredictor(nn.Module):
    def __init__(self, num_blocks=1, input_dim=22, batch_size=128, hidden_dim1=64, hidden_dim2=128, GPU=True):
        super(MyPredictor, self).__init__()
        self.batch_size= batch_size
        self.hidden_dim1=hidden_dim1
        self.hidden_dim2=hidden_dim2
        self.GPU=GPU

        self.lstm1 = nn.LSTM(input_dim,self.hidden_dim1,num_layers=2)
        self.lstm2 = nn.LSTM(self.hidden_dim1, self.hidden_dim2)
        self.fc1 = nn.Linear(self.hidden_dim2, 256)
        self.fc2=nn.Linear(256,1)


    if self.GPU:
        self.hx1 = Variable(torch.zeros(30, self.batch_size, self.hidden_dim1).cuda())
        self.cx1 = Variable(torch.zeros(30, self.batch_size, self.hidden_dim1).cuda())
        self.hx2 = Variable(torch.zeros(30, self.batch_size, self.hidden_dim2).cuda())
        self.cx2 = Variable(torch.zeros(30, self.batch_size, self.hidden_dim2).cuda())
    else:
        self.hx1 = Variable(torch.zeros(30, self.batch_size, self.hidden_dim1))
        self.cx1 = Variable(torch.zeros(30, self.batch_size, self.hidden_dim1))
        self.hx2 = Variable(torch.zeros(30, self.batch_size, self.hidden_dim2))
        self.cx2 = Variable(torch.zeros(30, self.batch_size, self.hidden_dim2))

        self.hidden1=(self.hx1,self.cx1)
        self.hidden2=(self.hx2,self.cx2)

    def forward(self, x):

        out1, self.hidden1 = self.lstm1(x, self.hidden1)
        out2, self.hidden2 = self.lstm1(x, self.hidden2)
        out3=self.fc1(out2)
        out3= F.relu(out3)
        out4=self.fc2(out3)
        out=F.relu(out4)

        return out

此外,我将隐藏状态和单元状态初始化为 1 * Batch_size * 隐藏大小。但是,由于我有 30 作为序列长度,它应该是 30 * batch_size * 隐藏大小吗?

def train(epoch):
    print('\nEpoch: %d' % epoch)
    net.train()
    train_loss = 0
    correct = 0
    total = 0
    store=[]
    for batch_idx, (inputs, targets) in enumerate(trainloader):
        inputs, targets = inputs.to(device), targets.to(device)
        optimizer.zero_grad()
        outputs = net(inputs)
        loss = criterion(outputs, targets)
        loss.backward()
        optimizer.step()

        train_loss += loss.item()
        _, predicted = outputs.max(1)
        total += targets.size(0)
        correct += predicted.eq(targets).sum().item()

#         progress_bar(batch_idx, len(trainloader), 'Loss: %.3f | Acc: %.3f%% (%d/%d)'
#             % (train_loss/(batch_idx+1), 100.*correct/total, correct, total))
    print("Train->Epoch: ",epoch," Accuracy: ",100.*correct/total," Loss ",train_loss/len(trainloader))
    return[100.*correct/total,train_loss/len(trainloader)]


def test(epoch):
    global best_acc
    criterion = nn.CrossEntropyLoss()
    net.eval()
    test_loss = 0
    correct = 0
    total = 0
    with torch.no_grad():
        for batch_idx, (inputs, targets) in enumerate(testloader):
            inputs, targets = inputs.to(device), targets.to(device)
            outputs = net(inputs)
            loss = criterion(outputs, targets)

            test_loss += loss.item()
            _, predicted = outputs.max(1)
            total += targets.size(0)
            correct += predicted.eq(targets).sum().item()

#             progress_bar(batch_idx, len(testloader), 'Loss: %.3f | Acc: %.3f%% (%d/%d)'
#                 % (test_loss/(batch_idx+1), 100.*correct/total, correct, total))

    print("Test->Epoch: ",epoch," Accuracy: ",100.*correct/total," Loss ",test_loss/len(testloader))

我正在加载我的输入,如下所示:

from sklearn.externals import joblib
import numpy as np

#See if Gpu is available
device = 'cuda' if torch.cuda.is_available() else 'cpu'
net=MyPredictor()      
net = net.to(device)
GPU=False
if device == 'cuda':
    net = torch.nn.DataParallel(net)
    cudnn.benchmark = True
    GPU= True

#optimizer = optim.SGD(model.parameters(), lr=0.1)
optimizer = optim.Adam(net.parameters(), lr=0.001)
criterion = nn.CrossEntropyLoss()

#Load the datset


X, y = joblib.load("/app/dhanush/lstm_training_data.pkl")
X_train=np.array(X[0:30000])
X_test=np.array(X[30000:])
y_train= np.array(y[0:30000])
y_test= np.array(y[30000:])

print (X_train.shape)
print (y_train.shape)

trainset = MyData(X_train,y_train)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=128, shuffle=False, num_workers=2)

testset = MyData(X_test, y_test)
testloader = torch.utils.data.DataLoader(testset, batch_size=128, shuffle=False, num_workers=2)


for epoch in range(0, 21):
    train(epoch)
    test(epoch)

我收到以下形状不匹配错误。我绝对认为这与我的输入张量或我初始化隐藏状态的方式有关。另外,我不确定我对第一个全连接层的输入是否正确。我应该只给出 LSTM 2 的最后一个隐藏状态输出吗(self.hx2[-1]?)

在阅读其他帖子时,我看到对于 2D 输入,有时会要求您重新整形以(sequence * batch size * feature)直接输入到 LSTM。这是如何运作的 ?

最重要的是我收到以下错误:

RuntimeError: Expected hidden[0] size (1, 30, 64), got (30, 128, 64)

我知道这很多,但我的目标是提供尽可能多的信息。我已经阅读了其他帖子,示例 GitHub 代码,但其中大多数处理使用稍后我不想使用的嵌入。

标签: pythonpytorch

解决方案


推荐阅读