当包含计算和删除时,将外部和内部循环向量化

时间:2017-02-05 06:19:56

标签: python numpy

我一直在检查如何对外部和内部for循环进行矢量化。这些都有一些计算,还有一个删除 - 这似乎使它更不直接。

如何最好地进行矢量化?

import numpy as np

flattenedArray = np.ndarray.tolist(someNumpyArray)

#flattenedArray is a python list of lists.
c = flattenedArray[:]
for a in range (len(flattenedArray)):
    for b in range(a+1, len(flattenedArray)):
        if a == b:
            continue
        i0 = flattenedArray[a][0]
        j0 = flattenedArray[a][1]
        z0 = flattenedArray[a][2]
        i1 = flattenedArray[b][0]
        i2 = flattenedArray[b][1]
        z1 = flattenedArray[b][2]

        if ((np.square(z0-z1)) <= (np.square(i0-i1) + (np.square(j0-j2)))):
            if (np.square(i0-i1) + (np.square(j0-j1))) <= (np.square(z0+z1)):
                        c.remove(flattenedArray[b])

2 个答案:

答案 0 :(得分:1)

当然,@ MSeifert经常是正确的。所以下面的完整矢量化只是为了表明“它是如何完成的”

import numpy as np

N = 4
data = np.random.random((N, 3))

# vectorised code
j, i = np.tril_indices(N, -1) # chose tril over triu to have contiguous columns
                              # useful later
sqsum = np.square(data[i,0]-data[j,0]) + np.square(data[i,1]-data[j,1])
cond = np.square(data[i, 2] + data[j, 2]) >= sqsum
cond &= np.square(data[i, 2] - data[j, 2]) <= sqsum
# because equal 'b's are grouped together we can use reduceat:
cond = np.r_[False, np.logical_or.reduceat(
    cond, np.add.accumulate(np.arange(N-1)))]
left = data[~cond, :]


# original code (modified to make it run)
flattenedArray = np.ndarray.tolist(data)

#flattenedArray is a python list of lists.
c = flattenedArray[:]
for a in range (len(flattenedArray)):
    for b in range(a+1, len(flattenedArray)):
        if a == b:
            continue
        i0 = flattenedArray[a][0]
        j0 = flattenedArray[a][1]
        z0 = flattenedArray[a][2]
        i1 = flattenedArray[b][0]
        j1 = flattenedArray[b][1]
        z1 = flattenedArray[b][2]

        if ((np.square(z0-z1)) <= (np.square(i0-i1) + (np.square(j0-j1)))):
            if (np.square(i0-i1) + (np.square(j0-j1))) <= (np.square(z0+z1)):
                try:
                        c.remove(flattenedArray[b])
                except:
                        pass

# check they are the same
print(np.alltrue(c == left))

答案 1 :(得分:0)

如果使用蒙版,对内部循环进行矢量化并不是一个大问题:

 S <- 0.25    ### !!!  Change this to "24" and see how another plot will appear !!! ###
Ur <- c(0.25, 24, 16)

if(S>=1){

plot(1, 1, type = "n", xlim = c(0,1.5), ylim = c(1/3, 100), log="y", bty="n", ann=F, axes=F, xaxs="i")

axis(side=1, at = seq(0,1.5,.25),labels = c("0",".25",".5",".75","1","1.25","1.5"))
axis(side=2, at = c(1/3, 1, 3, 10, 30, 100),labels = c("1/3", "1", "3", "10", "30", "100"),las=1)

}else{

plot(1, 1, type = "n", xlim = c(0,1.5), ylim = c(.01, 3), log="y", bty="n", ann=F ,axes=F, xaxs="i")

axis(side=1, at = seq(0,1.5,.25),labels = c("0",".25",".5",".75","1","1.25","1.5"))
axis(side=2, at = c(.01, 1/30, 1/10, 1/3, 1, 3),labels = c("1/100", "1/30", "1/10", "1/3", "1", "3"),las=1)
}


legend(0, (10^par("usr"))[4], bquote(paste("Selected Prior:              ",bold('PN'[10])," = ", .(round(S,3)))), ## Legend
   pch = 21,cex=2,pt.bg="green", col="red", pt.cex=2.8, bty="n")  

如果你还想要对外循环进行矢量化,则必须通过广播来实现,但是会使用大量内存import numpy as np # I'm using a random array flattenedArray = np.random.randint(0, 100, (10, 3)) mask = np.zeros(flattenedArray.shape[0], bool) for idx, row in enumerate(flattenedArray): # Calculate the broadcasted elementwise addition/subtraction of this row # with all following added_squared = np.square(row[None, :] + flattenedArray[idx+1:]) subtracted_squared = np.square(row[None, :] - flattenedArray[idx+1:]) # Check the conditions col1_col2_added = subtracted_squared[:, 0] + subtracted_squared[:, 1] cond1 = subtracted_squared[:, 2] <= col1_col2_added cond2 = col1_col2_added <= added_squared[:, 2] # Update the mask mask[idx+1:] |= cond1 & cond2 # Apply the mask flattenedArray[mask] 而不是O(n**2)。鉴于关键的内部循环已经被矢量化,因此通过矢量化外部循环将不会有很多加速。