classdef seluLayer < nnet.layer.Layer

    properties
        alpha
    end
   
    methods
        function layer = seluLayer(alpha,name)
            layer.Type = 'Scaled Exponential Linear Unit';
            layer.alpha = alpha;
            
            % Assign layer name if it is passed in.
            if nargin > 1
                layer.Name = name;
            end
            
            % Give the layer a meaningful description.
            layer.Description = "Scaled Exponential linear unit with alpha: " + ...
                alpha;
        end

         function Z = predict(layer,X)
            % Forward input data through the layer at prediction time and
            % output the result
            %
            % Inputs:
            %         layer    -    Layer to forward propagate through
            %         X        -    Input data
            % Output:
            %         Z        -    Output of layer forward function
            
            % Expressing the computation in vectorized form allows it to
            % execute directly on the GPU.
            ramda=1.0507009873554804934193349852946;
            Z = (ramda.*X .* (X > 0)) + ...
                (ramda.*layer.alpha.*(exp(min(X,0)) - 1) .* (X <= 0));
        end
        
        function dLdX = backward(layer, X, Z, dLdZ, ~)
            % Backward propagate the derivative of the loss function through 
            % the layer
            %
            % Inputs:
            %         layer             - Layer to backward propagate through
            %         X                 - Input data
            %         Z                 - Output of layer forward function            
            %         dLdZ              - Gradient propagated from the deeper layer
            %         memory            - Memory value which can be used in
            %                             backward propagation [unused]
            % Output:
            %         dLdX              - Derivative of the loss with
            %                             respect to the input data
            
            dLdX = dLdZ .* ((X > 0) + ...
                ((layer.alpha + Z) .* (X <= 0)));            
        end
        
    end
end

