Source code for neuroptica.losses

'''The Losses submodule contains classes for computing common loss functions.'''

import numpy as np


class Loss:

    @staticmethod
    def L(X: np.ndarray, T: np.ndarray) -> np.ndarray:
        '''
        The scalar, real-valued loss function (vectorized over multiple X, T inputs)
        :param X: the output of the network
        :param T: the target output
        :return: loss function for each X
        '''
        raise NotImplementedError("Loss function must be specified in child class")

    @staticmethod
    def dL(X: np.ndarray, T: np.ndarray) -> np.ndarray:
        '''
        The derivative of the loss function dL/dX_L used for backpropagation (vectorized over multiple X)
        :param X: the output of the network
        :param T: the target output
        :return: dL/dX_L for each X
        '''
        raise NotImplementedError("Derivative loss function must be specified in child class")


class MeanSquaredError(Loss):

    @staticmethod
    def L(X: np.ndarray, T: np.ndarray) -> np.ndarray:
        return np.sum(1 / 2 * np.abs(T - X) ** 2, axis=0)

    @staticmethod
    def dL(X: np.ndarray, T: np.ndarray) -> np.ndarray:
        return np.conj(X - T)


[docs]class CategoricalCrossEntropy(Loss): '''Represents categorical cross entropy with a softmax layer implicitly applied to the outputs'''
[docs] @staticmethod def L(X: np.ndarray, T: np.ndarray) -> np.ndarray: X_softmax = np.exp(X) / np.sum(np.exp(X), axis=0) tol = 1e-10 X_clip = np.clip(X_softmax, tol, 1 - tol) return -np.sum(T * np.log(X_clip), axis=0)
[docs] @staticmethod def dL(X: np.ndarray, T: np.ndarray) -> np.ndarray: X_softmax = np.exp(X) / np.sum(np.exp(X), axis=0) return np.conj(X_softmax - T)