簡體   English   中英

是否有任何選項可以進一步提高此數據規范化的時間效率?

[英]Is there any option to improve the time efficiency of the this data normalization any further?

我有一個名為 tArray 的矩陣,其形狀為 (11, 512) 並且想要對其中的值進行歸一化。 我看到 np.max() 花費了很多時間,但我沒有找到任何進一步改進它的選項。 下面這行代碼的時間效率可以提高嗎?:

tArray = np.array([[val/tArray[i][sqLen-1] for val in tArray[i]] if i not in [1,2] else [val/np.max(tArray[i][:sqLen-1]) for val in tArray[i]] for i in range(len(tArray))])

重現:

tArray = np.random.randint(1, 100, size=(11, 512))
tArray = np.array([[val/tArray[i][512-1] for val in tArray[i]] if i not in [1,2] else [val/np.max(tArray[i][:512-1]) for val in tArray[i]] for i in range(len(tArray))])```

這是〜180X加速改進方法:

請注意,對於輸入數組的形狀[512-1][-1] (最后一列)相同, [:512-1][:-1]相同。

循環的主要條件if i not in [1,2] else表明聚合/計算隱含在 3 個切片中: [0] (第一行)、 [1:3] (第 1 行和第 2 行)和剩余行[3:]

因此,不是遍歷每一行並重新計算每一列,我們可以以矢量化方式一次對 3 個連續切片應用所需的操作,並最終將結果與np.vstack例程連接起來:

np.vstack((tArray[0]/tArray[0,-1], tArray[1:3]/tArray[1:3,:-1].max(1)[:,None], tArray[3:]/tArray[3:,-1][:,None]))

讓我們看看測量:

tArray = np.random.randint(1, 100, size=(11, 512)) # input array

In [165]: %timeit tArray1 = np.array([[val/tArray[i][512-1] for val in tArray[i]] if i not in [1,2] else [val/np.max
     ...: (tArray[i][:512-1]) for val in tArray[i]] for i in range(len(tArray))])
4.54 ms ± 23.8 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [171]: %timeit new_arr = np.vstack((tArray[0]/tArray[0,-1], tArray[1:3]/tArray[1:3,:-1].max(1)[:,None], tArray[3:]/tAr
     ...: ray[3:,-1][:,None]))
25.5 µs ± 264 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)

當然, tArray1new_arr的內容是一樣的:

In [173]: tArray1
Out[173]: 
array([[ 8.11111111,  2.33333333,  9.33333333, ...,  0.44444444,
         5.22222222,  1.        ],
       [ 0.76767677,  0.77777778,  0.72727273, ...,  0.58585859,
         0.29292929,  0.09090909],
       [ 0.36363636,  0.85858586,  0.35353535, ...,  0.06060606,
         0.48484848,  0.55555556],
       ...,
       [ 1.875     ,  2.04166667,  0.29166667, ...,  0.20833333,
         0.58333333,  1.        ],
       [ 0.28735632,  0.11494253,  0.37931034, ...,  0.50574713,
         0.74712644,  1.        ],
       [ 5.625     , 10.5       ,  0.5       , ...,  2.125     ,
         0.75      ,  1.        ]])

In [174]: new_arr
Out[174]: 
array([[ 8.11111111,  2.33333333,  9.33333333, ...,  0.44444444,
         5.22222222,  1.        ],
       [ 0.76767677,  0.77777778,  0.72727273, ...,  0.58585859,
         0.29292929,  0.09090909],
       [ 0.36363636,  0.85858586,  0.35353535, ...,  0.06060606,
         0.48484848,  0.55555556],
       ...,
       [ 1.875     ,  2.04166667,  0.29166667, ...,  0.20833333,
         0.58333333,  1.        ],
       [ 0.28735632,  0.11494253,  0.37931034, ...,  0.50574713,
         0.74712644,  1.        ],
       [ 5.625     , 10.5       ,  0.5       , ...,  2.125     ,
         0.75      ,  1.        ]])

創建一個分母數組,用最大值替換所選行中的分母。 然后將整個矩陣除以這個分母數組(您需要轉置矩陣來執行此操作,然后再將其轉回)。

t = np.random.randint(1, 100, size=(11, 512))
ignore = [1, 2] 
denoms = t[..., -1].copy()
denoms[ignore] = t[ignore, :-1].max(axis=1)
result = (t.T / denoms).T

這似乎比vstack解決方案稍微快一些,並且還允許您更清楚地選擇哪些行到 select。

這對於 350 倍的加速(浮點數 560 倍)怎么樣?

def f(a):
    d = a[:, -1].copy()
    d[1:3] = a[1:3, :-1].max(1)
    return a / d[:, None]

float arrays 上,它比@Roman 的答案快兩倍。 我認為它也更容易閱讀。

a = np.random.uniform(1, 100, size=(11, 512))

%timeit np.vstack((a[0]/a[0,-1], a[1:3,:]/a[1:3,:-1].max(), a[3:,:]/a[3:,-1][:,None]))
24.4 µs ± 102 ns per loop (mean ± std. dev. of 7 runs, 10,000 loops each)

%timeit f(a)
11.8 µs ± 22.9 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)

int arrays 上,差別不大(快 60%)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM