How are losses aggregated over multiple computed batches?

tal123: <p>According to <a href="https://discuss.pytorch.org/t/virtual-batches-of-sgd-optimization/157964">this</a> and <a href="https://discuss.pytorch.org/t/why-do-we-need-to-set-the-gradients-manually-to-zero-in-pytorch/4903/20">this</a> posts, it is possible to simulate a large SGD batch size by executing multiple smaller batches, while calling the loss + <code>loss.backward()</code> on each of them, and only finally calling <code>optimizer.step()</code> - see below the quoted code from the original post.</p>
<p>The question is regarding the optimization step: So, our big batch consists of many small batches that were computed one by one. Furthermore, each small batch had its gradient computed separately - so before applying the optimization step of the big batch, there are many gradient vectors to aggregate into a single gradient vector. <strong>How does it aggregate them (average, sum)?</strong> It is a very important detail to know in order to determine the learning rate.</p>
<p><strong>Update</strong>: If I understand it correctly, according to experiments that I have conducted (and answers by other users to this question), the gradient is aggregated using <strong>sum</strong>. This means that the code sample below could be somewhat misleading -  users may want to change their code such that each batch’s loss will be multiplied by its relative size. Since the below example uses 10 “small batches”, the loss should typically be multiplied by <code>0.1</code> for each small batch: <code>loss = crit(pred, target) * 1/10.0</code>. Otherwise, the learning rate should be adjusted to comply with the fact that the gradient has the size of 10 summed gradients, which is the same as using a 10x higher learning rate.</p>
<aside class="quote no-group" data-username="albanD" data-post="20" data-topic="4903">
<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/alband/48/215_2.png" class="avatar"><a href="https://discuss.pytorch.org/t/why-do-we-need-to-set-the-gradients-manually-to-zero-in-pytorch/4903/20">Why do we need to set the gradients manually to zero in pytorch?</a></div>
<blockquote>
<pre><code class="lang-auto"># some code
# Initialize dataset with batch size 10
opt.zero_grad()
for i, (input, target) in enumerate(dataset):
    pred = net(input)
    loss = crit(pred, target)
    # one graph is created here
    loss.backward()
    # graph is cleared here
    if (i+1)%10 == 0:
        # every 10 iterations of batches of size 10
        opt.step()
        opt.zero_grad()
</code></pre>
</blockquote>
</aside>

eqy: <p>You can do a simple litmus test for this by trying some computation with known constant grads (e.g., addition).</p>
<pre><code class="lang-auto">&gt;&gt;&gt; import torch
&gt;&gt;&gt; a = torch.ones(3,3, requires_grad=True)
&gt;&gt;&gt; a.grad
&gt;&gt;&gt; a.sum().backward()
&gt;&gt;&gt; a.grad
tensor([[1., 1., 1.],
        [1., 1., 1.],
        [1., 1., 1.]])
&gt;&gt;&gt; a.sum().backward()
&gt;&gt;&gt; a.grad
tensor([[2., 2., 2.],
        [2., 2., 2.],
        [2., 2., 2.]])
&gt;&gt;&gt;
</code></pre>
<p>It is doing a sum of the gradients for each backward.</p>