With Matlab I am trying to evaluate differential entropies. These are integrals like
$$\int_\mathbb{R} p(x) \log (p(x)) \mathrm{d}x$$
where $p(x)$ is a probability density function. My $p(x)$ is computed by an external function. I tried to define
g = @(x) x.*log(x);
and compute the entropy using
integral(@(x) g(p(x)),0,inf)
(my $p(x)$ is defined on $[0;+\infty)$). But this fails due to NaN issues. However, even if I take the precaution to define g as an external function and set NaN outputs to zero by a conditional statement, the computation fails. Why?
Consider the following simple example:
I define g as an external function to avoid the $0 \log 0$ issue as follows:
function y = g(x)
if isnan(x.*log(x))
y = 0;
else
y = x.*log(x);
end
Now let's try to compute the entropy integral for $p(x) = e^{-x}$, which should obviously return $-1$. But it doesn't:
>> p = @(x) exp(-x);
>> integral(@(x) g(p(x)),0,inf)
Warning: Infinite or Not-a-Number value encountered.
> In funfun/private/integralCalc>iterateScalarValued at 349
In funfun/private/integralCalc>vadapt at 133
In funfun/private/integralCalc at 84
In integral at 89
What is Matlab's problem?
The reason is because you've not defined your function
gcorrectly in Matlab. The way it's written will not trapNaNcases. As per the documentation for theintegralfunction:The
integralfunction is vectorized and passes multiple values to your integrand function on each iteration. You've correctly vectorizedx.*log(x), but yourifstatement that checks forNaNwill only be triggered if the first element happens to beNaN. Using so-called logical indexing, you can rewritegconcisely asThen the following code
now returns
-1.000000000000000.Also, though it may not be numerically scaled as well, you could use the mathematically equivalent
g = @(x)log(x.^x);instead, which cannot evaluate toNaN.