簡體   English   中英

多個numpy數組上的多步線性代數運算

[英]Multi-step linear algebra operations on multiple numpy arrays

我有3個numpy數組:

import numpy
arr_a = numpy.random.random((300, 300))
arr_b = numpy.random.random((300, 300))
arr_c = numpy.random.random((300, 300))

我想從3個數組的組合中創建第4個數組(arr_d)。 規則如下:

如果arr_a柵格像元值> 0.2和arr_b值<0.4且arr_c> 0.6,則用1填充arr_d

如果arr_a柵格像元值> 0.3且arr_b值<0.5且arr_c> 0.6,則用2填充arr_d

如果arr_a網格單元值> 0.1和arr_b值<0.2並且arr_c> 0.5,則用3填充arr_d

在所有其他情況下,用4填充arr_d

我可以使用嵌套循環來做到這一點,但這很慢,而且不是很pythonic。 另外,這是一個測試用例,實際數組的大小為1000 * 1000,所以我想要一個可擴展的解決方案,最好是可並行化的。

使用純Python和for循環絕對不是走的路。 您可以使用NumPy中的數組操作編寫程序,從而有效地在C中執行循環,從而極大地加快了代碼的速度。 但是,這會為您的每個規則實例化一個全新的數組,每個規則的大小與數據的大小相同。 相反,您可以使用類似Numba的工具,例如Python的Anaconda發行版。 使用Numba,您可以使用循環來編寫代碼,而不會浪費時間(它將代碼編譯為本機機器指令)。 另外,不需要額外的大型陣列,從而使其存儲效率比NumPy高得多。 Numba也碰巧更快,如以下示例所示:

import numpy, numba, time

def using_numpy(shape):
    arr_a = numpy.random.random(shape)
    arr_b = numpy.random.random(shape)
    arr_c = numpy.random.random(shape)
    mask1 = numpy.logical_and(numpy.logical_and((arr_a > 0.2), (arr_b < 0.4)), (arr_c > 0.6))
    mask2 = numpy.logical_and(numpy.logical_and((arr_a > 0.3), (arr_b < 0.5)), (arr_c > 0.6))
    mask3 = numpy.logical_and(numpy.logical_and((arr_a > 0.1), (arr_b < 0.2)), (arr_c > 0.5))
    result = numpy.ones(arr_a.shape)*4
    result[mask1] = 1
    result[mask2] = 2
    result[mask3] = 3
    return result

@numba.jit
def using_numba(shape):
    arr_a = numpy.random.random(shape)
    arr_b = numpy.random.random(shape)
    arr_c = numpy.random.random(shape)
    result = numpy.empty(shape)
    for i in range(result.shape[0]):
        for j in range(result.shape[1]):
            if arr_a[i, j] > 0.2 and arr_b[i, j] < 0.4 and arr_c[i, j] > 0.6:
                result[i, j] = 1
            elif arr_a[i, j] > 0.3 and arr_b[i, j] < 0.5 and arr_c[i, j] > 0.6:
                result[i, j] = 2
            elif arr_a[i, j] > 0.1 and arr_b[i, j] < 0.2 and arr_c[i, j] > 0.5:
                result[i, j] = 3
            else:
                result[i, j] = 4
    return result
# Compile the using_numba function
using_numba((0, 0))

t0 = time.time()
result = using_numpy((3000, 3000))
print('NumPy took', time.time() - t0, 'seconds')

t0 = time.time()
result = using_numba((3000, 3000))
print('Numba took', time.time() - t0, 'seconds')

在這里,我使用了(3000, 3000)數組。 在我的機器上,使用NumPy需要0.47秒,而使用Numba需要0.29秒。

一種方法是使用布爾映射

condition_1 = numpy.logical_and(numpy.logical_and((arr_a > 0.2), (arr_b < 0.4)), (arr_c > 0.6))
condition_2 = numpy.logical_and(numpy.logical_and((arr_a > 0.3), (arr_b < 0.5)), (arr_c > 0.6))
condition_3 = numpy.logical_and(numpy.logical_and((arr_a > 0.1), (arr_b < 0.2)), (arr_c > 0.5))
result = numpy.ones((300, 300)) * 4
result[numpy.where(condition_3)] = 3
result[numpy.where(condition_2)] = 2
result[numpy.where(condition_1)] = 1

它避免了嵌套循環,但分配了三個專用數組,並進行了大量多余的分配。 必須有一個更優化的方法...

暫無
暫無

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

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