繁体   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