Hello @hkz,
Thank you for surfacing this quirk.
Opacus does indeed override the optimizer.step() when privacy engine is attached to it. In the current implementation, we perform the per-sample gradient clipping and subsequently call the original step() function of the optimizer (opacus/privacy_engine.py at master · pytorch/opacus · GitHub 1). Therefore, your code should work correctly regardless of when you initialize the scheduler.
However, this is risky as it might not work correctly should the implementation of optimizer.step() change in a manner inconsistent with the scheduler’s expectations; although, I don’t see this happening.
Bottom line: heeding the warning is ideal and recommended.