import numpy as np
[docs]class Activation:
[docs] def __call__(self, incoming):
raise NotImplementedError
[docs] def delta(self, incoming, outgoing, above):
"""
Compute the derivative of the cost with respect to the input of this
activation function. Outgoing is what this function returned in the
forward pass and above is the derivative of the cost with respect to
the outgoing activation.
"""
raise NotImplementedError
[docs]class Identity(Activation):
[docs] def __call__(self, incoming):
return incoming
[docs] def delta(self, incoming, outgoing, above):
delta = np.ones(incoming.shape).astype(float)
return delta * above
[docs]class Sigmoid(Activation):
[docs] def __call__(self, incoming):
return 1 / (1 + np.exp(-incoming))
[docs] def delta(self, incoming, outgoing, above):
delta = outgoing * (1 - outgoing)
return delta * above
[docs]class Relu(Activation):
[docs] def __call__(self, incoming):
return np.maximum(incoming, 0)
[docs] def delta(self, incoming, outgoing, above):
delta = np.greater(incoming, 0).astype(float)
return delta * above
[docs]class Softmax(Activation):
[docs] def __call__(self, incoming):
# The constant doesn't change the expression but prevents overflows.
constant = np.max(incoming)
exps = np.exp(incoming - constant)
return exps / exps.sum()
[docs] def delta(self, incoming, outgoing, above):
delta = outgoing * above
sum_ = delta.sum(axis=delta.ndim - 1, keepdims=True)
delta -= outgoing * sum_
return delta