0

I can't figure out why my relu function doesn't work but squarer works, how is it different?

import numpy as np

x = np.array([1, 2, 3, 4, 5])

squarer = lambda x: x ** 2
squarer(x)
# array([ 1,  4,  9, 16, 25])

relu = lambda x : 0 if x <= 0 else x
relu(x)
# ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
9
  • What don't you understand about the value of x <= 0? Commented Aug 9, 2021 at 19:57
  • The reason "squarer" works is that the ** operator automatically maps over its LHS (and maybe RHS, two). The "0 if x..." expression does not, so x is taken to be an array, and you get your error. Commented Aug 9, 2021 at 20:00
  • 1
    To write an if test in vectorized form, you could use np.where: relu = lambda x : np.where(x <= 0, 0, x) Commented Aug 9, 2021 at 20:00
  • @hpaulj I thought when applying relu or square to np.array, python will iterate over each element and apply the lambda function Commented Aug 9, 2021 at 20:08
  • 1
    @Raftel np.where is vectorized, while [relu(a) for a in x] goes one by one and has the overhead of creating a Python list. Especially for larger arrays, np.where is much faster. Commented Aug 9, 2021 at 20:21

1 Answer 1

1
In [6]: x = np.array([1, 2, 3, 4, 5])
   ...: 
   ...: squarer = lambda x: x ** 2
   ...: squarer(x)
Out[6]: array([ 1,  4,  9, 16, 25])

The lambda is just a function definition, and is equivalent of doing:

In [7]: x**2
Out[7]: array([ 1,  4,  9, 16, 25])

The function layer doesn't add any iteration. It's the power method of the x array that's doing the elementwise iteration.

In [8]: relu = lambda x : 0 if x <= 0 else x

Similarly the relu does not add any iteration; it's scalar python if/else clause.

In [13]: x = np.arange(-3,4)
In [14]: x
Out[14]: array([-3, -2, -1,  0,  1,  2,  3])

It can be applied to elements of x with a list comprehension:

In [15]: [relu(i) for i in x]
Out[15]: [0, 0, 0, 0, 1, 2, 3]

Arrays have a lt method, so:

In [16]: x<=0
Out[16]: array([ True,  True,  True,  True, False, False, False])

It can be use in masked way:

In [17]: x1=x.copy()
In [18]: x1[x<=0] = 0
In [19]: x
Out[19]: array([-3, -2, -1,  0,  1,  2,  3])
In [20]: x1
Out[20]: array([0, 0, 0, 0, 1, 2, 3])

Or via a where:

In [22]: np.where(x<=0, 0,x)
Out[22]: array([0, 0, 0, 0, 1, 2, 3])

where isn't an iterator either. It is effectively the same thing as the [17][18] lines.

Using an array in a if expression amounts to trying to convert it to a scalar boolean:

In [24]: if x<=0:x
Traceback (most recent call last):
  File "<ipython-input-24-6cecebf070dc>", line 1, in <module>
    if x<=0:x
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

In [25]: bool(x<=0)
Traceback (most recent call last):
  File "<ipython-input-25-f1a519ed746f>", line 1, in <module>
    bool(x<=0)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

It works it the array has only one element, but otherwise it raises this ambiguity error:

In [26]: bool(np.array(1)<=0)
Out[26]: False

but for "empty" array:

In [28]: bool(np.array([])<=0)
<ipython-input-28-03e1626841fc>:1: DeprecationWarning: The truth value of an empty array is ambiguous. Returning False, but in future this will result in an error. Use `array.size > 0` to check that an array is not empty.
  bool(np.array([])<=0)
Out[28]: False

But testing for a 'empty' list is ok:

In [29]: bool([])
Out[29]: False
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.