【问题标题】:How to vectorize the following python code?如何向量化以下python代码?
【发布时间】:2015-07-29 05:57:21
【问题描述】:

我正在尝试使用 Numpy 和矢量化操作来使一段代码运行得更快,但我没有成功找到解决方案。如果有人有想法...谢谢。

这是带有循环的工作代码:

y = np.zeros(len(tab))
for i in range(len(tab)):
    s =  0
    for n in range(len(coef[0])):
        s += coef[0][n] * ((a + b * np.dot(tab[i], vectors[n])) ** d)
    y[i] = s

在哪里,

  • 标签:numpy.array(N,M)
  • 向量:numpy.array(P,M)
  • 系数:numpy.array(1,P)
  • a、b、c:常量(a = 0,如果更简单的话)

【问题讨论】:

  • 您能否在问题的开头包含一个句子来描述代码应该完成的任务?很难给出纯粹的程序化评估。
  • @mprat - 它是 SVM 算法实现的一部分,类似于此实现 link - 第 83-88 行
  • @unutbu - 没错,我更正了代码

标签: python arrays performance numpy vectorization


【解决方案1】:

您可以使用基于np.einsummatrix-multiplication with np.dot 的方法,如下所示 -

# Calculate "((a + b * np.dot(tab[i], vectors[n])) ** d)" part
p1 = (a + b*np.einsum('ij,kj->ki',tab,vectors))**d

# Include "+= coef[0][n] *" part to get the final output
y_vectorized = np.dot(coef,p1)

运行时测试

数据集 #1:

这是一个快速的运行时测试,将原始循环方法与一些随机值的建议方法进行比较 -

In [168]: N = 50
     ...: M = 50
     ...: P = 50
     ...: 
     ...: tab = np.random.rand(N,M)
     ...: vectors = np.random.rand(P,M)
     ...: coef = np.random.rand(1,P)
     ...: 
     ...: a = 3.233
     ...: b = 0.4343
     ...: c = 2.0483
     ...: d = 3
     ...: 

In [169]: %timeit original_approach(tab,vectors,coef,a,b,c,d)
100 loops, best of 3: 4.18 ms per loop

In [170]: %timeit proposed_approach(tab,vectors,coef,a,b,c,d)
10000 loops, best of 3: 136 µs per loop

数据集 #2:

NMP 分别为 150,运行时是 -

In [196]: %timeit original_approach(tab,vectors,coef,a,b,c,d)
10 loops, best of 3: 37.9 ms per loop

In [197]: %timeit proposed_approach(tab,vectors,coef,a,b,c,d)
1000 loops, best of 3: 1.91 ms per loop

【讨论】:

    【解决方案2】:

    看起来很糟糕。但这是你需要的吗?

    y = array([ sum( [coef[0][n] * ((a + b * np.dot(tab[i], vectors[n])) ** d) 
                for n in range(len(vectors[0]))] ) for i in range(len(tab)) ])
    

    【讨论】:

    • 使用相同的数据集,我的实现:总运行时间 = 28 分钟,而您的实现:总运行时间 = 15 分钟。更好,但是不使用这2个循环就没有更好的解决方案了吗?
    • 这不是矢量化,即使您使用 numpy 来加快速度,您仍然有 2 个 for 循环..
    • 这只是将 2 循环重写为列表推导。仍然是一个 Python 循环,只是效率更高一些。
    猜你喜欢
    • 2019-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多