Hi Droid!



 droid:

The same logic follows for the other channels, where it’s important to have overlapping segments for this application.


Yes, it sounds like you do have a multi-label, three-class problem.


# red, blue, green channel weights = 6, 1, 30
loss_func = nn.BCEWithLogitsLoss(
    pos_weight=torch.Tensor([1, 30, 6]).repeat(BATCH_SIZE, 1))

# RuntimeError: The size of tensor a (3) must match the size of
# tensor b (256) at non-singleton dimension 3



Unfortunately, the documentation for BCEWithLogitsLoss is pretty
much silent about your use case (sometimes called the K dimensional
case in other parts of the pytorch documentation).  Specifically, your
prediction (and mask) don’t have shape [nBatch, nChannel], but
instead also have spatial dimensions, so that its shape is all of
[nBatch, nChannel, height, width].  That is you are not just
making a multi-label (nChannel) prediction for each sample in the
batch, but for each pixel in the image individually.
In this case, BCEWithLogitsLoss's weight and pos_weight tensors
(passed in as constructor arguments to BCEWithLogitsLoss) are
broadcast over pred and mask (called input and target in the
documentation).  Therefore, to make your pos_weight tensor properly
broadcastable, you need to add two singleton dimensions to its end
(that will then be broadcast over the height and width dimensions).
It doesn’t matter how you do this – one way is to use unsqueeze().
Thus, this should work:
>>> import torch
>>> torch.__version__
'1.9.0'
>>> _ = torch.manual_seed (2021)
>>> nBatch = 2
>>> nChannel = 3   # R, G, B
>>> height = 10
>>> width = 12
>>> pred = torch.randn (nBatch, nChannel, height, width)   # logits in [-inf, inf]
>>> mask = torch.rand (nBatch, nChannel, height, width)   # probabilities in [0.0, 1.0]
>>> pos_wt = torch.tensor ([6.0, 30.0, 1.0])   # weights are floats
>>> torch.nn.BCEWithLogitsLoss (pos_weight = pos_wt.unsqueeze (-1).unsqueeze (-1)) (pred, mask)
tensor(5.2394)

Note, mask should be of floating-point type, not integer.  Your mask
entries can be exactly 0.0 or 1.0 if you want, but they can be any
value in between, as well.
Best.
K. Frank