Which implementation performs mini-batch gradient descent correctly?

Audrey: <p>Hello, I want to implement such mini-batch gradient descent step below:</p>
<p><div class="lightbox-wrapper"><a class="lightbox" href="https://discuss.pytorch.org/uploads/default/original/3X/6/c/6cda2394c9c656f9e324720c3e945bbb2cf4389e.jpeg" data-download-href="https://discuss.pytorch.org/uploads/default/6cda2394c9c656f9e324720c3e945bbb2cf4389e" title="%E6%89%B9%E6%B3%A8%202019-11-12%20091432"><img src="https://discuss.pytorch.org/uploads/default/optimized/3X/6/c/6cda2394c9c656f9e324720c3e945bbb2cf4389e_2_517x44.jpeg" alt="%E6%89%B9%E6%B3%A8%202019-11-12%20091432" data-base62-sha1="fwWVv4eYHEd34EVQthXuDiNLNjE" width="517" height="44" srcset="https://discuss.pytorch.org/uploads/default/optimized/3X/6/c/6cda2394c9c656f9e324720c3e945bbb2cf4389e_2_517x44.jpeg, https://discuss.pytorch.org/uploads/default/optimized/3X/6/c/6cda2394c9c656f9e324720c3e945bbb2cf4389e_2_775x66.jpeg 1.5x, https://discuss.pytorch.org/uploads/default/original/3X/6/c/6cda2394c9c656f9e324720c3e945bbb2cf4389e.jpeg 2x" data-dominant-color="F3F3F3"><div class="meta"><svg class="fa d-icon d-icon-far-image svg-icon" aria-hidden="true"><use href="#far-image"></use></svg><span class="filename">%E6%89%B9%E6%B3%A8%202019-11-12%20091432</span><span class="informations">817×71 12.4 KB</span><svg class="fa d-icon d-icon-discourse-expand svg-icon" aria-hidden="true"><use href="#discourse-expand"></use></svg></div></a></div><br>
where <em>d(h+l,t)</em> is the distance of two vector <strong>h+l</strong> and <strong>t</strong>. <em>y</em> is the margin and [·]+ is the maximun of 0 and the value inside it.</p>
<p>Now I have two implementations of this and they behave differently. But I don’t know which one is correct for this algorithm above.</p>
<ul>
<li>Version 1 : Get a list of losses of mini-batch samples, and perform .backward() on loss.mean()</li>
</ul>
<pre data-code-wrap="python"><code class="lang-python">class Model():
    ...
   def forward(self, p_h, p_l, p_t, n_h, n_l, n_t):
         dis1 = (self.entity_em(p_h) + self.relation_em(p_l) - self.entity_emb(p_t)).norm(p=2, dim=1)
         dis2 = (self.entity_em(n_h) + self.relation_em(n_l) - self.entity_emb(n_t)).norm(p=2, dim=1)
         return self.loss(dis1, dis2)
   def loss(self, dis1, dis2):
         target = torch.tensor([-1])
         criterion = nn.MarginRankingLoss(margin=gamma, reduction='none')
         return criterion(dis1, dis2, target)
   ...
model = Model()
for batch_index in ... : # mini-batch loop
   optimizer.zero_grad()
   loss = model(p_h, p_l, p_t, n_h, n_l, n_t)
   total_loss += loss.sum().item()
   loss.mean().backward()
   optimizer.step()
</code></pre>
<ul>
<li>Version 2 : Get the sum of losses of mini-batch samples and perform .backward() on loss</li>
</ul>
<pre><code class="lang-auto">class Model():
    ...
   def forward(self, p_h, p_l, p_t, n_h, n_l, n_t):
         dis1 = (self.entity_em(p_h) + self.relation_em(p_l) - self.entity_emb(p_t)).norm(p=2, dim=1)
         dis2 = (self.entity_em(n_h) + self.relation_em(n_l) - self.entity_emb(n_t)).norm(p=2, dim=1)
         dis_diff = self.gamma + dis1 - dis2
         result = torch.sum(F.relu(distance_diff))
         return result
   ...
model = Model()
for batch_index in ... : # mini-batch loop
   optimizer.zero_grad()
   loss = model(p_h, p_l, p_t, n_h, n_l, n_t)
   total_loss += loss.item()
   loss.backward()
   optimizer.step()
</code></pre>
<p>So which one should I use and why?</p>