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):
max(x, y)
computes the element-wise maximum ofx
andy
:>> max([10 20], [0 30]) ans = 10 30
max(x, [], n)
computes the maximum ofx
along its dimensionn
:>> 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: