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
TensorDatasetand wrapping it with aDataLoader:>>> dataset = TensorDataset(Xs, ys) >>> dataloader = Dataloader(dataset, batch_size=4)
Then iterating over
dataloaderwill return batches of fours (inputs and corresponding labels):>>> for x, y in dataloader: ... output = model(x) ... loss = F.nll_loss(output, y)
TensorDatasetandDataloaderare both imported fromtorch.utils.data.Or use
torch.Tensor.unsqueezeonxto 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.