The code below allows me to get the partial derivative with respect to the three inputs of some function of the array x
import jax.numpy as jnp
import jax
def f(x):
return jnp.prod(x)
x=jnp.array([1.0,2.0,3.0])
funs = [f]
funs.append(lambda x: jax.grad(funs[0])(x)[0])
funs.append(lambda x: jax.grad(funs[1])(x)[1])
funs.append(lambda x: jax.grad(funs[2])(x)[2])
print(funs[3](x))
I would like the code above to generalize to an arbitrary number of inputs (and for some more complicated functions) thus I try:
funs = [f]
for i in range(n):
z = lambda x: jax.grad(funs[i])(x)[i]
funs.append(z)
funs[3](x)
but now I get the following error
---------------------------------------------------------------------------
RecursionError Traceback (most recent call last)
/tmp/ipykernel_331066/1225421420.py in <module>
19 funs.append(z)
20
---> 21 funs[3](x)
/tmp/ipykernel_331066/1225421420.py in <lambda>(x)
16 funs = [f]
17 for i in range(n):
---> 18 z = lambda x: jax.grad(funs[i])(x)[i]
19 funs.append(z)
20
[... skipping hidden 10 frame]
... last 11 frames repeated, from the frame below ...
/tmp/ipykernel_331066/1225421420.py in <lambda>(x)
16 funs = [f]
17 for i in range(n):
---> 18 z = lambda x: jax.grad(funs[i])(x)[i]
19 funs.append(z)
20
RecursionError: maximum recursion depth exceeded
Any idea how to make this work for any number of variables?
The issue is that i is a global variable, so it takes the value when the function is called, not when the function is defined. If you want the local value of i when the function is defined to be saved, you have to somehow bind it to the function; for example:
funs = [f]
for i in range(n):
z = lambda x, i=i: jax.grad(funs[i])(x)[i]
funs.append(z)
funs[3](x)
The result you're seeing is not anything specific to JAX, but rather comes from how Python variable binding works: when global variables are referenced in functions, the relevant value is not the value when the function is defined, but the value when the function is called. For example:
>>> funs = []
>>> for i in range(3):
... funs.append(lambda: print(i))
>>> print(i)
2
>>> funs[0]()
2
>>> funs[1]()
2
>>> i = 100
>>> funs[0]()
100
Related
I am trying to write a function that will create a list of lambda functions and then passing an array to this list.
I figured out how to hard code this function list, however, I cannot seem to figure out how to use a for loop to create the list.
For example, let's take a very simple function where we multiply every element of A by 1, then 2, then 3, ... and so on so that each row corresponds to the element of A and each column corresponds to the number at which A is multiplied by.
import numpy as np
A = np.array([1,2,3,4])
def f():
F3 = lambda x: 3*x
F2 = lambda x: 2*x
F1 = lambda x: 1*x
F0 = lambda x: 0*x
return lambda x: np.stack((F3(x),F2(x),F1(x),F0(x)),axis=1)
F = f()
F(A)
My output is then.
array([[ 3, 2, 1, 0],
[ 6, 4, 2, 0],
[ 9, 6, 3, 0],
[12, 8, 4, 0]])
The code above only goes to 3*x. What would I do if I want to follow the pattern to n*x? My basic idea would be as follows (however, this does not work):
import numpy as np
A = np.array([1,2,3,4])
def _f():
return lambda x: n*x
def f(N):
F = []
for n in range(N):
F.append(lambda x: _f(n))
return np.array(F)
F = f(5)
F(A)
In real life, my function _f() is far more complicated. The motivation behind this is that I would rather have my program iterate through each _f only once and then perform the calculation F(A) in one shot.
The desired output of can be achieved by the following code, however, this will iterate through the loop each time F is called.
import numpy as np
A = np.array([1,2,3,4])
def _f(n,x):
return n*x
def f(N,x):
F = []
for n in range(N):
F.append(_f(n,x))
return np.array(F)
F = f(5,A)
print(F.T)
This would return:
[[ 0 1 2 3 4]
[ 0 2 4 6 8]
[ 0 3 6 9 12]
[ 0 4 8 12 16]]
This loop is broken:
for n in range(N):
F.append(lambda x: _f(n))
because n is lazily read in the body of the function (so all the functions stored read the final value of n from the loop).
The easiest fix is to bind n as a default argument; default arguments are bound eagerly at definition time:
for n in range(N):
F.append(lambda x, n=n: _f(n))
^^^^^ Changed part
If you want to avoid the default argument, make your factory function do the eager binding for you:
def _f(n): # Now receives n as an argument to outer function
return lambda x: n*x # While inner function uses n from closure and x passed when called
then use it with:
for n in range(N):
F.append(_f(n))
_f (properly defined; it should take n as an argument rather than treating n as a global variable) is already the function which, when called, returns your desired function.
# Or _f = lambda n: lambda x: n * x
def _f(n):
return lambda x: n * x
F = [_f(n) for n in range(N)]
That said, you can avoid lambda expressions and their scoping issues altogether by using functools.partial:
from functools import partial
from operator import mul
F = [partial(mul, n) for n in range(N)]
I am learning python program syntax and do not have too much program experience. I have trouble to understand the statement that show in the title. I find a relevant piece of code to explain the statement, but I still can not understand it clearly.
Can anyone illustrate the statement according to the code ,please? Also briefly explain the difference between runtime and definition time? I try to google the the terminology of definition time, but I do not get a comprehend answer.
>>> x = 10
>>> a = lambda y: x + y
>>> x = 20
>>> b = lambda y: x + y
>>>
when I call the function a with argument 10, I get a unexpected result.
>>> a(10)
30 # why the result is not 20,30 respectively ?
>>> b(10)
30
>>>
Think of it this way. When a function is invoked, if a variable used in it, is not defined in it, then it will go to the previous level and try to find the variable there. If it is not there, then go up and the searching continues till the top level is reached.
In your case, when you do
>>> a(10)
the function a is executed and it is not able to find x in it, and it goes up one level and finds x there. The current value of x is 20. That is why you are getting 30.
Check out the following examples, they might help you understand this better.
>>> x = 10
>>> a = lambda y: x + y
>>> a(10)
20
>>> x = 20
>>> a(10)
30
Also this
>>> a = lambda y: z + y
>>> a(10)
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "<input>", line 1, in <lambda>
NameError: name 'z' is not defined
>>> z = 20
>>> a(10)
30
In the second example, z is not even defined when a is defined. But when you invoke a the second time, z is defined in the previous namespace.
b = lambda y: x + y
is effectively the same as
def b(y):
return x + y
When x is not found in the local namespace (i.e., within the function or its arguments), Python looks for it in the "parent" namespace, where it is equal to 20 at the time the functions are called.
Because you have later on defined x as being equal to 20.
So the later value of x is 20,
So when you do
>>> a = lambda y: x + y
then x is 20, because you have called the print function after declaring the new value of x.
If you want to see your answer as 20, you should call a(20), just after
>>> x = 10
>>> a = lambda y: x + y
>>> a(10)
20
The body of a function, whether defined with lambda or def, does not bind vaariables until the function is run (it does bind scope, so running it elsewhere doesn't pick up someone else's x).
If you want definition time binding, you can fake it a bit with default arguments:
a = lambda y, x=x: x + y
So when called with one argument, it uses the definition time value of x.
When you defined your a = lambda y: x+y, x at definition time of a was equal to 10, but after you re-defined x to be 20, at running time of a(x), it will take the last value defined to x (at run time which is 20 and not 10), which will gives a(10) = x + y = 20 + 10 = 30
There are two examples.
# 1st example
>>> def accum(sum, a):
return sum + a
>>> sum = 0
>>> for sum in iter(lambda:accum(sum, 2), 40):
print sum,
2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32...
# 2nd example
>>> def accum(sum, a):
return sum + a
>>> sum = 0
>>> for sum in iter(accum(sum, 2), 40):
print sum,
TypeError: iter(v, w) : v must be callable
Why lambda function doesn't make error but accum function makes error?
Thanks in advance :)
In neither case you are passing a function that takes arguments. In second case the value of v is bound to the integer 2, whereas in the first case v refers to a callable anonymous lambda function () -> sum + a.
The following 2 are almost equivalent:
def x():
return sum + a
x = lambda: sum + a
except lambda does not provide nice debugging traceback, since lambda functions are unnamed.
Also, the names of the variables are a bit misleading, took me a some moments to figure out what is happening. There are exactly 2 variables called sum - the one within accum function, and the other in the global scope. There is also the 3rd, masked one that contains the global built-in function sum...
The lambda is an anonymous function and is callable. If the notation is confusing, you can replace it with a named function:
def wrapper():
return accum(sum, 2)
for sum in iter(wrapper, 40):
The v argument must be callable. The result of accum(sum, 2) is an integer, which isn't callable.
In one of the training parts of my course I was given the following question:
Write a function make_multiplier(factor) that returns a function which takes an argument x and which should return factor * x.
For example:
f=make_multiplier(10)
f(1)
10
f(2)
20
I have absolutely no idea where to start with this one; I have scrummaged through all my notes and cant find anything useful.
Could someone please give me a hint or point me in the right direction of what I need to do?
Here is a function that returns a function:
def foo():
def bar():
return 42
return bar
You can call it like so:
foo()() # 42
# or
baz = foo()
baz() # 42
There's your hint.
Dead simple, just nest your functions:
def make_multiplier(x):
def multiplier(y):
return x * y
return multiplier
Nested functions automatically look up unknown variables (x in this case) from their surrounding scope, using the value of x as it was when the outer function was called. The thing to remember here is that functions are just objects too, you can store them in a variable just like you can with other python objects, and defer calling them.
This gives:
>>> def make_multiplier(x):
... def multiplier(y):
... return x * y
... return multiplier
...
>>> f = make_multiplier(10)
>>> f(1)
10
>>> f(2)
20
>>> g = make_multiplier(5)
>>> g(1)
5
>>> f(3)
30
Note how g was given a different value for x, which is independent from the value for x in f.
You could use a lambda as well; lambdas are just anonymous functions limited to one expression; that's enough here:
def make_multiplier(x):
return lambda y: x * y
Another alternative technique is binding x to a keyword parameter, which means you could override it if you so wish:
def make_multiplier(x):
def multiply(y, x=x):
return x * y
return multiply
or the lambda version:
def make_multiplier(x):
return lambda y, x=x: x * y
and then pass in one or two arguments to the returned callable:
>>> f = make_multiplier(10)
>>> f(5)
50
>>> f(5, 3)
15
In addition to Matt Ball or Martijn Pieters closure methods (which is the right answer in this particular case) there are two other forms that you will see that are worth recognizing in Python.
The first is using a lambda anonymous function:
>>> f=lambda x: x*10
>>> f(1)
10
>>> f(2)
20
The second is writing a class:
class Multiplyby:
def __init__(self,x):
self.x=x
def __call__(self,y):
return self.x*y
fx10=Multiplyby(10)
fx5=Multiplyby(5)
for y in [1,2,3]:
print y, fx10(y), fx5(y)
prints:
1 10 5
2 20 10
3 30 15
Using lambdas:
>>> make_multiplier = lambda n: lambda x: x * n
>>> make_multiplier(10)(5)
50
10000000 loops, best of 3: 0.189 usec per loop
Using stdlib:
import functools
import operator
f = lambda n: functools.partial(operator.mul, n)
10000000 loops, best of 3: 0.148 usec per loop
I'm not recommending this, I'm just showing what's possible in point-lessfree style:
>>> from functools import partial
>>> from operator import mul
>>> make_multiplier = partial(partial, mul)
>>> f = make_multiplier(10)
>>> f(1)
10
>>> f(2)
20
Hi I am new to functional programming. What i did is
>>> g=lambda x:x*2
>>> f=g
>>> g=lambda x:f(f(x))
>>> g(9)
36
Now, it is not creating g as a nonterminating recursive function - g(x) is transformed to a new function which gives the result g(g(x)).
>>> f=g
>>> g=lambda x:f(f(x))
>>> f(8)
RuntimeError: maximum recursion depth exceeded
I expected g to be transformed into a function which gives the result g(g(g(x))), according to the first definition of g(x). Why does it not? Is it possible to make a new function which results in g(g(g(...(g(x))....))) for a certain number of iterations in this way?
When you do f = g for the second time, f becomes lambda x: f(x). Closures are created by name, not by value.
This becomes easy with a helper function:
def compose(f, g):
return lambda x: f(g(x))
square = lambda x:x*2
g = square
for i in xrange(4):
g = compose(g, square)
In python, variables are names mapped to values, not values themselves (everything is a reference). Also, you can think of lambda as storing text that can be evaluated. The following will illustrate
a = 2
f = lambda x: a*x
f(2) # This gives 4
a = 3
f(2) # This gives 6
This should clear up why you are getting infinite recursion.
In answer to your question about recursing, here is a little hack that might do
g = lambda x, n: n > 0 and g(x, n-1)**2 or x
Then g(2,3) would be (((2)^2)^2)^2 = 256.
This
g=lambda x:x*2
f=g
g=lambda x:f(x)
is equivalent to:
f=lambda x:x*2
g=lambda x:f(x)
When you call g, you get whatever f happens to be defined in the global (or enclosing) scope.
what you're expecting is something like:
f=lambda x:x*2
g=lambda x, f=f:f(x)
That captures the value of f in the outer scope at the time the lambda expression is evaluated.