Source code for gradient clipping and noise addition in Opacus

username: Chandan_Tankala
cooked: <p>Hello, I believe Opacus has the functionality for clipping the l2-norm of per-sample gradients, then averaging the clipped gradients, and finally adding Gaussian noise to the average of per-sample gradients. Can someone provide me the source code for that?</p>
<p>I have tried looking on <a href="https://opacus.ai/api/privacy_engine.html" class="inline-onebox" rel="noopener nofollow ugc">Opacus · Train PyTorch models with Differential Privacy</a>. I am using the “privacy_engine.make_private_with_epsilon()” function which has a parameter “max_grad_norm”, but I am not sure where I can find the source code where clipping and average of gradients is computed. I believe <a href="https://opacus.ai/api/grad_sample_module.html" class="inline-onebox" rel="noopener nofollow ugc">Opacus · Train PyTorch models with Differential Privacy</a> provides source code for how per sample gradients are computed. But again I could not find the source code for clipping of l2 norm of gradients, averaging of gradients, and noise addition.</p>
<p>Any help is appreciated! Thanks.</p>

username: Soumya_Kundu
cooked: <p>In  <a href="https://github.com/pytorch/opacus/blob/36f7a34c904af228b2ec2f0e727b64fc55cbd98c/opacus/privacy_engine.py#L30" rel="noopener nofollow ugc">line 301 of <code>def make_private(</code></a> :         - [Optimizer is now responsible for gradient clipping and adding noise to the gradients.]</p>
<ul>
<li>
<p>Gradient Clipping: <a href="https://github.com/pytorch/opacus/blob/main/opacus/utils/fast_gradient_clipping_utils.py#L23" rel="noopener nofollow ugc"><code>class DPTensorFastGradientClipping</code></a></p>
</li>
<li>
<p>Noise Addition: <a href="https://github.com/pytorch/opacus/blob/main/opacus/schedulers/noise_scheduler.py#L75C1-L75C40" rel="noopener nofollow ugc"><code>class ExponentialNoise(_NoiseScheduler)</code></a></p>
</li>
<li>
<p>Per-Sample Gradients: <a href="https://github.com/pytorch/opacus/blob/36f7a34c904af228b2ec2f0e727b64fc55cbd98c/opacus/grad_sample/grad_sample_module.py#L79" rel="noopener nofollow ugc"><code>class GradSampleModule(AbstractGradSampleModule)</code></a></p>
</li>
<li>
<p><a href="https://github.com/pytorch/opacus/blob/36f7a34c904af228b2ec2f0e727b64fc55cbd98c/opacus/optimizers/optimizer_fast_gradient_clipping.py#L72" rel="noopener nofollow ugc">Averaging:</a> [expected_batch_size: batch_size used for averaging gradients. When using<br>
Poisson sampling averaging denominator can’t be inferred from the<br>
actual batch size. Required is <code>loss_reduction="mean"</code>, ignored if<br>
<code>loss_reduction="sum"</code>]</p>
</li>
</ul>

username: Chandan_Tankala
cooked: <p>Thanks, that was good to see. However, if I use the make_private_with_epsilon() method in PrivacyEngine class, then does the l2 norm of the per-sample gradient get clipped? I do not know which norm gets clipped in the Gradient Clipping link you sent. Also, in this method, I did not find a parameter that accounts for averaging of gradients. Do you know how would the averaging be done if I use this method? I also do not know the noise distribution as I did not find a corresponding parameter in this method. Any thoughts on these questions? Appreciate your time.</p>

username: Soumya_Kundu
cooked: <aside class="quote no-group" data-username="Chandan_Tankala" data-post="3" data-topic="209005">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/chandan_tankala/48/72487_2.png" class="avatar"> Chandan_Tankala:</div>
<blockquote>
<p>However, if I use the make_private_with_epsilon() method in PrivacyEngine class, then does the l2 norm of the per-sample gradient get clipped?</p>
</blockquote>
</aside>
<p>Yes : "<a href="https://github.com/pytorch/opacus/blob/36f7a34c904af228b2ec2f0e727b64fc55cbd98c/tutorials/building_image_classifier.ipynb#L45" rel="noopener nofollow ugc">Max Grad Norm: The maximum L2 norm of per-sample gradients before they are aggregated by the averaging step"</a></p>
<aside class="quote no-group" data-username="Chandan_Tankala" data-post="3" data-topic="209005">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/chandan_tankala/48/72487_2.png" class="avatar"> Chandan_Tankala:</div>
<blockquote>
<p>I did not find a parameter that accounts for averaging of gradients. Do you know how would the averaging be done if I use this method?</p>
</blockquote>
</aside>
<p>Based on the link and the text above, does it not mean that it happens batch wise?</p>
<aside class="quote no-group" data-username="Chandan_Tankala" data-post="3" data-topic="209005">
<div class="title">
<div class="quote-controls"></div>
<img loading="lazy" alt="" width="24" height="24" src="https://discuss.pytorch.org/user_avatar/discuss.pytorch.org/chandan_tankala/48/72487_2.png" class="avatar"> Chandan_Tankala:</div>
<blockquote>
<p>I also do not know the noise distribution as I did not find a corresponding parameter in this method.</p>
</blockquote>
</aside>
<p>Based on <a href="https://opacus.ai/api/privacy_engine.html" rel="noopener nofollow ugc">this</a> – I think gaussian noise?</p>

username: Chandan_Tankala
cooked: <p>Thanks, that is helpful. I had seen this link earlier, but I wasn’t sure if a page from the tutorials means that indeed l2-norm of the per-sample gradient is clipped and these are averaged batch-wise. I am citing the results obtained from this code in a paper and just wanted to be sure.</p>