背景
我已经训练出了一种卷积神经网络,希望其他人能够使用它,而不需要像Theano这样难以安装的库(我在Linux上发现安装简单,但在Windows上非常困难)。
我使用Numpy/Scipy编写了一个实现,速度几乎足够快,但如果能再快两三倍就更好了。
我的尝试
以下代码的执行占用了90%的时间:
conv_out = np.sum([scipy.signal.convolve2d(x[i],W[f][i],mode='valid') for i in range(num_in)], axis=0)
这一行会被调用32次(每个特征图调用一次),num_in是16(上一层的特征数)。因此,这一行总体上较慢,因为它会导致convolve2d例程被调用32*16=512次。
x[i]仅为25*25,而W[f][i]为2*2。
问题
有没有更好的在Numpy/Scipy中表示此类型卷积层的方法可以更快地执行?
(我仅使用此代码来应用学习到的网络,因此我没有大量需要并行处理的图像。)
代码
进行时序实验的完整代码如下:
import numpy as np
import scipy.signal
from time import time
def max_pool(x):
"""Return maximum in groups of 2x2 for a N,h,w image"""
N,h,w = x.shape
return np.amax([x[:,(i>>1)&1::2,i&1::2] for i in range(4)],axis=0)
def conv_layer(params,x):
"""Applies a convolutional layer (W,b) followed by 2*2 pool followed by RelU on x"""
W,biases = params
num_in = W.shape[1]
A = []
for f,bias in enumerate(biases):
conv_out = np.sum([scipy.signal.convolve2d(x[i],W[f][i],mode='valid') for i in range(num_in)], axis=0)
A.append(conv_out + bias)
x = np.array(A)
x = max_pool(x)
return np.maximum(x,0)
W = np.random.randn(32,16,2,2).astype(np.float32)
b = np.random.randn(32).astype(np.float32)
I = np.random.randn(16,25,25).astype(np.float32)
t0 = time()
O = conv_layer((W,b),I)
print time()-t0
此时打印出0.084秒。
更新
采用mplf的建议:
d = x[:,:-1,:-1]
c = x[:,:-1,1:]
b = x[:,1:,:-1]
a = x[:,1:,1:]
for f,bias in enumerate(biases):
conv_out = np.sum([a[i]*W[f,i,0,0]+b[i]*W[f,i,0,1]+c[i]*W[f,i,1,0]+d[i]*W[f,i,1,1] for i in range(num_in)], axis=0)
我得到了0.075秒,略快一些。
0.024
,然后在搭载 Python 3.4 的 Windows 10 笔记本电脑 i5 4200M 上,在足够多的后台应用程序下使 CPU 利用率保持在 20%,结果为0.018-0.020
。你使用的是什么硬件/操作系统? - IVlad(i>>1)&1::2, i&1::2
部分的提示吗? 我可以看到最终效果是以步长2采样2x2网格,但不太明白位运算部分。 如何将其推广到步长为s
的最大nxn
? - Jason