解释numpy的矢量化函数应用程序VS python for for循环之间的速度差异

Kao*_*Kao 13 python performance loops numpy vectorization

我在一组42000张图像上实现了一个称为TF-IDF的加权系统,每个图像包含784个像素.这基本上是42000乘784矩阵.

我尝试的第一种方法是使用显式循环并花费了超过2个小时.

def tfidf(color,img_pix,img_total):
    if img_pix==0:
        return 0
    else:
        return color * np.log(img_total/img_pix)

...

result = np.array([])
for img_vec in data_matrix:
    double_vec = zip(img_vec,img_pix_vec)
    result_row = np.array([tfidf(x[0],x[1],img_total) for x in double_vec])
    try:
        result = np.vstack((result,result_row))
    # first row will throw a ValueError since vstack accepts rows of same len
    except ValueError:
        result = result_row
Run Code Online (Sandbox Code Playgroud)

我试图使用numpy矩阵的第二种方法花了不到5分钟.请注意,data_matrix,img_pix_mat都是42000 x 784矩阵,而img_total是标量.

result = data_matrix * np.log(np.divide(img_total,img_pix_mat))
Run Code Online (Sandbox Code Playgroud)

我希望有人能解释速度上的巨大差异.

题为"NumPy数组:高效数值计算结构"(http://arxiv.org/pdf/1102.1523.pdf)的以下论文的作者在第4页的最上面指出,他们观察到500倍的速度提升由于矢量化计算.我假设我看到的速度增加很多是由于这个原因.但是,我想更进一步,问为什么numpy矢量化计算比标准python循环快得多?

另外,也许你们可能知道为什么第一种方法很慢的其他原因.尝试/除结构有高开销吗?或者为每个循环形成一个新的np.array需要很长时间?

谢谢.

use*_*tar 9

由于numpy的内部工作原理(据我所知,numpy在内部与C一起工作,所以你所有下推到numpy实际上要快得多,因为它是用不同的语言)

编辑:取出zip,并用vstack替换它也应该更快,(如果参数非常大,拉链往往会变慢,而且比vstack更快),(但这也是把它变成numpy的东西)因此进入C),而zip是python)

是的,如果我理解正确 - 不确定那个 - ,你做了42k次尝试/除了块,这肯定会对速度不利,

测试:

T=numpy.ndarray((5,10))
for t in T:
print t.shape
Run Code Online (Sandbox Code Playgroud)

结果(10,)

这意味着是的,如果您的矩阵是42kx784矩阵,那么您尝试42k次尝试除外块,我假设应该在计算时间内产生效果,以及每次都做一次拉链,但不确定如果这是主要原因,

(所以每运行42k次你的东西,需要0.17秒,我很确定try/except块不需要0.17秒,但是它可能造成的开销大约是否有助于它?

尝试更改以下内容:

double_vec = zip(img_vec,img_pix_vec)
result_row = np.array([tfidf(x[0],x[1],img_total) for x in double_vec])
Run Code Online (Sandbox Code Playgroud)

result_row=np.array([tfidf(img_vec[i],img_pix_vec[i],img_total) for i in xrange(len(img_vec))])
Run Code Online (Sandbox Code Playgroud)

至少摆脱了zip语句,但不确定zip语句是否将你的时间减少了一分钟,或者差不多两个小时(我知道zip很慢,与numpy vstack相比,但没有任何线索,如果这会给你两小时的时间收益)

  • 这回答了这个问题吗?或者你想要一个更技术性的答案?(一般来说,python不能快速运行,其他语言也存在,但是那些想要使用python但仍然获得至少与你在C或FORTRAN中获得的速度相当的速度的numpy存在,为数字训练申请而制作) (2认同)

use*_*ica 8

您所看到的差异并不是由于像SSE矢量化这样的任何幻想.主要原因有两个.第一个是NumPy是用C语言编写的,而C实现不需要经历大量的运行时方法调度和异常检查等等Python实现的完成.

第二个原因是即使对于Python代码,基于循环的实现也是低效的.你vstack在循环中使用,每次调用时vstack,它都必须完全复制你传递给它的所有数组.这len(data_matrix)为你的渐近复杂性增加了额外的因素.