Try to reuse the layers where the weight sharing happens (e.g. assign the same nn.Linear instance to the model instance). This way you don’t have to copy the layer parameters.
When defining the SGD optimizer, you can define a separate param group for each model type to apply different learning rates to them, etc. Check the docs 2 for that. Since the instances share the parameters, be careful to not pass the same parameter to the optimizer multiple times (it gets modified each time in that case, in PyTorch 1.7 this will raise a warning). To avoid that, you can do something like that:
optimizer = optim.SGD([{'params': list(set(itertools.chain(instanceA.parameters(), instanceB.parameters(), ...)), 
                        'lr': ...},
                      ], ...)