项目作者: FnSK4R17s

项目描述 :
Testing Mixed Precision Training Using Pytorch Lightning and Segmentation Models
高级语言: Python
项目地址: git://github.com/FnSK4R17s/Testing-Mixed-Precision-Training-Using-Pytorch-Lightning-and-Segmentation-Models.git


Testing Mixed Precision Training Using Pytorch Lightning and Segmentation Models



header

Testing Mixed Precision Training Using PyTorch Lightning and Segmentation Models PyTorch


logo

Segmentation tasks are becoming easier day by day especially due to th rise in number of open source pachages like Segmentation Models PyTorch . Similarly with the advent of mixed precision training, even beginners can train state of the art models on their PCs. In this project I have tried to experiment with fp16 training with the help of PyTorch Lightning framework.

Pytorch lightning is a lightweight wrapper over pytorch and is used by researchers worldwide to speed up their Deep Learning experiments. You can use this project to set up your image segmentation project easily. The project structure is similar to the directory structure used in kaggle competitions so it will be easier to convert this project into a kaggle kernel.

Requirements

Table Of Contents

In a Nutshell

In a nutshell here’s how to train your own segmentation model with PyTorch Lightning and Segmentation Models PyTorch , so for example assume you want to implement ResNet-34 to compete in Carvana Image Masking Challenge, so you should do the following:

  • Create /input folder and place your dataset in it, edit config.py such that train and test paths point to their respective folders
  1. INPUT = 'input'
  2. OUTPUT = 'output'
  3. TRAIN_PATH = f'{INPUT}/train_hq'
  4. MASK_PATH = f'{INPUT}/train_masks'
  5. TEST_PATH = f'{INPUT}/test_hq'
  • In config.py file change the value of MODEL_NAME to the name of model that you wish to use, here we have used smp_unet_resnet34 .
  1. MODEL_NAME = 'smp_unet_resnet34'
  • In model_dispatcher.py file, you can build a dictionary named build_model to define your model using Segmentation Models PyTorch library
    ```python
    import segmentation_models_pytorch as smp

MODELS = {
‘smp_unet_resnet34’ : smp.Unet(‘resnet34’, encoder_weights=’imagenet’, classes=config.CLASSES, activation=’softmax’),
}

  1. - In `dataset.py` file create a `Dataset Object` like this
  2. ```python
  3. class CarvanaDataset:
  4. def __init__(self, folds):
  5. df = pd.read_csv(config.TRAIN_FOLDS)
  6. df = df[['img', 'kfold']]
  7. df = df[df.kfold.isin(folds)].reset_index(drop=True)
  8. self.image_ids = df.img.values
  9. if len(folds) == 1:
  10. self.aug = A.Compose([
  11. A.Resize(config.CROP_SIZE, config.CROP_SIZE, always_apply=True),
  12. A.Normalize(config.MODEL_MEAN, config.MODEL_STD, always_apply=True)
  13. ])
  14. else:
  15. self.aug = A.Compose([
  16. A.Resize(config.CROP_SIZE, config.CROP_SIZE, always_apply=True),
  17. A.ShiftScaleRotate(
  18. shift_limit=0.0625,
  19. scale_limit=0.1,
  20. rotate_limit=15,
  21. p=0.9),
  22. A.Normalize(config.MODEL_MEAN, config.MODEL_STD, always_apply=True)
  23. ])
  24. def __len__(self):
  25. return len(self.image_ids)
  26. def __getitem__(self, item):
  27. img_name = self.image_ids[item]
  28. image = np.array(Image.open(f'{config.TRAIN_PATH}/{img_name}.jpg'))
  29. mask = np.array(Image.open(f'{config.MASK_PATH}/{img_name}_mask.gif'))
  30. augmented = self.aug(image=image, mask=mask)
  31. image = augmented['image']
  32. mask = augmented['mask']
  33. image = np.transpose(image, (2, 0, 1)).astype(np.float32)
  34. return {
  35. 'image': torch.tensor(image, dtype=torch.float),
  36. 'mask': torch.tensor(mask, dtype=torch.float)
  37. }
  • Now, run folds.py to create folds for training and validation. You can test your dataset using test_dataset.py.
  • Now we can build our Lightning Module :-
    ```python
    import pytorch_lightning as pl
    import model_dispatcher
    import config
    from dataset import CarvanaDataset

class CarvanaModel(pl.LightningModule):
def init(self, trainfolds, valfolds):
super(CarvanaModel, self).__init
()

  1. # import model from model dispatcher
  2. self.model = model_dispatcher.MODELS[config.MODEL_NAME]
  3. self.train_folds = train_folds
  4. self.val_folds = val_folds
  5. def forward(self, x):
  6. return self.model(x)
  7. def training_step(self, batch, batch_nb):
  8. # REQUIRED
  9. x = batch['image']
  10. y = batch['mask']
  11. y_hat = self(x)
  12. loss = IoULoss()(y_hat, y)
  13. tensorboard_logs = {'train_loss': loss}
  14. return {'loss': loss, 'log': tensorboard_logs}
  15. def validation_step(self, batch, batch_nb):
  16. # OPTIONAL
  17. x = batch['image']
  18. y = batch['mask']
  19. y_hat = self(x)
  20. return {'val_loss': IoULoss()(y_hat, y)}
  21. def validation_epoch_end(self, outputs):
  22. # OPTIONAL
  23. avg_loss = torch.stack([x['val_loss'] for x in outputs]).mean()
  24. tensorboard_logs = {'val_loss': avg_loss}
  25. return {'val_loss': avg_loss, 'log': tensorboard_logs}
  26. def configure_optimizers(self):
  27. return torch.optim.Adam(self.parameters(), lr=config.LR)
  28. def train_dataloader(self):
  29. # REQUIRED
  30. return DataLoader(CarvanaDataset(folds=self.train_folds), shuffle=True, batch_size=config.TRAIN_BATCH_SIZE)
  31. def val_dataloader(self):
  32. # OPTIONAL
  33. return DataLoader(CarvanaDataset(folds=self.val_folds), batch_size=config.VAL_BATCH_SIZE)
  1. - Now we can train our model using the `Lightning_trainer.py` script
  2. ```python
  3. carvana_model = CarvanaModel(train_folds, val_folds)
  4. # most basic trainer, uses good defaults (1 gpu)
  5. trainer = pl.Trainer(gpus=1, accumulate_grad_batches=64, amp_level='O1', precision=16, profiler=True, max_epochs=config.EPOCHS)
  6. trainer.fit(carvana_model)

Note: We have used amp to perform Mixed Precision Training using NVIDIA APEX library

Project Structure

  1. ├── input
  2. ├── test_hq - here's the folder containing test images.
  3. │ ├── train_hq - here's the folder containing train images.
  4. └── train_masks - here's the folder containing train masks.
  5. ├── lightning_logs
  6. │ └── version_# - training checkpoints are saved here.
  7. ├── output
  8. │ └── train_folds.py - this file is generated when we run folds.py.
  9. └── src
  10. ├── config.py - this file contains all the hyperparameters for the project.
  11. ├── dataset.py - this file contains dataset object.
  12. ├── decoders.py - redundant file will be used in future.
  13. ├── dice_loss.py - this file defines various losses which can be used to train the model.
  14. ├── encoders.py - redundant file will be used in future.
  15. ├── folds.py - this file created folds for cross validation.
  16. ├── Lightning_module.py - this file contains the Lightinig Module.
  17. ├── Lightning_trainer.py - run this file to train the model.
  18. ├── Lightning_tester.py - this file is used to evaluate the trained model.
  19. ├── model_dispatcher.py - this file contains model definitions.
  20. ├── ND_Crossentropy.py - helper function for loss function.
  21. ├── test_dataset.py - this file contains the train loops.
  22. └── test_model.py - this file contains the inference process.

Future Work

  • Write Unetify script using encoder.py and decoder.py
  • Add Augmentations to the dataset to make the model more robust
  • Add Hydra support

Contributing

Any kind of enhancement or contribution is welcomed.

Acknowledgments

  • Loss functions were taken from this repo SegLoss