我有三個一維向量。假設 T 有 100k 元素陣列, f 和 df 各有 200 個元素陣列:
T = [T0, T1, ..., T100k]
f = [f0, f1, ..., f200]
df = [df0, df1, ..., df200]
對于每個元素陣列,我必須計算一個函式,如下所示:
P = T*f T**2 *df
我的第一個直覺是使用 NumPy 外部來查找f和df的每個組合的函式
P1 = np.outer(f,T)
P2 = np.outer(df,T**2)
P = np.add.outer(P1, P2)
但是,在這種情況下,我面臨 ram 問題并收到以下錯誤:
無法為形狀為 (200, 100000, 200, 100000) 且資料型別為 float64 的陣列分配 2.23 PiB
有什么好方法可以計算嗎?
我嘗試使用 for 回圈
n=100
f_range = 5e-7
df_range = 1.5e-15
fsrc = np.arange(f - n * f_range, f n * f_range, f_range) #array of 200
dfsrc = np.arange(df - n * df_range, df n * df_range, df_range) #array of 200
dfnus=pd.DataFrame(fsrc)
numf=dfnus.shape[0]
dfnudots=pd.DataFrame(dfsrc)
numfdot=dfnudots.shape[0]
test2D = np.zeros([numf,(numfdot)])
for indexf, f in enumerate(fsrc):
for indexfd, fd in enumerate(dfsrc):
a=make_phase(T,f,fd) #--> this is just a function that performs T*f T**2 *df
zlauf2d=z_n(a, n=1, norm=1) #---> And this is just another function that takes this 1D "a" and gives another 1D element array
test2D[indexf, indexfd]=np.copy(zlauf2d) #---> I do this so I could make a contour plot at the end. It just copys the same thing to 2D
現在我的 test2D 的形狀為 (200,200)。這就是我想要的,但是地板回圈需要很長時間,我想以某種方式將兩個 for 回圈減少到至少一個。
uj5u.com熱心網友回復:
使用廣播:
P1 = (f[:, np.newaxis] * T).sum(axis=-1)
P2 = (df[:, np.newaxis] * T**2).sum(axis=-1)
P = P1[:, np.newaxis] P2
或者,使用外部:
P1 = (np.outer(f, T)).sum(axis=-1)
P2 = (np.outer(df, T**2)).sum(axis=-1)
P = P1[..., np.newaxis] P2
這會產生一個 shape 陣列(f.size, df.size) == (200, 200)。
一般來說,如果最終輸出陣列的大小非常大,可以:
- 減少資料型別的大小。一種方法是更改??用于計算最終輸出的陣列的資料型別
P1.astype(np.float32)。或者,某些操作允許將 adtype=np.float32作為引數傳入。 - 將計算分塊并處理結果的較小部分。
根據最近的編輯,計算一個a帶有 shape的陣列(200, 200, 100000)。然后,沿最后一個軸取其元素范數以生成z形狀為 的陣列(200, 200)。
a = (
f[:, np.newaxis, np.newaxis] * T
df[np.newaxis, :, np.newaxis] * T**2
)
# L1 norm along last axis.
z = np.abs(a).sum(axis=-1)
這會產生一個 shape 陣列(f.size, df.size) == (200, 200)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/443161.html
