如何在Numpy中实现ReLU函数
How to implement the ReLU function in Numpy
我想制作一个使用 ReLU 函数的简单神经网络。有人可以告诉我如何使用 numpy 实现该功能吗?
有几种方法。
>>> 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]])
如果使用以下代码对结果进行计时:
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
我们得到:
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
所以乘法似乎是最快的。
由于其他问题和评论中提出的要点,我正在完全修改我的原始答案。这是新的基准测试脚本:
import time
import numpy as np
def fancy_index_relu(m):
m[m < 0] = 0
relus = {
"max": lambda x: np.maximum(x, 0),
"in-place max": lambda x: np.maximum(x, 0, x),
"mul": lambda x: x * (x > 0),
"abs": lambda x: (abs(x) + x) / 2,
"fancy index": fancy_index_relu,
}
for name, relu in relus.items():
n_iter = 20
x = np.random.random((n_iter, 5000, 5000)) - 0.5
t1 = time.time()
for i in range(n_iter):
relu(x[i])
t2 = time.time()
print("{:>12s} {:3.0f} ms".format(name, (t2 - t1) / n_iter * 1000))
每次实现和迭代都需要注意使用不同的 ndarray。以下是结果:
max 126 ms
in-place max 107 ms
mul 136 ms
abs 86 ms
fancy index 132 ms
EDIT 正如 jirassimok 在下面提到的那样,我的函数将就地更改数据,之后它在 timeit 中运行得更快。这导致了良好的结果。这是一种欺骗。很抱歉给您带来不便。
我发现了一种使用 numpy 的更快的 ReLU 方法。您也可以使用 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. ]])
这是我的基准:
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)
你可以用更简单的方法来做到这一点:
def ReLU(x):
return x * (x > 0)
def dReLU(x):
return 1. * (x > 0)
这是更精确的实现:
def ReLU(x):
return abs(x) * (x > 0)
不公平。
由于,in-place方法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
计时:
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()
得到结果:
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
In-placemaximum 方法只比maximum 方法快一点,可能是因为它省略了'out' 的变量赋值。而且还是比乘法慢
并且由于您正在实施 ReLU 函数。您可能必须通过 relu 为反向传播保存 'x'。例如:
def relu_backward(dout, cache):
x = cache
dx = np.where(x > 0, dout, 0)
return dx
所以我推荐你使用乘法。
如果Relu有3个参数(t0, a0, a1)
,那就是我们要实现
if x > t0:
x = x * a1
else:
x = x * a0
我们可以使用下面的代码:
X = X * (X > t0) * a1 + X * (X < t0) * a0
X
有矩阵
numpy没有relu的功能,你自己定义如下:
def relu(x):
return np.maximum(0, x)
例如:
arr = np.array([[-1,2,3],[1,2,3]])
ret = relu(arr)
print(ret) # print [[0 2 3] [1 2 3]]
ReLU(x) 也等于 (x+abs(x))/2
我想制作一个使用 ReLU 函数的简单神经网络。有人可以告诉我如何使用 numpy 实现该功能吗?
有几种方法。
>>> 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]])
如果使用以下代码对结果进行计时:
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
我们得到:
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
所以乘法似乎是最快的。
由于其他问题和评论中提出的要点,我正在完全修改我的原始答案。这是新的基准测试脚本:
import time
import numpy as np
def fancy_index_relu(m):
m[m < 0] = 0
relus = {
"max": lambda x: np.maximum(x, 0),
"in-place max": lambda x: np.maximum(x, 0, x),
"mul": lambda x: x * (x > 0),
"abs": lambda x: (abs(x) + x) / 2,
"fancy index": fancy_index_relu,
}
for name, relu in relus.items():
n_iter = 20
x = np.random.random((n_iter, 5000, 5000)) - 0.5
t1 = time.time()
for i in range(n_iter):
relu(x[i])
t2 = time.time()
print("{:>12s} {:3.0f} ms".format(name, (t2 - t1) / n_iter * 1000))
每次实现和迭代都需要注意使用不同的 ndarray。以下是结果:
max 126 ms
in-place max 107 ms
mul 136 ms
abs 86 ms
fancy index 132 ms
EDIT 正如 jirassimok 在下面提到的那样,我的函数将就地更改数据,之后它在 timeit 中运行得更快。这导致了良好的结果。这是一种欺骗。很抱歉给您带来不便。
我发现了一种使用 numpy 的更快的 ReLU 方法。您也可以使用 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. ]])
这是我的基准:
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)
你可以用更简单的方法来做到这一点:
def ReLU(x):
return x * (x > 0)
def dReLU(x):
return 1. * (x > 0)
这是更精确的实现:
def ReLU(x):
return abs(x) * (x > 0)
由于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
计时:
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()
得到结果:
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
In-placemaximum 方法只比maximum 方法快一点,可能是因为它省略了'out' 的变量赋值。而且还是比乘法慢
并且由于您正在实施 ReLU 函数。您可能必须通过 relu 为反向传播保存 'x'。例如:
def relu_backward(dout, cache):
x = cache
dx = np.where(x > 0, dout, 0)
return dx
所以我推荐你使用乘法。
如果Relu有3个参数(t0, a0, a1)
,那就是我们要实现
if x > t0:
x = x * a1
else:
x = x * a0
我们可以使用下面的代码:
X = X * (X > t0) * a1 + X * (X < t0) * a0
X
有矩阵
numpy没有relu的功能,你自己定义如下:
def relu(x):
return np.maximum(0, x)
例如:
arr = np.array([[-1,2,3],[1,2,3]])
ret = relu(arr)
print(ret) # print [[0 2 3] [1 2 3]]
ReLU(x) 也等于 (x+abs(x))/2