After calling, .backward(), I think you can iterate over model parameters and collect their gradients. Then you can modify them, and call the optimizer.step() as usual. That’s what comes to my mind at least.
And if you’re simply weighting training data instances, you can multiply the loss function rather than directly modifying the gradients.