Apply online data augmentation only to minority class #3152
Replies: 4 comments 3 replies
-
Hi @tommydino93 , Thanks for your interest here. Thanks. |
Beta Was this translation helpful? Give feedback.
-
Hi @tommydino93, You could separate your data augmentations from the other transforms and then use a lambda function to conditionally apply the data augmentations. Something like this (untested): # data augmentations
random_augmentations = Compose([
RandFlipd(keys="image"),
...
])
# standard transformations
transformations = Compose([
LoadImaged(keys="image"),
...,
Lambda(lambda x: random_augmentations(x) if x["label"] in (1, 2) else x)
])
data1 = {"image": some_filename, "label": 0}
transformations(data1) # should have identity applied
data2 = {"image": some_filename, "label": 1}
transformations(data2) # should have random augmentations applied Here, I've used dictionary transformations so that when performing transformations to the image, we have access to the label at the same time. |
Beta Was this translation helpful? Give feedback.
-
thank you very much @Nic-Ma and @rijobro ! However, I was thinking that by doing as you suggested (@rijobro ), I would not duplicate the minority class, but instead I would simply apply the transformations to the volumes belonging to the minority class. What would be more desirable in my case would be probably to perform offline augmentation and really create augmented volumes. Or am I missing something and the same thing can be done with online augmentation? Thanks again |
Beta Was this translation helpful? Give feedback.
-
Thanks @rijobro Yes, by online I meant on-the-fly and by offline I meant to pre-compute the augmentations. I hadn't thought about the overfitting on the pre-computed augmentations, you are right. So I decided to go for the on-the-fly. Your solution works, but I had to add Here is the (pseudo) code that works for me: # define monai data augmentation (will only be applied on minority class volumes, see Lambda)
augmentation_transforms = Compose([RandRotate90d(keys="volume", prob=0.25, max_k=3, spatial_axes=(0, 1)),
RandFlipd(keys="volume", prob=0.25, spatial_axis=None),
RandGaussianNoised(keys="volume", prob=0.25, mean=0.0, std=0.1),
RandZoomd(keys="volume", prob=0.25, min_zoom=0.7, max_zoom=1.3)])
# define preprocessing and transforms for training volumes
train_transforms = Compose([LoadImaged(keys="volume"),
ScaleIntensityd(keys="volume", minv=0.0, maxv=1.0), # rescale intensities between "minv" and "maxv"
AddChanneld(keys="volume"), # add channel; monai expects channel-first tensors
Resized(keys="volume", spatial_size=tuple(median_shape)), # resize all volumes to median volume shape
Lambda(lambda x: augmentation_transforms(x) if x["label"] in (1, 2) else x), # apply data augmentation(s)
EnsureTyped(keys="volume")]) # ensure that input data is either a PyTorch Tensor or np array
x_train = ["filepath1", "filepath2", "filepath2", "..."]
y_train = [0, 1, 2, ...]
# create input dict
train_files = [{"volume": volume_name, 'label': label_name} for volume_name, label_name in zip(x_train, y_train)]
train_ds = Dataset(data=train_files, transform=train_transforms)
train_loader = DataLoader(train_ds, batch_size=batch_size, shuffle=True, num_workers=nb_workers, pin_memory=torch.cuda.is_available(), collate_fn=lambda x: x)
# ... begin training loop |
Beta Was this translation helpful? Give feedback.
-
Hi :)
I modified the 3D classification tutorial for a 3-class problem (labels 0, 1, and 2) and it runs fine.
Now I'd like to apply online data augmentation with
Compose
, but only to volumes that are associated with the labels 1 and 2 (minority classes). What is the recommended way to do this? I came up with 2 possible solutions:ImageDataset
, apply different transformation and then merge them. However, I did not find a way to merge the datasets.Compose
that selectively applies the augmentations, though I did not find such an argument.Thanks a lot in advance,
Tommaso
Beta Was this translation helpful? Give feedback.
All reactions