Python 如何使用numpy和strips来提高循环的性能

Python 如何使用numpy和strips来提高循环的性能,python,numpy,Python,Numpy,我是numpy的新手,刚听说过跨步,但我很难理解如何使用跨步。我有一个很慢的小循环,这似乎是一个很好的例子,可以用于跨步 def semivariogram( ds, band, lag ): width = ds.RasterXSize height = ds.RasterYSize data = band.ReadAsArray( 0, 0, width, height ).astype(np.float) #print 'w: {}, h: {}'.form

我是numpy的新手,刚听说过跨步,但我很难理解如何使用跨步。我有一个很慢的小循环,这似乎是一个很好的例子,可以用于跨步

def semivariogram( ds, band, lag ):
    width = ds.RasterXSize
    height = ds.RasterYSize
    data = band.ReadAsArray( 0, 0, width, height ).astype(np.float)
    #print 'w: {}, h: {}'.format(width, height)

    sumw = 0.0
    sumh = 0.0
    for i in range(width-lag):
        for j in range(height-lag):
            sumw += data[i+lag,j]-data[i,j]
            sumh += data[i,j+lag]-data[i,j]

    Nh2 = 2.0*(width-lag)*(height-lag)

    return [sumw/Nh2, sumh/Nh2, (sumw/Nh2+sumh/Nh2)/2.0]
该行:

data = band.ReadAsArray( 0, 0, width, height ).astype(np.float)
正在将图像的一个波段读入浮点数组。而
ds
是图像的句柄,如:

ds = gdal.Open('test.tif')

好的,让我们一步一步来做

你有:

sumw = 0.0
sumh = 0.0
for i in range(width-lag):
    for j in range(height-lag):
        sumw += data[i+lag,j]-data[i,j]
        sumh += data[i,j+lag]-data[i,j]
为了清晰起见,让我们将其分成两个循环

sumw = 0.0
for i in range(width-lag):
    for j in range(height-lag):
        sumw += data[i+lag,j]-data[i,j]
sumh = 0.0
for j in range(height-lag):
    for i in range(width-lag):
        sumh += data[i,j+lag]-data[i,j]
我们可以把
数据[i,j+lag]
写成
数据[:-lag,lag:[i,j]
,而
数据[i,j]
数据[:-lag,:-lag][i,j]
(对于
i
j
的范围,假设lag!=0)。因此,我们的循环变成:

sumw = 0.0
for i in range(width-lag):
    for j in range(height-lag):
        sumw += data[lag:,:-lag][i,j]-data[:-lag,:-lag][i,j]
sumh = 0.0
for j in range(height-lag):
    for i in range(width-lag):
        sumh += data[:-lag,lag:][i,j]-data[:-lag,:-lag][i,j]
但现在我们注意到,我们所有的循环都只是在一个简单的索引上迭代,
[i,j]
,所以我们可以将它们完全展平:

sumw = (data[lag:,:-lag] - data[:-lag,:-lag]).sum()
sumh = (data[:-lag,lag:] - data[:-lag,:-lag]).sum()
通过发现差值之和就是总和之差,可以更快地实现这一点:

sumw = data[lag:,:-lag].sum() - data[:-lag,:-lag].sum()
sumh = data[:-lag,lag:].sum() - data[:-lag,:-lag].sum()
此时,您可以直观地思考整个任务:

您希望
sumw
作为绿色轮廓上的和减去红色轮廓上的和,而
sumh
作为蓝色轮廓上的和减去红色轮廓上的和

在这里,我们可以进行两种简化:

  • 我们注意到,第一个和中的大多数元素都从第二个和中删除。事实上,唯一不属于这种情况的要素是
    [:lag]
    [-lag::
    。这就变成了:

    sumw = data[-lag:,:-lag].sum() - data[:lag,:-lag].sum()
    sumh = data[:-lag,-lag:].sum() - data[:-lag,:lag].sum()
    
    如果
    滞后
    ,哪个会更快。在这里,我们设置了
    sumw=green-(红色+洋红色)
    ,以及
    sumh=blue-(红色+黄色)

  • 我们注意到第二个和是重复的,所以我们有

    sum_shared = data[:-lag,:-lag].sum()
    sumw = data[lag:,:-lag].sum() - sum_shared 
    sumh = data[:-lag,lag:].sum() - sum_shared
    

  • 为什么你确定你需要大跨步?这些与数据的搅动方式相对应。您提供的代码需要使用numpy vector和切片操作来编写,以从使用numpy中获益。您的代码不是在做
    sumw=data[lag:,:].sum()-data[:-lag,:].sum()
    ?Eric,谢谢!但是这里有些不正确的地方:我为标签0-5上面的每个代码片段打印了sumw,sumh,并得到了值:0 10512.0 135002.0,1 10512.0 135002.0,2 10512.0 135002.0,3 10720.0 135750.0,4 10720.0 135750.0,5-10720.0-135750.0你如何得出这些数字不正确的结论?如果我没有任何背景,那么我应该从这些数字中推断出什么呢。我的方法给出的结果和你的方法相同吗?因此,如果你看上面代码的分解,在你对我的问题的转换中有6个代码块,将它们标记为0-5,在每个代码块之后,我分别添加了“print N,sumw,sumh”,其中N=0..5。然后块0、1、2打印相同的结果,3、4相同但不同于0,1、2和5与3、4相同但相反。似乎3,4,5是一个或多个附加项的总和。不知道为什么5是否定的。顺便说一句,你对问题的分解非常好,并且是教程,谢谢!5是否定的,因为它是错误的!那件容易修理。你能确认
    lag
    是非零和正的吗?我想我知道我的错误了