torchsight.trainers.dlde.weighted module

DLDENet trainer for the weighted version.

Source code
"""DLDENet trainer for the weighted version."""
from torchsight.losses import DLDENetLoss
from torchsight.models import DLDENet

from ..retinanet import RetinaNetTrainer


class DLDENetTrainer(RetinaNetTrainer):
    """Deep Local Directional Embedding with tracked means trainer.

    As the architecture is very similar with RetinaNet we use the same trainer and only
    override some attributes and methods. For more information please read the RetinaNet
    trainer documentation.
    """
    # Base hyperparameters, can be replaced in the initialization of the trainer
    hyperparameters = {
        'model': {
            'resnet': 18,
            'features': {
                'pyramid': 256,
                'regression': 256,
                'classification': 256
            },
            'anchors': {
                'sizes': [32, 64, 128, 256, 512],
                'scales': [2 ** 0, 2 ** (1/3), 2 ** (2/3)],
                'ratios': [0.5, 1, 2]
            },
            'fpn_levels': [3, 4, 5, 6, 7],
            'embedding_size': 256,
            'normalize': True,
            'pretrained': True,
            'evaluation': {'threshold': 0.5, 'iou_threshold': 0.5},
            'weighted_bias': False,
            'fixed_bias': 0,
            'increase_norm_by': None
        },
        'criterion': {
            'alpha': 0.25,
            'gamma': 2.0,
            'sigma': 3.0,
            'iou_thresholds': {'background': 0.4, 'object': 0.5},
            'increase_foreground_by': 1000,
            # Weight of each loss. See train method.
            'weights': {'classification': 1e4, 'regression': 1, 'similarity': 1},
            'soft': False,  # Apply soft loss weighted by the IoU
        },
        'datasets': {
            'use': 'coco',
            'coco': {
                'root': './datasets/coco',
                'class_names': (),  # () indicates all classes
                'train': 'train2017',
                'validation': 'val2017'
            },
            'logo32plus': {
                'root': './datasets/logo32plus',
                'classes': None,
            },
            'flickr32': {
                'root': './datasets/flickr32',
                'brands': None,
                'only_boxes': True,
                'training': 'trainval',  # The name of the dataset to use for training
                'validation': 'test'  # The name of the dataset to use for validation
            }
        },
        'dataloaders': {
            'batch_size': 1,
            'shuffle': True,
            'num_workers': 8
        },
        'optimizer': {
            'use': 'sgd',  # Which optimizer the trainer must use
            'adabound': {
                'lr': 1e-3,  # Learning rate
                'final_lr': 1  # When the optimizer change from Adam to SGD
            },
            'sgd': {
                'lr': 1e-2,
                'momentum': 0.9,
                'weight_decay': 1e-4
            }
        },
        'scheduler': {
            'factor': 0.1,
            'patience': 5,
            'threshold': 0.01
        },
        'transform': {
            'GaussNoise': {
                'var_limit': (10, 50),
                'p': 0.5
            },
            'GaussianBlur': {
                'blur_limit': 0.7,
                'p': 0.5
            },
            'RandomBrightnessContrast': {
                'brightness_limit': 0.2,
                'contrast_limit': 0.2,
                'p': 0.5
            },
            'Rotate': {
                'limit': 45,
                'p': 0.5
            },
            'LongestMaxSize': {
                'max_size': 512
            },
            'PadIfNeeded': {
                'min_height': 512,
                'min_width': 512
            },
            'RandomSizedBBoxSafeCrop': {
                'height': 512,
                'width': 512
            }
        }
    }

    ####################################
    ###           GETTERS            ###
    ####################################

    def get_model(self):
        """Initialize and get a DLDENet model instance."""
        hyperparameters = self.hyperparameters['model']
        return DLDENet(
            classes=hyperparameters['classes'],
            resnet=hyperparameters['resnet'],
            features=hyperparameters['features'],
            anchors=hyperparameters['anchors'],
            fpn_levels=hyperparameters['fpn_levels'],
            embedding_size=hyperparameters['embedding_size'],
            normalize=hyperparameters['normalize'],
            pretrained=hyperparameters['pretrained'],
            device=self.device,
            weighted_bias=hyperparameters['weighted_bias'],
            fixed_bias=hyperparameters['fixed_bias'],
            increase_norm_by=hyperparameters['increase_norm_by'],
        )

    def get_criterion(self):
        """Get the criterion to use to train the model.

        Returns:
            DLDENetLoss: The unified loss between FocalLoss and Cosine similarity Loss.
        """
        params = self.hyperparameters['criterion']

        return DLDENetLoss(
            alpha=params['alpha'],
            gamma=params['gamma'],
            sigma=params['sigma'],
            iou_thresholds=params['iou_thresholds'],
            increase_foreground_by=params['increase_foreground_by'],
            soft=params['soft'],
            device=self.device
        )

    ####################################
    ###           METHODS            ###
    ####################################

    def forward(self, *args):
        """Forward pass through the network and loss computation.

        Returns:
            torch.Tensor: The loss of the batch.
        """
        images, annotations, *_ = args
        images, annotations = images.to(self.device), annotations.to(self.device)

        anchors, regressions, classifications = self.model(images)
        del images

        losses = self.criterion(anchors, regressions, classifications, annotations, self.model)
        del anchors, regressions, classifications, annotations

        classification, regression, similarity = losses

        # Amplify the losses according to the criterion weights
        weights = self.hyperparameters['criterion']['weights']
        classification *= weights['classification']
        regression *= weights['regression']
        similarity *= weights['similarity']

        loss = classification + regression + similarity

        # Log the classification and regression loss too:
        self.current_log['Class.'] = '{:.4f}'.format(float(classification))
        self.current_log['Pos'] = '{:.4f}'.format(float(self.criterion.focal.pos_loss * weights['classification']))
        self.current_log['Neg'] = '{:.4f}'.format(float(self.criterion.focal.neg_loss * weights['classification']))
        self.current_log['Regr.'] = '{:.4f}'.format(float(regression))
        self.current_log['Simil.'] = '{:.4f}'.format(float(similarity))
        # Log the mean norm of the weights in the classification module and their biases
        self.current_log['w-norm'] = '{:.4f}'.format(float(self.model.classification.weights.norm(dim=0).mean()))
        if self.model.classification.weighted_bias:
            self.current_log['bias'] = '{:.4f}'.format(float(self.model.classification.bias.mean()))

        return loss

Classes

class DLDENetTrainer (ancestors: RetinaNetTrainer, Trainer)

Deep Local Directional Embedding with tracked means trainer.

As the architecture is very similar with RetinaNet we use the same trainer and only override some attributes and methods. For more information please read the RetinaNet trainer documentation.

Source code
class DLDENetTrainer(RetinaNetTrainer):
    """Deep Local Directional Embedding with tracked means trainer.

    As the architecture is very similar with RetinaNet we use the same trainer and only
    override some attributes and methods. For more information please read the RetinaNet
    trainer documentation.
    """
    # Base hyperparameters, can be replaced in the initialization of the trainer
    hyperparameters = {
        'model': {
            'resnet': 18,
            'features': {
                'pyramid': 256,
                'regression': 256,
                'classification': 256
            },
            'anchors': {
                'sizes': [32, 64, 128, 256, 512],
                'scales': [2 ** 0, 2 ** (1/3), 2 ** (2/3)],
                'ratios': [0.5, 1, 2]
            },
            'fpn_levels': [3, 4, 5, 6, 7],
            'embedding_size': 256,
            'normalize': True,
            'pretrained': True,
            'evaluation': {'threshold': 0.5, 'iou_threshold': 0.5},
            'weighted_bias': False,
            'fixed_bias': 0,
            'increase_norm_by': None
        },
        'criterion': {
            'alpha': 0.25,
            'gamma': 2.0,
            'sigma': 3.0,
            'iou_thresholds': {'background': 0.4, 'object': 0.5},
            'increase_foreground_by': 1000,
            # Weight of each loss. See train method.
            'weights': {'classification': 1e4, 'regression': 1, 'similarity': 1},
            'soft': False,  # Apply soft loss weighted by the IoU
        },
        'datasets': {
            'use': 'coco',
            'coco': {
                'root': './datasets/coco',
                'class_names': (),  # () indicates all classes
                'train': 'train2017',
                'validation': 'val2017'
            },
            'logo32plus': {
                'root': './datasets/logo32plus',
                'classes': None,
            },
            'flickr32': {
                'root': './datasets/flickr32',
                'brands': None,
                'only_boxes': True,
                'training': 'trainval',  # The name of the dataset to use for training
                'validation': 'test'  # The name of the dataset to use for validation
            }
        },
        'dataloaders': {
            'batch_size': 1,
            'shuffle': True,
            'num_workers': 8
        },
        'optimizer': {
            'use': 'sgd',  # Which optimizer the trainer must use
            'adabound': {
                'lr': 1e-3,  # Learning rate
                'final_lr': 1  # When the optimizer change from Adam to SGD
            },
            'sgd': {
                'lr': 1e-2,
                'momentum': 0.9,
                'weight_decay': 1e-4
            }
        },
        'scheduler': {
            'factor': 0.1,
            'patience': 5,
            'threshold': 0.01
        },
        'transform': {
            'GaussNoise': {
                'var_limit': (10, 50),
                'p': 0.5
            },
            'GaussianBlur': {
                'blur_limit': 0.7,
                'p': 0.5
            },
            'RandomBrightnessContrast': {
                'brightness_limit': 0.2,
                'contrast_limit': 0.2,
                'p': 0.5
            },
            'Rotate': {
                'limit': 45,
                'p': 0.5
            },
            'LongestMaxSize': {
                'max_size': 512
            },
            'PadIfNeeded': {
                'min_height': 512,
                'min_width': 512
            },
            'RandomSizedBBoxSafeCrop': {
                'height': 512,
                'width': 512
            }
        }
    }

    ####################################
    ###           GETTERS            ###
    ####################################

    def get_model(self):
        """Initialize and get a DLDENet model instance."""
        hyperparameters = self.hyperparameters['model']
        return DLDENet(
            classes=hyperparameters['classes'],
            resnet=hyperparameters['resnet'],
            features=hyperparameters['features'],
            anchors=hyperparameters['anchors'],
            fpn_levels=hyperparameters['fpn_levels'],
            embedding_size=hyperparameters['embedding_size'],
            normalize=hyperparameters['normalize'],
            pretrained=hyperparameters['pretrained'],
            device=self.device,
            weighted_bias=hyperparameters['weighted_bias'],
            fixed_bias=hyperparameters['fixed_bias'],
            increase_norm_by=hyperparameters['increase_norm_by'],
        )

    def get_criterion(self):
        """Get the criterion to use to train the model.

        Returns:
            DLDENetLoss: The unified loss between FocalLoss and Cosine similarity Loss.
        """
        params = self.hyperparameters['criterion']

        return DLDENetLoss(
            alpha=params['alpha'],
            gamma=params['gamma'],
            sigma=params['sigma'],
            iou_thresholds=params['iou_thresholds'],
            increase_foreground_by=params['increase_foreground_by'],
            soft=params['soft'],
            device=self.device
        )

    ####################################
    ###           METHODS            ###
    ####################################

    def forward(self, *args):
        """Forward pass through the network and loss computation.

        Returns:
            torch.Tensor: The loss of the batch.
        """
        images, annotations, *_ = args
        images, annotations = images.to(self.device), annotations.to(self.device)

        anchors, regressions, classifications = self.model(images)
        del images

        losses = self.criterion(anchors, regressions, classifications, annotations, self.model)
        del anchors, regressions, classifications, annotations

        classification, regression, similarity = losses

        # Amplify the losses according to the criterion weights
        weights = self.hyperparameters['criterion']['weights']
        classification *= weights['classification']
        regression *= weights['regression']
        similarity *= weights['similarity']

        loss = classification + regression + similarity

        # Log the classification and regression loss too:
        self.current_log['Class.'] = '{:.4f}'.format(float(classification))
        self.current_log['Pos'] = '{:.4f}'.format(float(self.criterion.focal.pos_loss * weights['classification']))
        self.current_log['Neg'] = '{:.4f}'.format(float(self.criterion.focal.neg_loss * weights['classification']))
        self.current_log['Regr.'] = '{:.4f}'.format(float(regression))
        self.current_log['Simil.'] = '{:.4f}'.format(float(similarity))
        # Log the mean norm of the weights in the classification module and their biases
        self.current_log['w-norm'] = '{:.4f}'.format(float(self.model.classification.weights.norm(dim=0).mean()))
        if self.model.classification.weighted_bias:
            self.current_log['bias'] = '{:.4f}'.format(float(self.model.classification.bias.mean()))

        return loss

Class variables

var hyperparameters

Methods

def get_criterion(self)

Get the criterion to use to train the model.

Returns

DLDENetLoss
The unified loss between FocalLoss and Cosine similarity Loss.
Source code
def get_criterion(self):
    """Get the criterion to use to train the model.

    Returns:
        DLDENetLoss: The unified loss between FocalLoss and Cosine similarity Loss.
    """
    params = self.hyperparameters['criterion']

    return DLDENetLoss(
        alpha=params['alpha'],
        gamma=params['gamma'],
        sigma=params['sigma'],
        iou_thresholds=params['iou_thresholds'],
        increase_foreground_by=params['increase_foreground_by'],
        soft=params['soft'],
        device=self.device
    )
def get_model(self)

Initialize and get a DLDENet model instance.

Source code
def get_model(self):
    """Initialize and get a DLDENet model instance."""
    hyperparameters = self.hyperparameters['model']
    return DLDENet(
        classes=hyperparameters['classes'],
        resnet=hyperparameters['resnet'],
        features=hyperparameters['features'],
        anchors=hyperparameters['anchors'],
        fpn_levels=hyperparameters['fpn_levels'],
        embedding_size=hyperparameters['embedding_size'],
        normalize=hyperparameters['normalize'],
        pretrained=hyperparameters['pretrained'],
        device=self.device,
        weighted_bias=hyperparameters['weighted_bias'],
        fixed_bias=hyperparameters['fixed_bias'],
        increase_norm_by=hyperparameters['increase_norm_by'],
    )

Inherited members