How to apply a function / map values of each element in a 2d numpy array/matrix?
Given the following numpy matrix:
import numpy as np
mymatrix = np.matrix('-1 0 1; -2 0 2; -4 0 4')
matrix([[-1, 0, 1],
[-2, 0, 2],
[-4, 0, 4]])
and the following function (sigmoid/logistic):
import math
def myfunc(z):
return 1/(1+math.exp(-z))
I want to get a new NumPy array/matrix where each element is the result of applying the myfunc
function to the corresponding element in the original matrix.
the map(myfunc, mymatrix)
fails because it tries to apply myfunc to the rows not to each element. I tried to use numpy.apply_along_axis
and numpy.apply_over_axis
but they are meant also to apply the function to rows or columns and not on an element by element basis.
So how can apply myfunc(z)
to each element of myarray
to get:
matrix([[ 0.26894142, 0.5 , 0.73105858],
[ 0.11920292, 0.5 , 0.88079708],
[ 0.01798621, 0.5 , 0.98201379]])
Solution 1:
Apparently, the way to apply a function to elements is to convert your function into a vectorized version that takes arrays as input and return arrays as output.
You can easily convert your function to vectorized form using numpy.vectorize
as follows:
myfunc_vec = np.vectorize(myfunc)
result = myfunc_vec(mymatrix)
or for a one shot usage:
np.vectorize(myfunc)(mymatrix)
As pointed out by @Divakar, it's better (performance-wise) if you can write an already vectorized function from scratch (using NumPy built ufuncs without using numpy.vectorize
) like so:
def my_vectorized_func(m):
return 1/(1+np.exp(-m)) # np.exp() is a built-in ufunc
my_vectorized_func(mymatrix)
Since numpy.exp
is already vectorized (and math.exp
wasn't) the whole expression 1/(1+np.exp(-m))
will be vectorized (and faster that applying my original function to each element).
The following complete example produced the required output:
import numpy as np
mymatrix = np.matrix('-1 0 1; -2 0 2; -4 0 4')
import math
def myfunc(z):
return 1/(1+math.exp(-z))
np.vectorize(myfunc)(mymatrix) # ok, but slow
def my_vectorized_func(m):
return 1/(1+np.exp(-m))
my_vectorized_func(mymatrix) # faster using numpy built-in ufuncs
Solution 2:
Just in case this helps, scipy has a sigmoid function you can directly call on a matrix.