Re: Plotting an ELU function with GNU Octave

Juan Pablo Carbajal <[email protected]>
Newsgroups gmane.comp.gnu.octave.general
Message-ID <CABDtPkSNXT1yD_n8xJ06gMLeiWh4crGwjkSthfU3pxgF-94ycw@mail.gmail.com>
On Thu, Feb 4, 2021 at 8:53 PM Brett Green <[email protected]> wrote:
>
>
> On Thu, Feb 4, 2021 at 2:27 PM Alexandru Munteanu <[email protected]> wrote:
>>
>> Hello,
>>
>> I am trying to create plots for an ELU (Exponential Liniear Unit)
>> funciton. The function is defined as follows:
>>
>> function e = elu(z, alpha)
>>   if z >= 0
>>     e = z
>>   else
>>     e = alpha * ((exp(z)) - 1)
>>   endif
>> endfunction
>>
>> So this is pretty simple so far (alpha is a constant of values 0.01),
>> and I can test to evaluate it in the interpreter and everything is
>> working as expected.
>>
>>
>> However, I want to plot the values of elu(x), where x belongs to the
>> interval (-5, 5).
>>
>> function plot_elu
>>   x = -5:0.01:5
>>   y = elu(x, 0.01)
>>
>>   plot(x, y, "linewidth", 5)
>>   set(gca,"fontsize", 25)
>>   axis([-6, 6, -1.2, 1.2])
>>   grid on;
>> endfunction
>>
>> This is where the plot goes wrong: it creates the plot as if the values
>> for elu are all going on the second branch of the if-then-else
>> statement.
>>
>> I have attached what the plot looks like. Any help in this direction is appreciated.
>>
>> --
>> Alexandru Munteanu
>>
>
> The if statement does not operate elementwise, which is the cause of your problem. The expression
>
> y = (x>=0).*x + (x<0).*alpha.*(exp(x)-1)
>
> is essentially an elementwise if-else statement.
>
> Try something more like this.
>
> x = -5:0.01:5
> alpha = 0.01
> y = (x>=0).*x + (x<0).*alpha.*(exp(x)-1)
> plot(x, y, "linewidth", 5)
> set(gca,"fontsize", 25)
> axis([-6, 6, -1.2, 1.2])
> grid on
>
> - Brett Green

That solution is perfectly acceptable for this case. However if the
computational cost of the different branches of your function is not
that low you could use a mask, e.g.

y = zeros(size(x));  # allocate space for the answer (needed for the
mask to work)
x_ge_zero = (x >= 0);  # this is the mask. Parenthesis are not needed
y(x_ge_zero) = x(x_ge_zero);  # y(x) = x if x >=0
y(!x_ge_zero) = alpha .* expm1 (x(!x_ge_zero));  # y(x) = exp(x) - 1
if x < 0. Use expm1 instead of exp(x) - 1

This approach also has the advantage that you can do boolean
operations on the mask.

x_abs_gt_one = abs(x) > 1
msk = x_abs_gt_one & x_ge_zero  # x is non-negative and with absolute
value bigger than 1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.