I am trying to train a simple RNN off tabular .csv data with 9 features and 7 classes.
However, I keep running into the runtime error that the hx should be 2-D input. Additionally, I'm not sure why it expects an unbatched input when batch_first=True.
Specifications:
- Google Colab environment
- CSV file for data
What I've tried:
- Changing the hyperparameters
- Adding .squeeze(1) before model(data)
My suspicions:
- Something problematic with the custom dataset?
# Hyperparameters
input_size = 9
sequence_length = 1
num_layers = 2
hidden_size = 81
num_classes = 1
learning_rate = 0.001
batch_size = 32
num_epochs = 4
Model
# Recurrent neural network (many-to-one)
class RNN(nn.Module):
def __init__(self, input_size, hidden_size, num_layers, num_classes):
super(RNN, self).__init__()
self.hidden_size = hidden_size
self.num_layers = num_layers
self.rnn = nn.RNN(input_size, hidden_size, num_layers, batch_first=True)
self.fc = nn.Linear(hidden_size * sequence_length, num_classes)
def forward(self, x):
# Set initial hidden and cell states
h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_size).to(device)
# Forward propagate LSTM
out, _ = self.rnn(x, h0)
out = out.reshape(out.shape[0], -1)
# Decode the hidden state of the last time step
out = self.fc(out)
return out
Data
df1=pd.read_csv('s01.csv')
dfLabels=pd.read_csv('s01-labels.csv')
from sklearn.model_selection import train_test_split
X_train,X_test,y_train,y_test = train_test_split(df1,dfLabels,test_size=0.2, random_state=44)
# Create Dataset
class PDDataset(Dataset):
def __init__(self, df_features, df_labels):
x = df_features.values
y = df_labels.values
self.x = torch.tensor(x, dtype=torch.float32)
self.y = torch.tensor(y)
def __len__(self):
return len(self.y)
def __getitem__(self, idx):
return self.x[idx], self.y[idx]
# Load Data
train_dataset = PDDataset(X_train, y_train)
test_dataset = PDDataset(X_test, y_test)
train_loader = DataLoader(dataset=train_dataset, batch_size=batch_size, shuffle=True, drop_last=True)
test_loader = DataLoader(dataset=test_dataset, batch_size=batch_size, shuffle=True, drop_last=True)
Instantiation
# Initialize network (try out just using simple RNN, or GRU, and then compare with LSTM)
# model = RNN(input_size, hidden_size, num_layers, num_classes).to(device)
model = RNN(input_size, num_classes, hidden_size, num_layers).to(device)
# Loss and optimizer
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=learning_rate)
Training
# Train Network
for epoch in range(num_epochs):
for batch_idx, (data, targets) in enumerate(tqdm(train_loader)):
# Get data to cuda if possible
data = data.to(device=device)#.squeeze(1)
targets = targets.to(device=device)
# forward
# print(data.dim())
scores = model(data)
loss = criterion(scores, targets)
# backward
optimizer.zero_grad()
loss.backward()
# gradient descent update step/adam step
optimizer.step()
Error
---------------------------------------------------------------------------
RuntimeError Traceback (most recent call last)
<ipython-input-32-3b061434be54> in <module>
8 # forward
9 # print(data.dim())
---> 10 scores = model(data)
11 loss = criterion(scores, targets)
12
3 frames
/usr/local/lib/python3.7/dist-packages/torch/nn/modules/rnn.py in forward(self, input, hx)
926 if hx.dim() != 2:
927 raise RuntimeError(
--> 928 f"For unbatched 2-D input, hx should also be 2-D but got {hx.dim()}-D tensor")
929 hx = hx.unsqueeze(1)
930 else:
RuntimeError: For unbatched 2-D input, hx should also be 2-D but got 3-D tensor