Is there a readily available Pythonic way to compose a multiple nested function g = f3(f2(f1())) from a list of functions [f1, f2, f3] where there are more functions in a list.
If there are a few, I may do:
g = lambda x: f3(f2(f1(x)))
However when I have dozens of functions e.g layers in a deep neural network, it is un-manageable. Prefer not creating another function to compose g but finding an available way.
Based on the answer from @Chris. For sequential neural network layers [ batchnorm, matmul, activation, softmaxloss ]
, each of which has a forward(X)
method to calculate its output to the next layer, the loss function L and loss would be:
L = reduce(lambda f, g: lambda X: g(f(X)), [ layer.forward for layer in layers ] ) # Loss function
network_loss = L(X)
One way using functools.reduce
:
from functools import reduce
f1 = lambda x: x+1
f2 = lambda x: x*2
f3 = lambda x: x+3
funcs = [f1, f2, f3]
g = reduce(lambda f, g: lambda x: g(f(x)), funcs)
Output:
g(1)==7 # ((1+1) * 2) + 3
g(2)==9 # ((2+1) * 2) + 3
Insight:
functools.reduce
will chain its second argument (funcs
here) according to its first argument (lambda
here).
That being said, it will start chaining f1
and f2
as f_21(x) = f2(f1(x))
, then f3
and f_21
as f3(f_21(x))
which becomes g(x)
.
One problem with the reduce
-baed approach is that you introduce O(n) additional function calls. An alternative is to define a single function that remembers the functions to compose; when called, it simply calls each function in sequence on the given argument.
def compose(*args):
"""compose(f1, f2, ..., fn) == lambda x: fn(...(f2(f1(x))...)"""
def _(x):
result = x
for f in args:
result = f(result)
return result
return _
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With