Hi,
The problem is with the fact that you use .data. You should not use .data anymore.
There were 2 possible use case for .data and their new versions are:
If you want to do ops that are not registered by the autograd engine, use with torch.no_grad():. If you want to break the computational graph to prevent gradients from flowing back, use .detach().
You will see that what you try to do is not a valid use of .data.  And in particular, you hide the fact that you changed the weights from the autograd engine.
You will need to do the computation of U and changing the weights inside your forward pass.
Also Linear layers are not built to be used this way and so will prevent you from making their .weight something else than an nn.Parameter. I guess the simplest here is to do self.hidden1.weight.copy_(torch.ger(self.u, self.u)) in your forward pass and keep the requires_grad=False in the __init__ function.