下面是箱的通用號碼一個量化的方法 -
def vectorized_app(input_data, num_bins):
s0 = input_data.min(0)
s1 = input_data.max(0)
m,n,r = input_data.shape
ids = (num_bins*((input_data - s0)/(s1-s0))).astype(int).clip(max=num_bins-1)
offset = num_bins*(r*np.arange(n)[:,None] + np.arange(r))
ids3D = ids + offset
count3D = np.bincount(ids3D.ravel(), minlength=n*r*num_bins).reshape(n,r,-1)
bins3D = create_ranges_nd(s0, s1, num_bins+1)[...,:-1]
out = np.empty((n,r,num_bins,2))
out[...,0] = bins3D
out[...,1] = count3D
return out
輔助功能(s) -
# https://stackoverflow.com/a/46694364/ @Divakar
def create_ranges_nd(start, stop, N, endpoint=True):
if endpoint==1:
divisor = N-1
else:
divisor = N
steps = (1.0/divisor) * (stop - start)
return start[...,None] + steps[...,None]*np.arange(N)
運行測試
原始的方法 -
def org_app(input_data, num_bins):
q,m,n = input_data.shape
plot_data = np.zeros((m,n,num_bins,2))
for i in range(m):
for j in range(n):
data = input_data[:, i, j]
hist, bins = np.histogram(data, bins=num_bins)
plot_data[i][j] = np.stack((bins[:-1], hist), axis=1)
return plot_data
時序和驗證 -
讓我們測試出形狀(100, 100, 100)
的大型數據陣列上,並與框的數目爲10
:
In [967]: # Setup input
...: num_bins = 10
...: m = 100
...: n = 100
...: q = 100
...: input_data = np.random.rand(q,m,n)
...:
...: out1 = org_app(input_data, num_bins)
...: out2 = vectorized_app(input_data, num_bins)
...: print np.allclose(out1, out2)
...:
True
In [968]: %timeit org_app(input_data, num_bins)
1 loop, best of 3: 748 ms per loop
In [969]: %timeit vectorized_app(input_data, num_bins)
100 loops, best of 3: 12.7 ms per loop
In [970]: 748/12.7 # speedup with vectorized one over original
Out[970]: 58.89763779527559
更快你的意思是更簡潔嗎? –
更快的意義運行時間,所以理想地利用numpy的矢量化能力,類似於使用np.sum()計算總和而不是循環並手動計算 – holtc
因此,我查找了一些信息。也許,這個scipy網站會是你想要的?我發現以下內容: https://docs.scipy.org/doc/numpy-1.13.0/reference/arrays.nditer.html – Maderas