2015-11-05 61 views
3
更換迭代

我試圖重寫以下例程(A,B,C,d,和e是所有陣列):在NumPy的

def generate_a(b, c, e): 
    a = np.zeros_like(b) 
    d = np.zeros_like(b) 
    for i in range(a.size): 
     a[i] = (b[i]/c[i]) + d[i-1] 
     d[i] = a[i] * e[i] 
    return a 

不使用 'for' 循環中,由於常規需要運行數百萬次。這是一個小技巧,因爲d中任何給定單元格的值取決於爲a中的單元格計算的結果,而這又取決於爲d計算的最後一個值。關於如何在沒有迭代的情況下完成任何想法?

+0

爲元件'一個[0]',預計什麼D'的'值被使用? –

回答

3

因爲a[i]取決於d[i-1]d[i-1]取決於a[i-1]a[i]還取決於a[0], a[1], ... a[i-1],你將不能夠進行並行計算,因爲它主張。你需要接受這個循環,或者找出一個封閉的表單來完成你的計算。

+0

封閉的形式是可計算的 – toine

1

您可以使用地圖和lambda。

嘗試:

import numpy as np 

def func(i,l): 
    l[0][i] = (l[1][i]/l[2][i]) + l[3][i-1] 
    l[3][i] = l[0][i] * l[4][i] 

    return l[0][i] 

def generate_a(b, c, e): 
    a = np.zeros_like(b) 
    d = np.zeros_like(b) 

    a = map(lambda i:func(i,[a, b, c, d, e]), xrange(a.size)) 

    return a 

print generate_a([5, 6, 7],[1,2,3],[8,9,12]) 
+0

這是更優雅,但沒有太多的時間節省,因爲地圖功能仍然迭代。 – triphook

5

這個solution啓發,這是一個後表明遞歸是vectorizable,如果遞歸可能是追查。正如鏈接解決方案中所述,從目前的開始,這不應該是快速的,但是如果要使用並行處理器,則可以採用這種方法。所以,請把這篇文章作爲如何追蹤和向量化遞歸的指導。這裏的執行 -

def generate_a_vectorized(b, c, e): 

    K = (b/c)*e 
    N = e.size 

    mask = np.linspace(N,1,N,dtype=int)[:,None] <= np.arange(N) 

    Pn = np.tile(e[None],(N,1)) 
    Pn[mask] = 1 
    En = Pn[:,::-1].cumprod(1)[:,::-1] 
    En[mask] = 0 
    An = np.append(0,K[:-1]) 

    d_out = En.dot(An)[::-1] + K 
    return (b/c) + np.append(0,d_out[:-1]) 

採樣運行&驗證輸出 -

In [279]: M = 50 
    ...: b = np.random.rand(M) 
    ...: c = np.random.rand(M) 
    ...: e = np.random.rand(M) 
    ...: 

In [280]: np.allclose(generate_a(b, c, e),generate_a_vectorized(b, c, e)) 
Out[280]: True 

In [281]: %timeit generate_a(b,c,e) 
10000 loops, best of 3: 79.4 µs per loop 

In [282]: %timeit generate_a_vectorized(b,c,e) 
10000 loops, best of 3: 157 µs per loop 
1

一個快速的想法與數學(因爲b[i]/c[i]是從計算獨立的,我把它叫做bc[i]下圖):

Wolfram Language (Raspberry Pi Pilot Release) 
Copyright 1988-2015 Wolfram Research 
Information & help: wolfram.com/raspi 

In[1]:= RSolve[ { a[i]==bc[i] + a[i-1]*e[i-1], a[-1]==0 }, a[i], i]      

Out[1]= {{a[i] -> 

>  Product[e[K[1]], {K[1], 1, -1 + i}] 

         bc[1 + K[2]] 
>  Sum[---------------------------------, {K[2], -1, -1 + i}]}} 
      Product[e[K[1]], {K[1], 1, K[2]}] 

蘭迪çtolt它以前,除非前面的計算將導致更簡單的東西,我強烈懷疑你能GE比你現有的更好。 你可以得到更好的代碼,但可能沒有更高效的代碼。