簡體   English   中英

以正確的方式使用NumPy將函數應用於數組中的特定點

[英]Using NumPy in the correct way to apply a function to specific points in an array

cArr是以下形式的數組:

cArr=np.array([[0,x0,y0,z0,1],[1,x1,y1,z1,1]])

每行的中間三個數字表示兩個點的坐標(參考點0和1),在3D中。 每行的第一個和最后一個值由其他函數使用。

cEDA是一個4D形狀的數組(100,100,100,4),基本上由隨機數填充。

對於0和1的每個點,在6個基本方向上,每個點周圍都有點的鄰域,坐標僅相差一個。

x0,y0,z0
x0+1,y0,z0
x0,y0+1,z0
x0,y0,z0+1
x0-1,y0,z0
x0,y0-1,z0
x0,y0,z0-1

計算與點0和點1相關的這7個點之間的距離(因此,點1與點0和點0本身周圍的點的鄰域之間的距離)並與-2(100,100,100)數組中的對應值組合cEDA並放置在cEDA中第i個100,100,100立方體中,其中i分別是點0或1。

我是C語言背景的python新手,並且正努力擺脫循環思維定勢。 我已經嘗試過預先計算距離並求和數組,但速度慢得多,但到目前為止最快的方法是遍歷每個單獨的值並賦值。 該函數運行很多次,並且是代碼中的瓶頸,並且確信有更好的方法來執行此功能。

我從概念上理解並且可以使用NumPy,但在這種情況下似乎無法應用-關於如何通過使用NumPy加快此功能的任何想法是正確的方法? 我已盡力解釋此功能的功能,對不起,我知道這很令人困惑!

def cF2(cArr, cEDA):
    # the coordinates of points 0 and 1 for readability
    x0 = cArr[0,1]
    y0 = cArr[0,2]
    z0 = cArr[0,3]
    x1 = cArr[1,1]
    y1 = cArr[1,2]
    z1 = cArr[1,3]

    # for each point around point 0 and the point itself, calculate the distance between this point and point 1
    # use this value and the corresponding value in cEDA(x,y,z,-2) and place result in  cEDA(x,y,z,0)
    cEDA[x0,y0,z0,0] = cEDA[x0,y0,z0,-2]-0.4799/(np.linalg.norm([x0,y0,z0]-cArr[1,1:4]))
    cEDA[x0-1,y0,z0,0] = cEDA[x0-1,y0,z0,-2]-0.4799/(np.linalg.norm([x0-1,y0,z0]-cArr[1,1:4]))
    cEDA[x0+1,y0,z0,0] = cEDA[x0+1,y0,z0,-2]-0.4799/(np.linalg.norm([x0+1,y0,z0]-cArr[1,1:4]))
    cEDA[x0,y0-1,z0,0] = cEDA[x0,y0-1,z0,-2]-0.4799/(np.linalg.norm([x0,y0-1,z0]-cArr[1,1:4]))
    cEDA[x0,y0+1,z0,0] = cEDA[x0,y0+1,z0,-2]-0.4799/(np.linalg.norm([x0,y0+1,z0]-cArr[1,1:4]))
    cEDA[x0,y0,z0-1,0] = cEDA[x0,y0,z0-1,-2]-0.4799/(np.linalg.norm([x0,y0,z0-1]-cArr[1,1:4]))
    cEDA[x0,y0,z0+1,0] = cEDA[x0,y0,z0+1,-2]-0.4799/(np.linalg.norm([x0,y0,z0+1]-cArr[1,1:4]))

    cEDA[x1,y1,z1,1] = cEDA[x1,y1,z1,-2]+0.4799/(np.linalg.norm([x1,y1,z1]-cArr[0,1:4]))
    cEDA[x1-1,y1,z1,1] = cEDA[x1-1,y1,z1,-2]+0.4799/(np.linalg.norm([x1-1,y1,z1]-cArr[0,1:4]))
    cEDA[x1+1,y1,z1,1] = cEDA[x1+1,y1,z1,-2]+0.4799/(np.linalg.norm([x1+1,y1,z1]-cArr[0,1:4]))
    cEDA[x1,y1-1,z1,1] = cEDA[x1,y1-1,z1,-2]+0.4799/(np.linalg.norm([x1,y1-1,z1]-cArr[0,1:4]))
    cEDA[x1,y1+1,z1,1] = cEDA[x1,y1+1,z1,-2]+0.4799/(np.linalg.norm([x1,y1+1,z1]-cArr[0,1:4]))
    cEDA[x1,y1,z1-1,1] = cEDA[x1,y1,z1-1,-2]+0.4799/(np.linalg.norm([x1,y1,z1-1]-cArr[0,1:4]))
    cEDA[x1,y1,z1+1,1] = cEDA[x1,y1,z1+1,-2]+0.4799/(np.linalg.norm([x1,y1,z1+1]-cArr[0,1:4]))
    return cEDA

如果您想多次調用它,則需要通過numba或Cython將整個for循環轉換為C循環。 但是,有一些方法可以提高功能的速度,這是您的原始功能:

def cF2(cArr, cEDA):
    # the coordinates of points 0 and 1 for readability
    x0 = cArr[0,1]
    y0 = cArr[0,2]
    z0 = cArr[0,3]
    x1 = cArr[1,1]
    y1 = cArr[1,2]
    z1 = cArr[1,3]

    # for each point around point 0 and the point itself, calculate the distance between this point and point 1
    # use this value and the corresponding value in cEDA(x,y,z,-2) and place result in  cEDA(x,y,z,0)
    cEDA[x0,y0,z0,0] = cEDA[x0,y0,z0,-2]-0.4799/(np.linalg.norm([x0,y0,z0]-cArr[1,1:4]))
    cEDA[x0-1,y0,z0,0] = cEDA[x0-1,y0,z0,-2]-0.4799/(np.linalg.norm([x0-1,y0,z0]-cArr[1,1:4]))
    cEDA[x0+1,y0,z0,0] = cEDA[x0+1,y0,z0,-2]-0.4799/(np.linalg.norm([x0+1,y0,z0]-cArr[1,1:4]))
    cEDA[x0,y0-1,z0,0] = cEDA[x0,y0-1,z0,-2]-0.4799/(np.linalg.norm([x0,y0-1,z0]-cArr[1,1:4]))
    cEDA[x0,y0+1,z0,0] = cEDA[x0,y0+1,z0,-2]-0.4799/(np.linalg.norm([x0,y0+1,z0]-cArr[1,1:4]))
    cEDA[x0,y0,z0-1,0] = cEDA[x0,y0,z0-1,-2]-0.4799/(np.linalg.norm([x0,y0,z0-1]-cArr[1,1:4]))
    cEDA[x0,y0,z0+1,0] = cEDA[x0,y0,z0+1,-2]-0.4799/(np.linalg.norm([x0,y0,z0+1]-cArr[1,1:4]))

    cEDA[x1,y1,z1,1] = cEDA[x1,y1,z1,-2]+0.4799/(np.linalg.norm([x1,y1,z1]-cArr[0,1:4]))
    cEDA[x1-1,y1,z1,1] = cEDA[x1-1,y1,z1,-2]+0.4799/(np.linalg.norm([x1-1,y1,z1]-cArr[0,1:4]))
    cEDA[x1+1,y1,z1,1] = cEDA[x1+1,y1,z1,-2]+0.4799/(np.linalg.norm([x1+1,y1,z1]-cArr[0,1:4]))
    cEDA[x1,y1-1,z1,1] = cEDA[x1,y1-1,z1,-2]+0.4799/(np.linalg.norm([x1,y1-1,z1]-cArr[0,1:4]))
    cEDA[x1,y1+1,z1,1] = cEDA[x1,y1+1,z1,-2]+0.4799/(np.linalg.norm([x1,y1+1,z1]-cArr[0,1:4]))
    cEDA[x1,y1,z1-1,1] = cEDA[x1,y1,z1-1,-2]+0.4799/(np.linalg.norm([x1,y1,z1-1]-cArr[0,1:4]))
    cEDA[x1,y1,z1+1,1] = cEDA[x1,y1,z1+1,-2]+0.4799/(np.linalg.norm([x1,y1,z1+1]-cArr[0,1:4]))
    return cEDA

np.random.seed(42)
cArr = np.random.randint(0, 100, (2, 5))
cEDA = np.random.rand(100, 100, 100, 4)
r1 = cF2(cArr, cEDA)

這是優化的功能:

tmp = np.eye(3)
offsets = np.concatenate((tmp, -tmp, [[0, 0, 0]]), 0).astype(int)[:, None, :]

def fast_cF2(cArr, cEDA):
    cArr = cArr[:, 1:4]
    t = cArr[None,:,:] + offsets
    X0, Y0, Z0 = t[:, 0, :].T
    X1, Y1, Z1 = t[:, 1, :].T

    d1 = 0.4799/np.linalg.norm(t[:, 0, :] - cArr[1], axis=1)
    d0 = 0.4799/np.linalg.norm(t[:, 1, :] - cArr[0], axis=1)

    cEDA[X0, Y0, Z0, 0] = cEDA[X0, Y0, Z0, -2] - d1
    cEDA[X1, Y1, Z1, 1] = cEDA[X1, Y1, Z1, -2] + d0
    return cEDA

np.random.seed(42)
cArr = np.random.randint(0, 100, (2, 5))
cEDA = np.random.rand(100, 100, 100, 4)
r2 = fast_cF2(cArr, cEDA)
print np.allclose(r1, r2)

時間結果:

%timeit cF2(cArr, cEDA)
%timeit fast_cF2(cArr, cEDA)

輸出:

1000 loops, best of 3: 320 µs per loop
10000 loops, best of 3: 91.6 µs per loop

我認為scipy.ndimage.generic_filter可以做到...

def neighborly_function(in_arr1d):
    # put your equation below - will have to figure out the details
    # below is just an example
    # has to return a scalar
    return sum(in_arr1d)

import scipy.ndimage as nd

huge_arr3d = [....]

# Since you want the cardinal directions you have to 'footprint'
footprint = np.array([[[False, False, False],
    [False,  True, False],
    [False, False, False]],

   [[False,  True, False],
    [ True, False,  True],
    [False,  True, False]],

   [[False, False, False],
    [False,  True, False],
    [False, False, False]]])

out = nd.generic_filter(huge_arr3d, neighborly_function, footprint=footprint)

http://docs.scipy.org/doc/scipy/reference/tutorial/ndimage.html上查看ndimage文檔,並在http://docs.scipy.org/doc/scipy/reference/tutorial/ndimage上查看generic_filter 。 HTML#通用的過濾函數

暫無
暫無

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

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