2

我这样声明 ReLU 函数:

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

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

ValueError:具有多个元素的数组的真值不明确。使用 a.any() 或 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()
4

3 回答 3

2

TLDR;你的第一个函数没有使用向量化方法,这意味着它需要一个浮点/整数值作为输入,而你的第二个函数利用了 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()

注意:此错误的原因是由于您使用的三元运算符(x if x > 0 else 0)。条件x>0只能取值TrueFalse给定的整数/浮点值。但是,当您传递一个数组时,您需要使用类似的东西any()all()将该布尔值列表聚合为一个,然后才能应用您的 if, else 子句。

解决方案 -

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

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])
于 2022-01-26T09:22:57.273 回答
1

请记住,这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 包含几个元素,可以是Trueor False。这是你错误的根源。

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

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

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

于 2022-01-26T09:12:17.710 回答
1

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

您的函数relu需要一个数值并将其与 0 进行比较并返回较大的值。x if x > 0 else 0将等于max(x, 0)where maxis a builtin Python 函数。

relu_np另一方面,使用maximum接受 2 个数字数组可迭代的 numpy 函数。这意味着您可以传递您的 numpy 数组x,它会自动将最大函数应用于每个项目。我相信这被称为“矢量化”。

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

于 2022-01-26T09:12:28.353 回答