Home > Enterprise >  How to vectorize a function that reduces an array to a scalar—or shut off the warning message?
How to vectorize a function that reduces an array to a scalar—or shut off the warning message?

Time:04-29

I'm making a surface plot of the LogSumExp function. This function is similar to max, in that it takes a set of numbers and returns (approximately) the maximum of those numbers; unlike max, the LogSumExp function is smooth. To understand the LogSumExp function, I'd like to see it plotted with inputs consisting of sets of just two numbers, serving as the x and y coordinates of a surface plot.

The following code:

function lse = lse(x)
   lse = log(sum(exp(x)));
end

fsurf(@(x,y) lse([x y]))

plots the graph (success!) but produces this warning message:

Warning: Function behaves unexpectedly on array inputs. To improve
performance, properly vectorize your function to return an output with
the same size and shape as the input arguments. 
> In matlab.graphics.function.FunctionSurface>getFunction
In matlab.graphics.function/FunctionSurface/updateFunction
In matlab.graphics.function/FunctionSurface/set.Function
In matlab.graphics.function.FunctionSurface
In fsurf>singleFsurf (line 267)
In fsurf>@(f)singleFsurf(cax,{f},extraOpts,args) (line 233)
In fsurf>vectorizeFsurf (line 233)
In fsurf (line 206) 

From Internet searches and other StackOverflow answers, I've learned that fsurf tries to pass a vector directly to the function in order to get a vector back, because that yields faster performance than calling the function once for every (x, y) pair.

The LogSumExp function, however, by definition reduces a vector to a scalar, so I'm not even sure that it is possible to vectorize it.

Is there a way to vectorize LogSumExp? If not, is there a way to prevent the warning message?

CodePudding user response:

Consider the max function. It can be used in two ways (or variations thereof):

  1. max(x, y) computes the element-wise maximum of x and y:

    >> max([10 20], [0 30]) 
    ans =
        10    30
    
  2. max(x, [], n) computes the maximum of x along its dimension n:

    >> max([10 20; 0 30], [], 1)
    ans =
        10    30
    

You have defined your lse function using the first approach. However, the second is more suited to vectorization. To define lse using the second approach, note that sum also works that way, with the syntax sum(x, n):

function lse = lse(x, n)
   lse = log(sum(exp(x), n));
end

The anonymous function passed to fsurf can then be defined as @(x,y) lse(cat(3, x, y), 3), using the fact that the arguments x, y with which fsurf will call it are matrices (i.e. 2 dimensions). Thus,

fsurf(@(x,y) lse(cat(3, x, y), 3))

produces the plot without warnings:

enter image description here

  • Related