I have the following function that returns one of several functions along with their derivative for training neural networks.
Can this function be improved and made more pythonic in any way?
Are there other things like reducing the redundancy of the list, etc.?
Could a better way be to instead enclose the inner functions inside a class?
Note: I am not looking to optimize the computational aspects of the functions.
import numpy as np
def get_activation_fn_with_deriv(fn_name):
""" Returns function objects for activation function and its derivative.
Returns function objects for the specified activation function and its derivative function.
Args:
fn_name: Name of the activation function.
Returns:
(fn, fn_deriv): A tuple of the activation function and its derivative function.
Raises:
ValueError: If an unavailable activation function is retrieved.
Examples:
>>> relu, relu_deriv = activation_fn_with_deriv('relu')
>>> relu(np.array([1, -1, 2.3]))
array([1. , 0. , 2.3])
"""
available_fn = ['identity', 'relu', 'sigmoid', 'tanh']
match fn_name.lower():
case 'identity':
def identity(x):
return x
def identity_deriv(x):
return np.ones(x.shape)
return identity, identity_deriv
case 'relu':
def relu(x):
return np.maximum(x, 0.0)
def relu_deriv(x):
return np.where(x >= 0.0, 1.0, 0.0)
return relu, relu_deriv
case 'sigmoid':
def sigmoid(x):
return 1 / (1 + np.exp(-x))
def sigmoid_deriv(x):
sigmoid_x = sigmoid(x)
return sigmoid_x * (1 - sigmoid_x)
return sigmoid, sigmoid_deriv
case 'tanh':
def tanh(x):
exp_2x = np.exp(2 * x)
return (exp_2x - 1) / (exp_2x + 1)
def tanh_deriv(x):
return 1 - tanh(x) ** 2
return tanh, tanh_deriv
case _:
raise ValueError(f'Specified activation function not available. Choose from - {[name.lower() for name in available_fn]}.')