python 中 ReLU 函数的 ValueError

ValueError with ReLU function in python

我这样声明 ReLU 函数:

def relu(x):
    return (x if x > 0 else 0)

并且发生了 ValueError,其回溯消息是

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

但是如果我用 numpy 改变 ReLU 函数,它就起作用了:

def relu_np(x):
    return np.maximum(0, x)

为什么这个功能(relu(x))不起作用?看不懂...

==================================

使用代码:

>>> x = np.arange(-5.0, 5.0, 0.1)
>>> y = relu(x)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "filename", line, in relu
    return (x if x > 0 else 0)
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

请记住,x > 0 是一个布尔值数组,如果您愿意,可以是掩码:

array([False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False, False, False, False,
       False, False, False, False, False, False, False, False, False,
       False, False, False, False, False,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True,  True,  True,  True,  True,  True,  True,  True,  True,
        True])

所以 if x>0 没有意义,因为 x 包含多个元素,可以是 TrueFalse。这是您的错误来源。

你的 numpy 的第二个实现很好!另一个实现(也许更清楚?)可能是:

def relu(x):
  return x * (x > 0)

在此实现中,我们对 x 进行逐元素乘法,x 是沿 x 轴的一系列值,如果 x 的元素低于 0,则乘以 0,如果元素高于 0,则乘以 1。

免责声明:如果我错了,请有人纠正我,我不是 100% 确定 numpy 是如何做的。

您的函数 relu 需要一个数值并将其与 0 和 returns 中较大的数值进行比较。 x if x > 0 else 0 等于 max(x, 0) 其中 max 是一个内置的 Python 函数。

relu_np 另一方面使用 numpy 函数 maximum 接受 2 个数字 or 数组 or可迭代对象。这意味着您可以传递您的 numpy 数组 x,它会自动将最大函数应用于每个项目。我相信这叫做 'vectorized'.

要使 relu 函数按原样工作,您需要以不同的方式调用它。您必须手动将函数应用于每个元素。你可以做类似 y = np.array(list(map(relu, x))).

的事情

TLDR; 你的第一个函数没有使用矢量化方法,这意味着它需要一个 float/int 值作为输入,而你的第二个函数利用了 Numpy 的矢量化。

NumPy 中的向量化

你的第二个函数使用了向量化的 numpy 函数,并且 运行 对数组的每个单独元素进行处理。

import numpy as np

arr = np.arange(-5.0, 5.0, 0.5)

def relu_np(x):
    return np.maximum(0, x)

relu_np(arr)

# array([0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0.5, 1. ,
#        1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5])

然而,您的第二个函数使用三元运算符 (x if x > 0 else 0),它需要一个单一的值输入并输出一个单一的值。这就是为什么当您传递单个元素时,它会起作用,但在传递数组时它无法 运行 独立地对每个元素执行函数。

def relu(x):
    return (x if x > 0 else 0)

relu(-8)

## 0

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

Note: The reason for this error is due to the ternary operator you are using (x if x > 0 else 0). The condition x>0 can only take the value True or False for a given integer/float value. However, when you pass an array, you will need to use something like any() or all() to aggregate that list of boolean values to a single one, before you can apply your if, else clause.

解决方案-

有几种方法可以完成这项工作 -

1。使用 np.vectorize(不推荐,性能低于纯 numpy 方法)

import numpy as np

arr = np.arange(-5.0, 5.0, 0.5)

def relu(x):
    return (x if x > 0.0 else 0.0)

relu_vec = np.vectorize(relu)
relu_vec(arr)

# array([0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0.5, 1. ,
#        1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5])

2。使用列表理解迭代数组

import numpy as np

arr = np.arange(-5.0, 5.0, 0.5)

def relu(x):
    return (x if x > 0 else 0)

arr = np.array(arr)

np.array([relu(i) for i in arr])

# array([0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0. , 0.5, 1. ,
#        1.5, 2. , 2.5, 3. , 3.5, 4. , 4.5])