如何在Numpy中实现ReLU功能

And*_*eta 55 python numpy machine-learning neural-network

我想制作一个简单的神经网络,我希望使用ReLU功能.有人能告诉我如何使用numpy实现该功能.谢谢你的时间!

Sid*_*Sid 99

有几种方法.

>>> x = np.random.random((3, 2)) - 0.5
>>> x
array([[-0.00590765,  0.18932873],
       [-0.32396051,  0.25586596],
       [ 0.22358098,  0.02217555]])
>>> np.maximum(x, 0)
array([[ 0.        ,  0.18932873],
       [ 0.        ,  0.25586596],
       [ 0.22358098,  0.02217555]])
>>> x * (x > 0)
array([[-0.        ,  0.18932873],
       [-0.        ,  0.25586596],
       [ 0.22358098,  0.02217555]])
>>> (abs(x) + x) / 2
array([[ 0.        ,  0.18932873],
       [ 0.        ,  0.25586596],
       [ 0.22358098,  0.02217555]])
Run Code Online (Sandbox Code Playgroud)

如果使用以下代码计时结果:

import numpy as np

x = np.random.random((5000, 5000)) - 0.5
print("max method:")
%timeit -n10 np.maximum(x, 0)

print("multiplication method:")
%timeit -n10 x * (x > 0)

print("abs method:")
%timeit -n10 (abs(x) + x) / 2
Run Code Online (Sandbox Code Playgroud)

我们得到:

max method:
10 loops, best of 3: 239 ms per loop
multiplication method:
10 loops, best of 3: 145 ms per loop
abs method:
10 loops, best of 3: 288 ms per loop
Run Code Online (Sandbox Code Playgroud)

所以乘法似乎是最快的.

  • +1.我冒昧地为你的答案添加一些timeit结果.如果您愿意,请随时编辑或还原编辑. (14认同)
  • np.maximum(x,0,x)在这里运行得最快. (6认同)
  • @丹尼尔S。对于未来的读者:“maximum(x, 0, x)”中的最后一个“x”表示“请就地更改“x”,而不是分配新的矩阵”。([来源](https://numpy.org/doc/stable/reference/ generated/numpy.maximum.html?highlight=max#numpy.maximum)) (2认同)

Ric*_*öhn 37

如果您不介意x进行修改,请使用np.maximum(x, 0, x).丹尼尔S指出了这一点.它要快得多,因为人们可能会忽略它,我会把它作为答案重新发布.这是比较:

max method:
10 loops, best of 3: 238 ms per loop
multiplication method:
10 loops, best of 3: 128 ms per loop
abs method:
10 loops, best of 3: 311 ms per loop
in-place max method:
10 loops, best of 3: 38.4 ms per loop
Run Code Online (Sandbox Code Playgroud)

  • @pikachuchameleon它更快,因为它就位.忽略`np.maximum(x,0,x)`的返回值,结果直接写入`x`. (6认同)
  • 与np.maximum(0,x)相比,np.maximum(x,0,x)如何花费更少的时间? (5认同)
  • 还值得注意的是,这将修改x (5认同)
  • 如果可以选择就地操作,那么正如 [Tobias 的回复](/sf/answers/3278653311/) 中指出的那样,可以有更快的就地操作。 (2认同)

Tob*_*ias 20

我找到了一个更快的ReLU方法和numpy.您也可以使用numpy的花式索引功能.

花式指数:

每循环20.3 ms±272μs(平均值±标准偏差,7次运行,每次10次循环)

>>> x = np.random.random((5,5)) - 0.5 
>>> x
array([[-0.21444316, -0.05676216,  0.43956365, -0.30788116, -0.19952038],
       [-0.43062223,  0.12144647, -0.05698369, -0.32187085,  0.24901568],
       [ 0.06785385, -0.43476031, -0.0735933 ,  0.3736868 ,  0.24832288],
       [ 0.47085262, -0.06379623,  0.46904916, -0.29421609, -0.15091168],
       [ 0.08381359, -0.25068492, -0.25733763, -0.1852205 , -0.42816953]])
>>> x[x<0]=0
>>> x
array([[ 0.        ,  0.        ,  0.43956365,  0.        ,  0.        ],
       [ 0.        ,  0.12144647,  0.        ,  0.        ,  0.24901568],
       [ 0.06785385,  0.        ,  0.        ,  0.3736868 ,  0.24832288],
       [ 0.47085262,  0.        ,  0.46904916,  0.        ,  0.        ],
       [ 0.08381359,  0.        ,  0.        ,  0.        ,  0.        ]])
Run Code Online (Sandbox Code Playgroud)

这是我的基准:

import numpy as np
x = np.random.random((5000, 5000)) - 0.5
print("max method:")
%timeit -n10 np.maximum(x, 0)
print("max inplace method:")
%timeit -n10 np.maximum(x, 0,x)
print("multiplication method:")
%timeit -n10 x * (x > 0)
print("abs method:")
%timeit -n10 (abs(x) + x) / 2
print("fancy index:")
%timeit -n10 x[x<0] =0

max method:
241 ms ± 3.53 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
max inplace method:
38.5 ms ± 4 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
multiplication method:
162 ms ± 3.1 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
abs method:
181 ms ± 4.18 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
fancy index:
20.3 ms ± 272 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
Run Code Online (Sandbox Code Playgroud)

  • (+1)您的奇特方法是我以前真正见过使用过的唯一方法!在我看来,它不仅高效,而且完美地描述了 ReLU 操作。 (2认同)
  • 仅当数组没有负数时,此方法才比其他方法更快;你的测试看起来很快,因为 timeit 修改了数组,所以在第一个循环之后,没有留下负数,并且运行得更快。在每次重新生成数组的测试中,逻辑索引分配(a[a &lt; 0] = 0)在所有方法中执行最差,而 np.maximum 执行得最好。 (2认同)

Shi*_*hah 12

你可以用更容易的方式完成它而不需要numpy:

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

def dReLU(x):
    return 1. * (x > 0)
Run Code Online (Sandbox Code Playgroud)


iva*_*npp 7

Richard Möhn 的比较 是不公平的。
正如Andrea Di Biagio 的评论,就地方法np.maximum(x, 0, x)将在第一个循环中修改 x。

所以这是我的基准:

import numpy as np

def baseline():
    x = np.random.random((5000, 5000)) - 0.5
    return x

def relu_mul():
    x = np.random.random((5000, 5000)) - 0.5
    out = x * (x > 0)
    return out

def relu_max():
    x = np.random.random((5000, 5000)) - 0.5
    out = np.maximum(x, 0)
    return out

def relu_max_inplace():
    x = np.random.random((5000, 5000)) - 0.5
    np.maximum(x, 0, x)
    return x 
Run Code Online (Sandbox Code Playgroud)

计时:

print("baseline:")
%timeit -n10 baseline()
print("multiplication method:")
%timeit -n10 relu_mul()
print("max method:")
%timeit -n10 relu_max()
print("max inplace method:")
%timeit -n10 relu_max_inplace()
Run Code Online (Sandbox Code Playgroud)

获取结果:

baseline:
10 loops, best of 3: 425 ms per loop
multiplication method:
10 loops, best of 3: 596 ms per loop
max method:
10 loops, best of 3: 682 ms per loop
max inplace method:
10 loops, best of 3: 602 ms per loop
Run Code Online (Sandbox Code Playgroud)

就地最大值方法只比最大值方法快一点,这可能是因为它省略了“out”的变量赋值。而且还是比乘法慢。
并且由于您正在实施 ReLU 函数。您可能必须通过 relu 为反向传播保存“x”。例如:

def relu_backward(dout, cache):
    x = cache
    dx = np.where(x > 0, dout, 0)
    return dx
Run Code Online (Sandbox Code Playgroud)

所以我建议你使用乘法方法。