How to backward the average of multiple losses?

username: ysleer
cooked: <p>I am trying to train a model using multiple data loaders.</p>
<p>The code I use is as follows:</p>
<pre><code class="lang-auto">loss_list = list()
    for epoch in range(cfg.start_epoch, cfg.max_epoch):
        batch_time = AverageMeter()
        data_time = AverageMeter()
        losses = AverageMeter()
        losses_exist = AverageMeter()

        print("Train Epoch: {}".format(epoch))

        model.train()

        end = time.time()
        for i in range(len(train_loader_list)):
            train_loader = train_loader_list[i]
            for batch_idx, sample in enumerate(train_loader):
                data_time.update(time.time() - end)

                optimizer.zero_grad()
                model.zero_grad()

                input = torch.autograd.Variable(sample['image'].cuda())

                target = torch.autograd.Variable(sample['label'].cuda())
                target_exist = torch.autograd.Variable(sample['exist'].cuda())

                output, output_exist = model(input)  # output_mid
                loss_seg = criterion(torch.nn.functional.log_softmax(output, dim=1), target)
                loss_exist = criterion_exist(output_exist, target_exist)
                loss = loss_seg + loss_exist * 0.1

                losses.update(loss.data.item(), input.size(0))
                losses_exist.update(loss_exist.item(), input.size(0))

                # optimizer.zero_grad()
                loss.backward(retain_graph=True)
                optimizer.step()

                # scheduler.step()

                # measure elapsed time
                batch_time.update(time.time() - end)
                end = time.time()
               

                if batch_idx == len(train_loader) - 1:
                    loss_list.append(loss)

        for loss_sample in loss_list:
            loss += loss_sample.item()

        loss_tot = loss / len(loss_list)

        optimizer.zero_grad()
        loss_tot.backward()
        optimizer.step()
</code></pre>
<p>I don’t know why this doesn’t work.</p>
<p>I get an error in the backward part.</p>
<p>I searched many places but couldn’t find the answer.</p>
<p>Helpme.</p>

username: Dwight_Foster
cooked: <p>What exactly is the error?</p>

username: ysleer
cooked: <p>Thank you for answer.</p>
<p>The error is as follows:<br>
“RuntimeError: one of the variables needed for gradient computation has been modified by an inplace operation: [torch.cuda.FloatTensor [128, 4]], which is output 0 of TBackward, is at version 106; expected version 105 instead. Hint: enable anomaly detection to find the operation that failed to compute its gradient, with torch.autograd.set_detect_anomaly(True)”.</p>

username: Dwight_Foster
cooked: <p>So I assume the error is with adding the loss. Can you try removing the * 0.1 and seeing if it helps.</p>

username: ysleer
cooked: <p>I get the same error.</p>
<p>We are replicating one model as much as the data loader to be used and training it with multiple data loaders.</p>
<p>When I thought about it, I didn’t know which model to update, so I thought I got an error. Does this also make sense?</p>

username: xian_kgx
cooked: <p>I guess you just need to concat the various dataloaders. Drop these:</p>
<pre><code class="lang-auto">loss_tot = loss / len(loss_list)

optimizer.zero_grad()
loss_tot.backward()
optimizer.step()
</code></pre>

username: ysleer
cooked: <p>Thank you for your reply.</p>
<p>But I didn’t understand the answer.</p>
<p>How do I update the average loss of each data loader loss if I proceed according to the answers you provided??</p>
<p>Also, what is the connection between connecting the data loader and deleting the part of the answer??</p>

username: xian_kgx
cooked: <p>It depends on what do you want to do with the loss.</p>
<p>Do you just need the value so you know what the average for the dataloaders are? Or is it something else? More particularly, I don’t understand you you to backward the loss_tot.</p>
<p>If you look at how it works, I think loss_tot will be loss of the last batch of the last dataloader + losses of the last batches of the dataloaders. It doesn’t make sense.</p>

username: ysleer
cooked: <p>Thank you for answer.</p>
<p>To explain what I want to do, the approximate process is as follows.</p>
<p><div class="lightbox-wrapper"><a class="lightbox" href="https://discuss.pytorch.org/uploads/default/original/3X/3/6/36b70e42345eed2e7861cf1fc5a46dc0ecf0eaaa.png" data-download-href="https://discuss.pytorch.org/uploads/default/36b70e42345eed2e7861cf1fc5a46dc0ecf0eaaa" title="스크린샷, 2021-03-10 11-44-43"><img src="https://discuss.pytorch.org/uploads/default/original/3X/3/6/36b70e42345eed2e7861cf1fc5a46dc0ecf0eaaa.png" alt="스크린샷, 2021-03-10 11-44-43" data-base62-sha1="7O1YF4JMEG1bJS5Cu4yGxPX4fsS" width="560" height="500" data-dominant-color="F7F7F8"><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">스크린샷, 2021-03-10 11-44-43</span><span class="informations">603×538 15.1 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></p>
<p>In the end, you want to update using the average of each data loader’s losses.</p>
<p>Isn’t this structure a proper structure??</p>

username: xian_kgx
cooked: <p>Usually NN models are trained using mini-batches. That’s why I suggest to just drop the mean loss backward part. With your code, you are trying to train with BOTH mini batches (the inner loss backward) AND also dataset/dataloader wise (once every len(dataloader)) (outer total_loss backward). This is not consistent in that you have so much more mini batches than datasets/dataloaders and you end up having those dataset/dataloader updates having little significance.</p>
<p>If you insist to do averaging, perhaps you can do zipping of the datasets, then in each batch, calculate the loss for each of the batch from difference datasets and then averaging the loss and backward.</p>

username: xian_kgx
cooked: <p>You can zip multiple datasets like this: <a href="https://discuss.pytorch.org/t/two-dataloaders-from-two-different-datasets-within-the-same-loop/87766/5" class="inline-onebox">Two DataLoaders from two different datasets within the same loop - #5 by Joshua_Clancy</a></p>

username: ysleer
cooked: <p>Thank you for your kind explanation.</p>
<p>I will also refer to the explanation related to zip.</p>
<p>I think integrating the dataloader is an efficient way. I tried, but the data loaders I made have different image sizes and batch sizes. So the integration failed.</p>
<p>In addition, is there a way to learn the input size and batch size differently, or is there an example that I can refer to?</p>
<p>For example,<br>
multi_scale = [(1025, 512), (512, 256), (256, 128)]<br>
multi_batch = [3, 4, 12]</p>
<p>After setting as follows, I would like to configure the batch size according to the input size.</p>
<p>I couldn’t find a way to integrate it so I configured the dataloader differently.</p>
<p>Is there a good way??</p>

username: xian_kgx
cooked: <p>So you wanted to do is multi-scale training?</p>
<p>Then perhaps you could do:</p>
<pre><code class="lang-auto">for batch1, batch2, batch3 in zip(daloaders[0], dataloaders[1], dataloaders[2]):
    input1, label1 = batch1
    input2, label2 = batch2
    input3, label3 = batch3

    pred1 = model(input1)
    pred2 = model(input2)
    pred3 = model(input3)
    loss1 = criterion(pred1, label1)
    loss2 = criterion(pred2, label2)
    loss3 = criterion(pred3, label3)
    loss = loss1 + loss2 + loss3
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
</code></pre>