How to apply a function / map values of each element in a 2d numpy array/matrix?

Numpy

Numpy Problem Overview


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

Numpy Solutions


Solution 1 - Numpy

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 - Numpy

Just in case this helps, scipy has a sigmoid function you can directly call on a matrix.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionRubenLagunaView Question on Stackoverflow
Solution 1 - NumpyRubenLagunaView Answer on Stackoverflow
Solution 2 - NumpymithunpaulView Answer on Stackoverflow