Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/performance/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 有没有一种方法可以使用numpy删除循环?_Python_Performance_Numpy_Vectorization - Fatal编程技术网

Python 有没有一种方法可以使用numpy删除循环?

Python 有没有一种方法可以使用numpy删除循环?,python,performance,numpy,vectorization,Python,Performance,Numpy,Vectorization,我有一个3D numpy数组输入_数据(q x m x n),我用它来构建直方图数据以最终绘制,它存储在plot_数据(m x n x 2)中。这一步在我的过程中是一个相当大的瓶颈,我想知道是否有一种更快、更“简单”的方法来实现这一点 num_bins = 3 for i in range(m): for j in range(n): data = input_data[:, i, j] hist, bins = np.histogram(data,

我有一个3D numpy数组输入_数据(q x m x n),我用它来构建直方图数据以最终绘制,它存储在plot_数据(m x n x 2)中。这一步在我的过程中是一个相当大的瓶颈,我想知道是否有一种更快、更“简单”的方法来实现这一点

num_bins = 3
for i in range(m):

    for j in range(n):

        data = input_data[:, i, j]

        hist, bins = np.histogram(data, bins=num_bins)

        # Create the (x, y) pairs to plot
        plot_data[i][j] = np.stack((bins[:-1], hist), axis=1)

我认为你们的样品是相似的,所以柱状图是相似的。在这种情况下,您可以简化比较,并以更矢量化的方式进行比较:

a=np.random.rand(100000,10,10)


def f():  # roughly your approach.
    plotdata=np.zeros((10,10,3),np.int32)
    for i in range(10):
        for j in range(10):
            bins,hist=np.histogram(a[:,i,j],3)
            plotdata[i,j]=bins 
    return plotdata

def g(): #vectored comparisons 
    u=(a < 1/3).sum(axis=0)
    w=(a > 2/3).sum(axis=0)
    v=len(a)-u-w
    return np.dstack((u,v,w))

这里有一个矢量化的方法来计算箱子的一般数量-

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
辅助功能-

运行时测试

原始方法-

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
时间安排和核查-

让我们在一个大型数据阵列上进行测试,该阵列的形状为
(100100100)
,存储箱的数量为
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()计算和,而不是手动循环计算和,我查找了一些信息。也许,scipy网站就是你想要的?我发现:你的数据是(q,m,n)。进一步调查的q,m,n值是多少?q,m,n可以是任何值,但为了近似我的数据,可能是100000 x 10 x 360@Maderas不幸的是,我不认为它对多维数组有效。不幸的是,我们不能像这样简化,我们需要真实数据与大型3d数组上的for循环相比,它的性能如何?@holtc补充道,假设形状的随机数(100100)和容器数=10。因此,当我在真实数据上运行它时,allclose()为false,由于我正在JIT所有方法,因此实际上速度较慢,因此很遗憾,我无法使用此选项。在我的例子中,输入的_数据大约为(100000,8360),最大为100bins@holtc是的,所以你的循环数只有8*360。那不多。保持你的循环/紧张-准时。@holtc如果你能在将来的问题中提前提到这些尺寸/形状的细节,那会有所帮助。
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
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