Defining your own custom criterion for dynamics evaluation

Defining your own custom criterion can be very useful as the same instance you can either use it for analysing training dynamics or you can use it as IB-based loss objective for HSIC networks.

Importing glow modules

[6]:
# importing Estimator class from glow
from glow.information_bottleneck import Estimator

Custom criterion class

Following is the general structure which your custom criterion class should follow in order for the PyGlow to detect your criterion function. NOTE: In most of the cases you won’t require implementation for eval_dynamics_segment so only criterion function is sufficient for PyGlow to accept your instance. You need eval_dynamics_segment implementation when you totally have to change the way you want to process a single dynamics segment.

[3]:
class CustomCriterion(Estimator):
    """
    This is a custom class for implementing your
    own criterion function (measure of dependence
    between random variables)

    Arguments:
        function (callable, optional): this is an example argument
        which denotes any function which your criterion demands
        gpu (bool): if true then all the computation is done on
        `GPU` otherwise on `CPU`
        **kwargs: The keyword arguments store all the parameters
        that are essential for the criterion function

    """
    def __init__(self, function, gpu, **kwargs):
        super().__init__(gpu, **kwargs)
        self.func = function  # attributes other than parameters

    def criterion(self, x, y):
        """
        Custom criterion function.

        Arguments:
            x (torch.Tensor): contains random variable one
            y (torch.Tensor): contains random variable two

        Returns:
            (torch.Tensor): calculated criterion of the two random variables 'x' and 'y'

        """
        # Define your logic for calculating criterion here
        # TODO


    # implement this only if you want to totally change the
    # logic of evaluating a single dyanmics segment else
    # there is inbuilt function that handles it.
    def eval_dynamics_segment(self, dynamics_segment):
        """
        Evaluates criterion for a dynamics segment using the
        criterion defined in the class itself.

        Arguments:
            dynamics_segment(iterable): this is a list of :class:`torch.Tensor`
            type objects whose first entry is input batch, last entry is labels
            batch and intermediate entries are hidden layers outputs batch

        Returns:
            (iterable): list of calculated coordinates according to the criterion
            with length equal to 'len(dynamics_segment)-2'

        """
        segment_size = len(dynamics_segment)
        # NOTE: dynamics_segment is a list where
        # input = dynamics_segment[0]
        # label = dynamics_segment[segment_size - 1]
        # and remaining tensors are hidden layers output
        output_segment = []  # output list which contains calculated coordinates
        for idx in range(1, segment_size-1):
            h = dynamics_segment[idx]
            # Define your logic of using h, input and label here
            # to apply your custom criterion on them.
            output_segment.append([self.criterion(h, x), self.criterion(h, y)])

        return output_segment