I was trying to make my own neural network using PyTorch. I do not understand why my code is not working properly.
import torch import torch.nn as nn import torch.nn.functional as F import torch.optim as optimizers import numpy as np from tqdm import tqdm import os import hashlib # Only for the first time MAKE_DATA = False class Model(nn.Module): def __init__(self): super().__init__() self.fc1 = nn.Linear(2, 100) self.fc2 = nn.Linear(100, 200) self.fc3 = nn.Linear(200, 200) self.fc4 = nn.Linear(200, 1) def forward(self, x): x = F.relu(self.fc1(x)) x = F.relu(self.fc2(x)) x = F.relu(self.fc3(x)) x = self.fc4(x) return F.relu(x) def make_numirical(data): data = str(data) data = data.encode() data = hashlib.md5(data).hexdigest() str1 = '' for c in data: if not (c >= '0' and c <= '9'): c = ord(c) if c > 10: c /= 10 str1 += str(int(c)) return int(str1[:20]) def make_train_data(): HITS = 'Songs_DB/Hits' NOHITS = 'Songs_DB/NoHits' hits_count = 0 no_hits_count = 0 LABELS = {HITS: 0, NOHITS: 0} training_data = [] i = 0 for label in LABELS: for f in tqdm(os.listdir(label)): try: path = os.path.join(label, f) with open(path, 'rb') as file: data = file.read() file.close() data = make_numirical(data) data = int(data) training_data.append([np.array([data]), np.eye(2)[i]]) if label == HITS: hits_count += 1 else: no_hits_count += 1 except: pass i += 1 np.random.shuffle(training_data) np.save('training_data.npy', training_data) print(hits_count) print(no_hits_count) if MAKE_DATA: make_train_data() model = Model() # 1 = brown, 0 = not brown, 1 = cat, 0 = dog. Xs = torch.Tensor([[0, 1], [1, 1], [1, 0], [1, 1], [1, 1], [0, 1], [1, 1], [0, 0], [1, 0]]) ys = torch.Tensor([[1], [0], [0], [1], [0], [1], [0], [1], [1]]) i = 0 for x in Xs: output = model(x) print(output) loss = F.nll_loss(output, ys[i]) print(loss)
The program keeps giving me this error:
Expected 2 or more dimensions (got 1)
Can anyone explain what is wrong with my code?
Advertisement
Answer
The tensor you use as the dataset, Xs
is shaped (n, 2)
. So when looping over it each element x
ends up as a 1D tensor shaped (2,)
. However, your module expects a batched tensor as input, i.e. here a 2D tensor shaped (n, 2)
, just like Xs
. You have two possible options, either use a data loader and divide your dataset into batches, or unsqueeze your input x
to make it two dimensional shaped (1, 2)
.
Using a
TensorDataset
and wrapping it with aDataLoader
:>>> dataset = TensorDataset(Xs, ys) >>> dataloader = Dataloader(dataset, batch_size=4)
Then iterating over
dataloader
will return batches of fours (inputs and corresponding labels):>>> for x, y in dataloader: ... output = model(x) ... loss = F.nll_loss(output, y)
TensorDataset
andDataloader
are both imported fromtorch.utils.data
.Or use
torch.Tensor.unsqueeze
onx
to add one extra dimension:>>> for x, y in zip(Xs, ys): ... output = model(x.unsqueeze()) ... loss = F.nll_loss(output, y)
Alternatively, you can do
x[None]
which has the same effect.