Processing batches efficiently

sugh7020: <p>I have a portion of my code as:</p>
<pre><code class="lang-auto">def DepthError(depth_pred, depth_gt):
    L_d, Mcard = 0.0, 0
    B, c, H, W = depth_pred.shape #batch, channels, height, width
    for b in range(B): #B is batch size, iterating over the images in a batch
        depth_pred2D = depth_pred[b][0] # bth depth image, depth images have 1 channel thus 0
        depth_gt2D = depth_gt[b][0]
        for h in range(H): # iterate over pixels along height
            for w in range(W):
                if depth_gt2D[h][w] &lt;= 0:
                    continue
                Mcard += 1
                diff = torch.sub(depth_pred2D[h][w], depth_gt2D[h][w])
                L_d += torch.abs(diff)
    L_d = torch.div(L_d, Mcard)
    return L_d #return depth loss

train_data = next(iter(train_dataloader))
image = train_data['image'].cuda()
depth_pred = depth_net(image) #estimate depth by passing image through network
L_d = DepthError(depth_pred, depth_gt) #depth loss
</code></pre>
<p>My code seems to be terribly slow, also I am trying to overfit to one batch by setting batch size to be 10. But my loss seems to be stuck at the same value and is not decreasing.<br>
Is the above method the right way to process images in a batch. Also, am I doing things correctly?</p>
<p>Thanks!</p>

Napam: <p>Hi, your problem seems to be easily <a href="https://pytorch.org/docs/stable/notes/broadcasting.html" rel="noopener nofollow ugc">“broadcastable”</a>! <img src="https://discuss.pytorch.org/images/emoji/apple/grin.png?v=9" title=":grin:" class="emoji" alt=":grin:"> Using broadcasting and such is much faster than looping in Python. From my understanding you want to do L1-loss (with some scaling), where you exclude the loss caused from negative depth values in the ground truth.</p>
<p>Here is my attempt at implementing the loss, I tested with some dummy data, and our results agree.</p>
<pre><code class="lang-python">import torch 

def DepthError(depth_pred, depth_gt):
    '''
    "Loopy loopy original solution"
    '''
    L_d, Mcard = 0.0, 0
    B, c, H, W = depth_pred.shape #batch, channels, height, width
    for b in range(B): #B is batch size, iterating over the images in a batch
        depth_pred2D = depth_pred[b][0] # bth depth image, depth images have 1 channel thus 0
        depth_gt2D = depth_gt[b][0]
        for h in range(H): # iterate over pixels along height
            for w in range(W):
                if depth_gt2D[h][w] &lt;= 0:
                    continue
                Mcard += 1
                diff = torch.sub(depth_pred2D[h][w], depth_gt2D[h][w])
                L_d += torch.abs(diff)
    L_d = torch.div(L_d, Mcard)
    return L_d #return depth loss


def DepthErrorVectorized(depth_pred, depth_gt):
    '''
    "Vectorized (that means using broadcasting) solution"
    '''
    diff = depth_pred - depth_gt # Difference
    diff = diff[depth_gt &gt; 0]    # Obtain the values that satisfies depth_gt &gt; 0
    L_d = diff.abs().sum()       # Abs and sum to get L1 loss
    Mcard = len(diff.view(-1))   # Flatten diff using .view(-1), then get cardinality
    return L_d / Mcard           # Scale L1 loss with cardinality

# Create some dummy ground truth data
y = torch.stack([
    torch.full((1, 64, 64), 2),  # Depth image of 2
    torch.full((1, 64, 64), 1),  # Depth image of 1
    torch.full((1, 64, 64), -1), # Depth image of -1
]).to(torch.float32)

# Create dummy predictions
pred = torch.ones_like(y) # "Predict all ones", intuitively loss should be 0.5000

print(DepthError(pred, y))           # tensor(0.5000)
print(DepthErrorVectorized(pred, y)) # tensor(0.5000)
</code></pre>

sugh7020: <p>Hi <a class="mention" href="/u/napam">@Napam</a> Thanks a lot for the help!</p>
<p>Thanks a lot again!</p>