Recently I observed that a lot of times while defining the neural nets we define separate ReLU objects for each layer. Why can't we use the same ReLU object wherever it is needed.
For example instead of writing like this-
def __init__(self):
self.fc1 = nn.Linear(784, 500)
self.ReLU_1 = nn.ReLU()
self.fc2 = nn.Linear(500, 300)
self.ReLU_2 = nn.ReLU()
def forward(x):
x = self.fc1(x)
x = self.ReLU_1(x)
x = self.fc2(x)
x = self.ReLU_2(x)
why can't we use
def __init__(self):
self.fc1 = nn.Linear(784, 500)
self.ReLU = nn.ReLU()
self.fc2 = nn.Linear(500, 300)
def forward(x):
x = self.fc1(x)
x = self.ReLU(x)
x = self.fc2(x)
x = self.ReLU(x)
Is this something specific to PyTorch?
We can do so. First variant is just for clarity.
Related
I am getting the following error:
RuntimeError: mat1 and mat2 shapes cannot be multiplied (32x33856 and 640000x256)
I don't understand how do I need to change the parameters of my net. I took the net created in this paper and tried to modify the parameters to meet my needs.This is the code, I changed the parameters of the first convolution but still get the error:
class ChordClassificationNetwork(nn.Module):
def __init__(self, train_model=False):
super(ChordClassificationNetwork, self).__init__()
self.train_model = train_model
self.flatten = nn.Flatten()
self.firstConv = nn.Conv2d(3, 64, (3, 3))
self.secondConv = nn.Conv2d(64, 64, (3, 3))
self.pool = nn.MaxPool2d(2)
self.drop = nn.Dropout(0.25)
self.fc1 = nn.Linear(100*100*64, 256)
self.fc2 = nn.Linear(256, 256)
self.outLayer = nn.Linear(256, 7)
def forward(self, x):
x = self.firstConv(x)
x = F.relu(x)
x = self.pool(x)
x = self.secondConv(x)
x = F.relu(x)
x = self.pool(x)
x = self.drop(x)
x = self.flatten(x)
x = self.fc1(x)
x = F.relu(x)
x = self.drop(x)
x = self.fc2(x)
x = F.relu(x)
x = self.drop(x)
x = self.outLayer(x)
output = F.softmax(x, dim=1)
return output
and this is the training file:
device = ("cuda" if torch.cuda.is_available() else "cpu")
transformations = transforms.Compose([
transforms.Resize((100, 100))
])
num_epochs = 10
learning_rate = 0.001
train_CNN = False
batch_size = 32
shuffle = True
pin_memory = True
num_workers = 1
dataset = GuitarDataset("../chords_data/cropped_images/train", transform=transformations)
train_set, validation_set = torch.utils.data.random_split(dataset, [int(0.8 * len(dataset)), len(dataset) - int(0.8*len(dataset))])
train_loader = DataLoader(dataset=train_set, shuffle=shuffle, batch_size=batch_size, num_workers=num_workers,
pin_memory=pin_memory)
validation_loader = DataLoader(dataset=validation_set, shuffle=shuffle, batch_size=batch_size, num_workers=num_workers,
pin_memory=pin_memory)
model = ChordClassificationNetwork().to(device)
criterion = nn.BCELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=learning_rate)
def check_accuracy(loader, model):
if loader == train_loader:
print("Checking accuracy on training data")
else:
print("Checking accuracy on validation data")
num_correct = 0
num_samples = 0
model.eval()
with torch.no_grad():
for x, y in loader:
x = x.to(device=device)
y = y.to(device=device)
scores = model(x)
predictions = torch.tensor([1.0 if i >= 0.5 else 0.0 for i in scores]).to(device)
num_correct += (predictions == y).sum()
num_samples += predictions.size(0)
print(
f"Got {num_correct} / {num_samples} with accuracy {float(num_correct) / float(num_samples) * 100:.2f}"
)
return f"{float(num_correct) / float(num_samples) * 100:.2f}"
def train():
model.train()
for epoch in range(num_epochs):
loop = tqdm(train_loader, total=len(train_loader), leave=True)
if epoch % 2 == 0:
loop.set_postfix(val_acc=check_accuracy(validation_loader, model))
for imgs, labels in loop:
imgs = imgs.to(device)
labels = labels.to(device)
outputs = model(imgs)
loss = criterion(outputs, labels)
optimizer.zero_grad()
loss.backward()
optimizer.step()
loop.set_description(f"Epoch [{epoch}/{num_epochs}]")
loop.set_postfix(loss=loss.item())
if __name__ == "__main__":
train()
What am I doing wrong?
Look at the error message, the issue comes from the fc1 layer which doesn't have the required number of neurons. It is receiving a tensor of shape (batch_size, 33856) but expects (batch_size, 640000). The reduction in dimensionality is caused by the different layers you have applied to your input tensor before fc1.
You can fix this by defining fc1 with:
self.fc1 = nn.Linear(33856, 256)
Alternatively, you can use nn.LazyLinear which will initialize its weights with the appropriate number of neurons at runtime depending on the input it receives. But that's lazy:
self.fc1 = nn.LazyLinear(256)
My Neural Network takes 1000 epochs just to solve XOR and when I increase number of neurons loss increases and it doesnt work.
Also before when I was using np.random.rand it did'nt work with a learning rate less than 1.
import numpy as np
input = np.array([[0, 1] ,[1, 0], [1, 1], [0, 0]])
labels = np.array([[1], [1], [0], [0]])
np.random.seed(0)
class NN:
def __init__(self):
self.layers = []
def add(self, layer):
self.layers.append(layer)
def loss(self, layer):
self.loss = layer
def predict(self, input):
output = input
for layer in self.layers:
output = layer.forward(output)
return output
def train(self, input, labels):
prediction = self.predict(input)
loss = self.loss.forward(prediction, labels)
gradient = self.loss.back() * 0.1
for layer in self.layers[::-1]:
gradient = layer.back(gradient)
return loss
Dense Layer
class Dense:
def __init__(self, input_size, output_size):
self.weights = np.random.randn(input_size, output_size) - 0.5
self.bias = np.random.randn(1, output_size) - 0.5
def forward(self, input):
self.input = input
output = np.dot(input, self.weights) + self.bias
return output
def back(self, gradient):
gradientW = np.dot(self.input.T, gradient)
self.weights -= gradientW
self.bias -= np.mean(gradient)
return np.dot(gradient, self.weights.T)
Sigmoid
class Sigmoid:
def forward(self, input):
output = 1 / (1+np.exp(-input))
self.output = output
return output
def back(self, gradient):
output = self.output * (1 - self.output)
gradient *= output
return gradient
I am using Mean Squaresd Error
class MSE:
def forward(self, input, labels):
self.input = input
self.labels = labels
return np.mean((labels - input)**2)
def back(self):
output = 2 * (self.input - self.labels)
return output
Calling the Class
N = NN()
N.add(Dense(2, 10))
N.add(Sigmoid())
N.add(Dense(10, 1))
N.add(Sigmoid())
N.loss(MSE())
Training
for i in range(1000):
loss = (N.train(input, labels))
if i%99==0:
print(loss)
print(N.predict(input))
Edit: I Tried this and now it works with 100 epochs. I needed an additional layer to increase neurons why? I tried to train it on AND but it doesnt work.
N = NN()
N.add(Dense(2, 50))
N.add(Sigmoid())
N.add(Dense(50, 1000))
N.add(Sigmoid())
N.add(Dense(1000, 50))
N.add(Sigmoid())
N.add(Dense(50, 1))
N.add(Sigmoid())
N.loss(MSE())
I code this neural network to make a gaussian regression but I don't understand why my loss doesn't change through epochs. I set the learning rate to 1 to see the loss decreases but it does not. I chose to take 2000 poitns to train my Neural network. I watched several algorithms on this website and I don't really understand why my algorithm do not achieve what I expect.
I have already imported all libraries needed.
Thank you for your help
def f(x):
return x * np.sin(x) # function to predict
m =2000
X_bis = np.zeros((1,m),dtype = float)
X_bis=np.random.random(m)*10
## Create my training,validation and test set
X_train = X_bis[0:600]
X_val = X_bis[600:800]
X_test = X_bis[800:]
y_train = f(X_train)
y_val = f(X_val)
y_test = f(X_test)
mean_X_train = np.mean(X_train)
std_X_train = np.std(X_train)
mean_y_train = np.mean(y_train)
std_y_train =np.std(y_train)
class MyDataset(data.Dataset):
def __init__(self, data_feature, data_target):
self.data_feature = data_feature
self.data_target = data_target
def __len__(self):
return len(self.data_feature)
def __getitem__(self, index):
X_train_normalized = (self.data_feature[index] - mean_X_train) / std_X_train
y_train_normalized = (self.data_target[index] - mean_y_train) / std_y_train
return torch.from_numpy(np.array(X_train_normalized,ndmin=1)).float(), torch.from_numpy(np.array(y_train_normalized, ndmin = 1)).float()
training_set = MyDataset(X_train,y_train)
train_loading = torch.utils.data.DataLoader(training_set, batch_size= 100)
val_set = MyDataset(X_val, y_val)
val_loading = torch.utils.data.DataLoader(val_set, batch_size= 10)
test_set = MyDataset(X_test,y_test)
test_loading = torch.utils.data.DataLoader(test_set, batch_size= 100)
class Net(nn.Module):
def __init__(self):
super(Net, self).__init__()
self.FC1 = nn.Linear(1,10)
self.FC2 = nn.Linear(10, 1)
def forward(self, x):
x = F.relu(self.FC1(x))
x = self.FC2(x)
return x
model = Net()
criterion = nn.MSELoss()
optimizer = torch.optim.SGD(model.parameters(),
lr=1, weight_decay= 0.01, momentum = 0.9)
def train(net, train_loader, optimizer, epoch):
net.train()
total_loss=0
for idx,(data, target) in enumerate(train_loader, 0):
outputs = net(data)
loss = criterion(outputs,target)
total_loss +=loss.cpu().item()
optimizer.step()
print('Epoch:', epoch , 'average training loss ', total_loss/ len(train_loader))
def test(net,test_loader):
net.eval()
total_loss = 0
for idx,(data, target) in enumerate(test_loader,0):
outputs = net(data)
outputs = outputs * std_X_train + mean_X_train
target = target * std_y_train + mean_y_train
loss = criterion(outputs,target)
total_loss += sqrt(loss.cpu().item())
print('average testing loss', total_loss/len(test_loader))
for epoch in range(50):
train(model,train_loading,optimizer,epoch)
test(model,val_loading)
'''
I'm wondering why you don't have loss.backward() after the line that you compute the loss (i.e., loss = criterion(outputs,target)) in your training snippet. This will help backpropagating and ultimately updating the parameters of your network upon optimizer.step(). Also, try using lower learning rates as lr=1 normally is too much in training such networks. Try using learning rates in between 0.001-0.01 to see if your network is learning the mapping between input X and target Y.
i buit from scratch the perceptron class in python, and now i'm trying to make the animated visualization of the decision boundary in every iteration of the learning process.The problem is that my code doesn't works, cuz looks like the "animation_func" is not called, i don't know why. can you help me.
class Perceptron:
def __init__(self,X=None, y=None,lr=0.001, niter=1000):
self.lr = lr
self.niter = niter
self.w = None
self.b = None
def fit(self,X,y):
for indice,X_i in enumerate(X):
self.w += self.lr*(y_[indice]-self.predic(X_i))* X_i
def animar_perceptron(self,X,y,niter):
samples,features = X.shape
self.w = np.zeros(features)
self.b = 0
y_ = np.array([1 if i>0 else 0 for i in y])
x0_1 = np.amin(X[:,0])
x0_2 = np.amax(X[:,0])
ymin = np.amin(X[:,1])
ymax= np.amax(X[:1])
fig, ax = plt.subplots()
ax.scatter(X[:,0], X[:,1],marker='o', c=y )
boundary, =ax.plot([X0_1, X0_2],[0, 0],'k')
def animation_func(_):
self.fit(X,y)
x1_1 = (-self.w[0]*x0_1-self.b )/self.w[1]
x1_2 = (-self.w[0]*x0_2-self.b )/self.w[1]
boundary.set_ydata([x1_1,x1_2])
return boundary,
return FuncAnimation(fig, func=animation_func, frames=np.arange(1,niter), interval=50)
def predic(self, X):
y_hat = np.dot(X,self.w) + self.b
y_hat =self.activate_fun(y_hat)
return y_hat
def activate_fun(self,z):
return np.where(z>0, 1,0)
def score(self, y_true, y_pred):
accuracy = np.sum(y_true == y_pred)/len(y_true)
return accuracy
p = Perceptron()
animacion = animar_perceptron(X,y,1000)
Using this model I'm attempting to initialise my network with my predefined weights and bias :
dimensions_input = 10
hidden_layer_nodes = 5
output_dimension = 10
class Model(torch.nn.Module):
def __init__(self):
super(Model, self).__init__()
self.linear = torch.nn.Linear(dimensions_input,hidden_layer_nodes)
self.linear2 = torch.nn.Linear(hidden_layer_nodes,output_dimension)
self.linear.weight = torch.nn.Parameter(torch.zeros(dimensions_input,hidden_layer_nodes))
self.linear.bias = torch.nn.Parameter(torch.ones(hidden_layer_nodes))
self.linear2.weight = torch.nn.Parameter(torch.zeros(dimensions_input,hidden_layer_nodes))
self.linear2.bias = torch.nn.Parameter(torch.ones(hidden_layer_nodes))
def forward(self, x):
l_out1 = self.linear(x)
y_pred = self.linear2(l_out1)
return y_pred
model = Model()
criterion = torch.nn.MSELoss(size_average = False)
optim = torch.optim.SGD(model.parameters(), lr = 0.00001)
def train_model():
y_data = x_data.clone()
for i in range(10000):
y_pred = model(x_data)
loss = criterion(y_pred, y_data)
if i % 5000 == 0:
print(loss)
optim.zero_grad()
loss.backward()
optim.step()
RuntimeError:
The expanded size of the tensor (10) must match the existing size (5)
at non-singleton dimension 1
My dimensions appear correct as they match the corresponding linear layers ?
The code provided doesn't run due to the fact that x_data isn't defined, so I can't be sure that this is the issue, but one thing that strikes me is that you should replace
self.linear2.weight = torch.nn.Parameter(torch.zeros(dimensions_input,hidden_layer_nodes))
self.linear2.bias = torch.nn.Parameter(torch.ones(hidden_layer_nodes))
with
self.linear2.weight = torch.nn.Parameter(torch.zeros(hidden_layer_nodes, output_dimension))
self.linear2.bias = torch.nn.Parameter(torch.ones(output_dimension))