De-collate a batch of data (for example, as produced by a `DataLoader`). Returns a list of structures with the original tensor's 0-th dimension sliced into elements using `torch.unbind`. Images originally stored as (B,C,H,W,[D]) will be returned as (C,H,W,[D]). Other information, such
(batch, detach: bool = True, pad=True, fill_value=None)
| 536 | |
| 537 | |
| 538 | def decollate_batch(batch, detach: bool = True, pad=True, fill_value=None): |
| 539 | """De-collate a batch of data (for example, as produced by a `DataLoader`). |
| 540 | |
| 541 | Returns a list of structures with the original tensor's 0-th dimension sliced into elements using `torch.unbind`. |
| 542 | |
| 543 | Images originally stored as (B,C,H,W,[D]) will be returned as (C,H,W,[D]). Other information, |
| 544 | such as metadata, may have been stored in a list (or a list inside nested dictionaries). In |
| 545 | this case we return the element of the list corresponding to the batch idx. |
| 546 | |
| 547 | Return types aren't guaranteed to be the same as the original, since numpy arrays will have been |
| 548 | converted to torch.Tensor, sequences may be converted to lists of tensors, |
| 549 | mappings may be converted into dictionaries. |
| 550 | |
| 551 | For example: |
| 552 | |
| 553 | .. code-block:: python |
| 554 | |
| 555 | batch_data = { |
| 556 | "image": torch.rand((2,1,10,10)), |
| 557 | DictPostFix.meta("image"): {"scl_slope": torch.Tensor([0.0, 0.0])} |
| 558 | } |
| 559 | out = decollate_batch(batch_data) |
| 560 | print(len(out)) |
| 561 | >>> 2 |
| 562 | |
| 563 | print(out[0]) |
| 564 | >>> {'image': tensor([[[4.3549e-01...43e-01]]]), DictPostFix.meta("image"): {'scl_slope': 0.0}} |
| 565 | |
| 566 | batch_data = [torch.rand((2,1,10,10)), torch.rand((2,3,5,5))] |
| 567 | out = decollate_batch(batch_data) |
| 568 | print(out[0]) |
| 569 | >>> [tensor([[[4.3549e-01...43e-01]]], tensor([[[5.3435e-01...45e-01]]])] |
| 570 | |
| 571 | batch_data = torch.rand((2,1,10,10)) |
| 572 | out = decollate_batch(batch_data) |
| 573 | print(out[0]) |
| 574 | >>> tensor([[[4.3549e-01...43e-01]]]) |
| 575 | |
| 576 | batch_data = { |
| 577 | "image": [1, 2, 3], "meta": [4, 5], # undetermined batch size |
| 578 | } |
| 579 | out = decollate_batch(batch_data, pad=True, fill_value=0) |
| 580 | print(out) |
| 581 | >>> [{'image': 1, 'meta': 4}, {'image': 2, 'meta': 5}, {'image': 3, 'meta': 0}] |
| 582 | out = decollate_batch(batch_data, pad=False) |
| 583 | print(out) |
| 584 | >>> [{'image': 1, 'meta': 4}, {'image': 2, 'meta': 5}] |
| 585 | |
| 586 | Args: |
| 587 | batch: data to be de-collated. |
| 588 | detach: whether to detach the tensors. Scalars tensors will be detached into number types |
| 589 | instead of torch tensors. |
| 590 | pad: when the items in a batch indicate different batch size, whether to pad all the sequences to the longest. |
| 591 | If False, the batch size will be the length of the shortest sequence. |
| 592 | fill_value: when `pad` is True, the `fillvalue` to use when padding, defaults to `None`. |
| 593 | """ |
| 594 | if batch is None: |
| 595 | return batch |
searching dependent graphs…