thank you very much !
I have changed the code you sent me so as to fit my problem.
my problem is not to train the net parameters, as in the code you sent, but rather to “train” the input.
in other words, after having trained my net, I want to find the input that will give maximum output.
the chages I did are as follows:

I added ‘requires grad’ to the input
I changed the loss to be ‘-output’ (the output with minus sign) because I’m looking the maximum output
Instead of updating the parameters (w1, w2 in the example) I’m updating the input (x in the example)
here is the code with my changes:

I workes well.
however, what I want to do now is to load my pre-trained net and then instead of:
y_pred = x.mm(w1).clamp(min=0).mm(w2)
I will have:
y_pred = net(x)
however, this does not work for some reason. meaning, even after the ‘.backward()’ command the ‘.grad’ of ‘x’ remains ‘None’. note this does not happen if I do:
y_pred = x.mm(w1).clamp(min=0).mm(w2)
!!!
very strange…
I don’t understand why with these ‘.mm’ commands the ‘.grad’ of inputs is being calculated and saved and with ‘net()’ it isn’t happening
here is what my net looks like (it has 3 hidden layers, input layer size is 11, output layer size is 1, all 3 middle layers have a size of 100):
class non_linear_Net_3_hidden(nn.Module):
    def init(self):
        super(non_linear_Net_3_hidden, self).init()
        self.fc1 = nn.Linear(input_layer_size, middle_layer_size)
        self.fc2 = nn.Linear(middle_layer_size, middle_layer_size)
        self.fc4 = nn.Linear(middle_layer_size, middle_layer_size)
        self.fc3 = nn.Linear(middle_layer_size, final_layer_size)
    def forward(self, x):
        x = F.sigmoid(self.fc1(x))
        x = F.sigmoid(self.fc2(x))
        x = F.sigmoid(self.fc4(x))
        x = self.fc3(x)
        return x