Randomcropbyposneglabel issues with dimensions.. the size of tensor a (118210248) must match the size of tensor b (101117952) at non-singleton dimension 0 monai randcropposneg error

Ibrahim_Manzoor: <p>Hi, I am training a UNET model for 3d data basically nifiti volumes with variable sizes in z dimension, the number of slices are different, they have their equivalent labels but I am getting this error on the first epoch, please let me know how to resolve it. I am sharing my code and error…</p>
<p><strong>CODE</strong><br>
from monai.utils import first, set_determinism<br>
import nibabel<br>
from monai.transforms import (<br>
AsDiscrete,<br>
Activationsd,<br>
EnsureType,<br>
DivisiblePadd,<br>
AsDiscreted,<br>
EnsureChannelFirstd,<br>
Compose,<br>
CropForegroundd,<br>
LoadImaged,<br>
Orientationd,<br>
NormalizeIntensityd,<br>
Resized,<br>
RandCropByPosNegLabeld,<br>
SaveImaged,<br>
ScaleIntensityRanged,<br>
Spacingd,<br>
Invertd,<br>
)<br>
from monai.handlers.utils import from_engine</p>
<p>from monai.handlers import TensorBoardStatsHandler<br>
from monai.losses import DiceLoss<br>
from monai.metrics import DiceMetric, HausdorffDistanceMetric<br>
from monai.networks.nets import UNet<br>
from monai.data import DataLoader<br>
from monai.config import print_config</p>
<p>from monai.networks.nets import UNet<br>
from monai.networks.layers import Norm<br>
from monai.metrics import DiceMetric<br>
from monai.losses import DiceLoss<br>
from monai.inferers import sliding_window_inference<br>
from monai.data import CacheDataset, DataLoader, Dataset, decollate_batch<br>
from monai.config import print_config<br>
from monai.apps import download_and_extract<br>
import torch<br>
import tempfile<br>
import shutil<br>
import os<br>
import glob</p>
<p>data_dir = “/home/hpc/iwi5/iwi5131h”<br>
root_dir = “/home/hpc/iwi5/iwi5131h”</p>
<p>train_images = sorted(glob.glob(os.path.join(data_dir, “traindata”, “<em>.nii.gz")))<br>
print(train_images)<br>
train_labels = sorted(glob.glob(os.path.join(data_dir, “trainlabels”, "</em>.nii.gz”)))</p>
<p>val_images = sorted(glob.glob(os.path.join(data_dir, ‘valdata’, ‘<em>.nii.gz’)))<br>
val_labels = sorted(glob.glob(os.path.join(data_dir, ‘vallabels’, '</em>.nii.gz’)))</p>
<p>train_files = [{“image”: image_name, ‘label’: label_name} for image_name, label_name in zip(train_images, train_labels)]<br>
val_files = [{“image”: image_name, ‘label’: label_name} for image_name, label_name in zip(val_images, val_labels)]</p>
<p>train_transforms = Compose(<br>
[<br>
LoadImaged(keys=[“image”, “label”]),<br>
EnsureChannelFirstd(keys=[“image”, “label”]),<br>
ScaleIntensityRanged(<br>
keys=[“image”],<br>
a_min=-57,<br>
a_max=164,<br>
b_min=0.0,<br>
b_max=1.0,<br>
clip=True,<br>
),<br>
CropForegroundd(keys=[“image”, “label”], source_key=“image”),<br>
Orientationd(keys=[“image”, “label”], axcodes=“RAS”),<br>
Spacingd(keys=[“image”, “label”], pixdim=(1.0, 1.0, 2.0), mode=(“bilinear”, “nearest”)),<br>
RandCropByPosNegLabeld(<br>
keys=[“image”, “label”],<br>
label_key=“label”,<br>
spatial_size=(96, 96, 96),<br>
pos=1,<br>
neg=1,<br>
num_samples=4,<br>
image_key=“image”,<br>
image_threshold=0,<br>
),<br>
# user can also add other random transforms<br>
# RandAffined(<br>
#     keys=[‘image’, ‘label’],<br>
#     mode=(‘bilinear’, ‘nearest’),<br>
#     prob=1.0, spatial_size=(96, 96, 96),<br>
#     rotate_range=(0, 0, np.pi/15),<br>
#     scale_range=(0.1, 0.1, 0.1)),<br>
]<br>
)<br>
val_transforms = Compose(<br>
[<br>
LoadImaged(keys=[“image”, “label”]),<br>
EnsureChannelFirstd(keys=[“image”, “label”]),<br>
ScaleIntensityRanged(<br>
keys=[“image”],<br>
a_min=-57,<br>
a_max=164,<br>
b_min=0.0,<br>
b_max=1.0,<br>
clip=True,<br>
),<br>
CropForegroundd(keys=[“image”, “label”], source_key=“image”),<br>
Orientationd(keys=[“image”, “label”], axcodes=“RAS”),<br>
Spacingd(keys=[“image”, “label”], pixdim=(1.0, 1.0, 2.0), mode=(“bilinear”, “nearest”)),<br>
]<br>
)<br>
train_ds = CacheDataset(<br>
data=train_files, transform=train_transforms,<br>
cache_rate=1.0, num_workers=0)</p>
<p>train_loader = DataLoader(train_ds, batch_size=1, shuffle=True, num_workers=0)</p>
<p>val_ds = CacheDataset(<br>
data=val_files, transform=val_transforms, cache_rate=1.0, num_workers=0)</p>
<p>val_loader = DataLoader(val_ds, batch_size=1, num_workers=0)</p>
<p>device = torch.device(“cuda:0”)<br>
model = UNet(<br>
spatial_dims=3,<br>
in_channels=1,<br>
out_channels=13,  # 11 organs + background<br>
channels=(16, 32, 64, 128, 256),<br>
strides=(2, 2, 2, 2),  # lenght - 1<br>
num_res_units=0,<br>
norm=Norm.BATCH,<br>
).to(device)<br>
loss_function = DiceLoss(to_onehot_y=True, softmax=True)<br>
optimizer = torch.optim.Adam(model.parameters(), 1e-4)</p>
<p>dice_metric = DiceMetric(include_background=False, reduction=“mean”)<br>
dice_metric_batch = DiceMetric(include_background=False, reduction=“mean_batch”)</p>
<p>surf_metric = HausdorffDistanceMetric(include_background=False, distance_metric=‘euclidean’, reduction=“mean”,<br>
percentile=95)<br>
surf_metric_batch = HausdorffDistanceMetric(include_background=True, distance_metric=‘euclidean’,<br>
reduction=“mean_batch”, percentile=95)</p>
<p>max_epochs = 1000<br>
val_interval = 1<br>
best_metric = -1<br>
best_metrics = -1<br>
best_metric_epoch = -1<br>
best_metric_epochs = -1<br>
epoch_loss_values = []<br>
metric_values = []<br>
smetric_values = []<br>
post_pred = Compose([EnsureType(), AsDiscrete(argmax=True, to_onehot=13)])<br>
post_label = Compose([EnsureType(), AsDiscrete(to_onehot=13)])</p>
<p>for epoch in range(max_epochs):<br>
print(“-” * 10)<br>
print(f"epoch {epoch + 1}/{max_epochs}“)<br>
model.train()<br>
epoch_loss = 0<br>
step = 0<br>
for batch_data in train_loader:<br>
step += 1<br>
inputs, labels = (<br>
batch_data[“image”].to(device),<br>
batch_data[“label”].to(device),<br>
)<br>
optimizer.zero_grad()<br>
# print(“Size of inputs[1] :”, inputs[1].shape)<br>
# print(“printing of inputs :”, inputs)<br>
outputs = model(inputs)<br>
loss = loss_function(outputs, labels)<br>
loss.backward()<br>
optimizer.step()<br>
epoch_loss += loss.item()<br>
print(<br>
f”{step}/{len(train_ds) // train_loader.batch_size}, "<br>
f"train_loss: {loss.item():.4f}“)<br>
epoch_loss /= step<br>
epoch_loss_values.append(epoch_loss)<br>
print(f"epoch {epoch + 1} average loss: {epoch_loss:.4f}”)</p>
<pre><code>if (epoch + 1) % val_interval == 0:
    model.eval()
    with torch.no_grad():
        for val_data in val_loader:
            val_inputs, val_labels = (
                val_data["image"].to(device),
                val_data["label"].to(device),
            )
            roi_size = (96, 96, 96)
            sw_batch_size = 4
            val_outputs = sliding_window_inference(
                val_inputs, roi_size, sw_batch_size, model)
            # val_outputs = model(val_inputs)
            val_outputs = [post_pred(i) for i in decollate_batch(val_outputs)]
            val_labels = [post_label(i) for i in decollate_batch(val_labels)]
            # compute metric for current iteration
            dice_metric(y_pred=val_outputs, y=val_labels)
            dice_metric_batch(y_pred=val_outputs, y=val_labels)
            surf_metric(y_pred=val_outputs, y=val_labels)
            surf_metric_batch(y_pred=val_outputs, y=val_labels)

        # aggregate the final mean dice result
        metric = dice_metric.aggregate().item()
        metric_batch_org = dice_metric_batch.aggregate()
        smetric = surf_metric.aggregate().item()
        smetric_batch_org = surf_metric_batch.aggregate()

        print(metric_batch_org[0].item())
        print(metric_batch_org[1].item())
        print(metric_batch_org[2].item())
        print(metric_batch_org[3].item())
        print(metric_batch_org[4].item())
        print(metric_batch_org[5].item())
        print(metric_batch_org[6].item())
        print(metric_batch_org[7].item())
        print(metric_batch_org[8].item())
        print(metric_batch_org[9].item())
        print(metric_batch_org[10].item())
        print(metric_batch_org[11].item())
        print(metric_batch_org[12].item())

        print("Hausdorff Distances")

        print(smetric_batch_org[0].item())
        print(smetric_batch_org[1].item())
        print(smetric_batch_org[2].item())
        print(smetric_batch_org[3].item())
        print(smetric_batch_org[4].item())
        print(smetric_batch_org[5].item())
        print(smetric_batch_org[6].item())
        print(smetric_batch_org[7].item())
        print(smetric_batch_org[8].item())
        print(smetric_batch_org[9].item())
        print(smetric_batch_org[10].item())
        print(smetric_batch_org[11].item())
        print(metric_batch_org[12].item())

        # reset the status for next validation round
        dice_metric.reset()
        dice_metric_batch.reset()
        surf_metric.reset()
        surf_metric_batch.reset()

        metric_values.append(metric)
        smetric_values.append(smetric)

        if metric &gt; best_metric:
            best_metric = metric
            best_metric_epoch = epoch + 1
            torch.save(model.state_dict(), os.path.join(
                root_dir, "resunet_trained_010102.pth"))
            print("saved new best metric model")
        print(
            f"current epoch: {epoch + 1} current mean dice: {metric:.4f}"
            f"\nbest mean dice: {best_metric:.4f} "
            f"at epoch: {best_metric_epoch}"
        )
</code></pre>
<p>print(<br>
f"train completed, best_metric: {best_metric:.4f} "<br>
f"at epoch: {best_metric_epoch}")</p>
<p>import numpy as np</p>
<p>np.save(‘loss_resunet_trained_010102.npy’, epoch_loss_values)  # save<br>
np.save(‘DICE_resunet_trained_010102.npy’, metric_values)  # save<br>
np.save(‘Hausdorff_resunet_trained_010102.npy’, smetric_values)  # save</p>
<p><strong>ERROR</strong><br>
epoch 1/1000<br>
Traceback (most recent call last):<br>
File “/home/hpc/iwi5/iwi5131h/.conda/envs/cuda_torch/lib/python3.11/site-packages/monai/transforms/transform.py”, line 102, in apply_transform<br>
return <em>apply_transform(transform, data, unpack_items)<br>
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br>
File “/home/hpc/iwi5/iwi5131h/.conda/envs/cuda_torch/lib/python3.11/site-packages/monai/transforms/transform.py”, line 66, in <em>apply_transform<br>
return transform(parameters)<br>
^^^^^^^^^^^^^^^^^^^^^<br>
File “/home/hpc/iwi5/iwi5131h/.conda/envs/cuda_torch/lib/python3.11/site-packages/monai/transforms/croppad/dictionary.py”, line 861, in <strong>call</strong><br>
self.randomize(label, fg_indices, bg_indices, image)<br>
File “/home/hpc/iwi5/iwi5131h/.conda/envs/cuda_torch/lib/python3.11/site-packages/monai/transforms/croppad/dictionary.py”, line 852, in randomize<br>
self.cropper.randomize(label=label, fg_indices=fg_indices, bg_indices=bg_indices, image=image)<br>
File “/home/hpc/iwi5/iwi5131h/.conda/envs/cuda_torch/lib/python3.11/site-packages/monai/transforms/croppad/array.py”, line 1060, in randomize<br>
fg_indices</em>, bg_indices</em> = map_binary_to_indices(label, image, self.image_threshold)<br>
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br>
File “/home/hpc/iwi5/iwi5131h/.conda/envs/cuda_torch/lib/python3.11/site-packages/monai/transforms/utils.py”, line 320, in map_binary_to_indices<br>
bg_indices = nonzero(img_flat &amp; ~label_flat)<br>
~



^



~~~~<br>
File “/home/hpc/iwi5/iwi5131h/.conda/envs/cuda_torch/lib/python3.11/site-packages/monai/data/meta_tensor.py”, line 268, in <strong>torch_function</strong><br>
ret = super().<strong>torch_function</strong>(func, types, args, kwargs)<br>
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br>
File “/home/hpc/iwi5/iwi5131h/.conda/envs/cuda_torch/lib/python3.11/site-packages/torch/_tensor.py”, line 1295, in <strong>torch_function</strong><br>
ret = func(*args, **kwargs)<br>
^^^^^^^^^^^^^^^^^^^^^<br>
RuntimeError: The size of tensor a (142909200) must match the size of tensor b (92475392) at non-singleton dimension 0</p>
<p>The above exception was the direct cause of the following exception:</p>
<p>Traceback (most recent call last):<br>
File “/home/hpc/iwi5/iwi5131h/code.py”, line 165, in <br>
for batch_data in train_loader:<br>
File “/home/hpc/iwi5/iwi5131h/.conda/envs/cuda_torch/lib/python3.11/site-packages/torch/utils/data/dataloader.py”, line 634, in <strong>next</strong><br>
data = self._next_data()<br>
^^^^^^^^^^^^^^^^^<br>
File “/home/hpc/iwi5/iwi5131h/.conda/envs/cuda_torch/lib/python3.11/site-packages/torch/utils/data/dataloader.py”, line 678, in _next_data<br>
data = self._dataset_fetcher.fetch(index)  # may raise StopIteration<br>
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br>
File “/home/hpc/iwi5/iwi5131h/.conda/envs/cuda_torch/lib/python3.11/site-packages/torch/utils/data/_utils/fetch.py”, line 51, in fetch<br>
data = [self.dataset[idx] for idx in possibly_batched_index]<br>
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br>
File “/home/hpc/iwi5/iwi5131h/.conda/envs/cuda_torch/lib/python3.11/site-packages/torch/utils/data/_utils/fetch.py”, line 51, in <br>
data = [self.dataset[idx] for idx in possibly_batched_index]<br>
~~~~~~~~~~~~^^^^^<br>
File “/home/hpc/iwi5/iwi5131h/.conda/envs/cuda_torch/lib/python3.11/site-packages/monai/data/dataset.py”, line 107, in <strong>getitem</strong><br>
return self._transform(index)<br>
^^^^^^^^^^^^^^^^^^^^^^<br>
File “/home/hpc/iwi5/iwi5131h/.conda/envs/cuda_torch/lib/python3.11/site-packages/monai/data/dataset.py”, line 921, in _transform<br>
data = apply_transform(_transform, data)<br>
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^<br>
File “/home/hpc/iwi5/iwi5131h/.conda/envs/cuda_torch/lib/python3.11/site-packages/monai/transforms/transform.py”, line 129, in apply_transform<br>
raise RuntimeError(f"applying transform {transform}") from e<br>
RuntimeError: applying transform &lt;monai.transforms.croppad.dictionary.RandCropByPosNegLabeld object at 0x7f0fa5d4bb10&gt;</p>