Hi, sorry for the short reply.
WRT your code you should perform the following:
model=VGG16Conv()
model = model.to(dev) # It's  not in-place, thus, your have to write model=model.to(dev)
opt=optim.SGD(model.parameters(), lr=l_r)

train_ds = TensorDataset(x_train_, y_train)
train_dl = DataLoader(train_ds, batch_size=bs, shuffle=True)
valid_ds = TensorDataset(x_valid_, y_valid)
valid_dl = DataLoader(valid_ds, batch_size=bs * 2)

for epoch in range(epochs):
    print('EPOCH ', epoch)
    for xb, yb in train_dl:
        for sub in range(1,4):
            loss=loss_func(model.feedforward(xb.to(dev), sub),yb.to(dev)) #Allocate input samples, not 
            #dataloader itself :slight_smile: 
            # YOu may have to allocate also sub, depending on what it does in your model
            loss.backward()
            self.plot_grad_flow()
            opt.step()
            opt.zero_grad()

You don’t have to allocate the dataloader but loaded samples
In this specific case, you don’t have to “allocate the loss” as you are using the functional version. It means that it behaves like a function. Its  nn.Module counterpart is a class. If you use the class version you should also allocate it.
In case of validation it’s the same. Allocate inputs as in training.
Lastly, the typical way of doing forward pass is calling model directly (once it’s been instantiated). You can simple do model(x,sub). You may review if the feedforward method calls model.forward function.
If you get an error like, input 1 is type torch.float and input 2 is type cuda.float (something like that), it means there is something not allocated in the gpu.