У меня есть набор данных из n обучающих выборок (где X matrix = 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, но большинство из них имеют дело с использованием встраивания позже, которое я не хочу использовать.