Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to compose a nested function g=fn(...(f3(f2(f1()))...) from a list of functions [f1, f2, f3,...fn]

Tags:

python

Question

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.


Update

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)
like image 921
mon Avatar asked Feb 04 '23 14:02

mon


2 Answers

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).

like image 184
Chris Avatar answered Feb 06 '23 15:02

Chris


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 _
like image 25
chepner Avatar answered Feb 06 '23 16:02

chepner