将 3D numpy 数组高效转换为 1D numpy 数组
Efficient conversion of a 3D numpy array to a 1D numpy array
我有一个这种形式的 3D numpy 数组:
>>>img.shape
(4504932, 2, 2)
>>> img
array([[[15114, 15306],
[15305, 15304]],
[[15305, 15306],
[15303, 15304]],
[[15305, 15306],
[15303, 15304]],
...,
[[15305, 15302],
[15305, 15302]]], dtype=uint16)
我想将其转换为一维 numpy 数组,其中每个条目都是上述 img numpy 数组中每个 2x2 子矩阵的总和。
我已经能够使用以下方法完成此操作:
img_new = np.array([i.sum() for i in img])
>>> img_new
array([61029, 61218, 61218, ..., 61214, 61214, 61214], dtype=uint64)
这正是我想要的。但这太慢了(大约需要 10 秒)。我可以使用更快的方法吗?我在上面包含了 img.shape
这样你就知道了这个 numpy 数组的大小。
编辑 - 附加信息:
我的 img
数组也可以是 4x4、5x5、7x7.. 等子矩阵形式的 3D 数组。这由变量 sub_rows
和 sub_cols
.
指定
img.sum(axis=(1, 2))
sum
允许您指定要求和的一个或多个轴,而不仅仅是对整个数组求和。这允许 NumPy 循环遍历 C 中的数组,每次求和仅执行几条机器指令,而不必通过 Python 字节码评估循环并创建大量包装对象以粘贴在列表中。
使用 numpy 方法 (apply_over_axes
) 通常更快,这里确实如此。我刚刚在 4000x2x2 阵列上进行了测试:
img = np.random.rand(4000,2,2)
timeit(np.apply_along_axis(np.sum, img, [1,2]))
# 1000 loops, best of 3: 721 us per loop
timeit(np.array([i.sum() for i in img]))
# 100 loops, best of 3: 17.2 ms per loop
可以使用np.einsum
-
img_new = np.einsum('ijk->i',img)
验证结果
In [42]: np.array_equal(np.array([i.sum() for i in img]),np.einsum('ijk->i',img))
Out[42]: True
运行时测试
In [34]: img = np.random.randint(0,10000,(10000,2,2)).astype('uint16')
In [35]: %timeit np.array([i.sum() for i in img]) # Original approach
10 loops, best of 3: 92.4 ms per loop
In [36]: %timeit img.sum(axis=(1, 2)) # From other solution
1000 loops, best of 3: 297 µs per loop
In [37]: %timeit np.einsum('ijk->i',img)
10000 loops, best of 3: 102 µs per loop
我有一个这种形式的 3D numpy 数组:
>>>img.shape
(4504932, 2, 2)
>>> img
array([[[15114, 15306],
[15305, 15304]],
[[15305, 15306],
[15303, 15304]],
[[15305, 15306],
[15303, 15304]],
...,
[[15305, 15302],
[15305, 15302]]], dtype=uint16)
我想将其转换为一维 numpy 数组,其中每个条目都是上述 img numpy 数组中每个 2x2 子矩阵的总和。
我已经能够使用以下方法完成此操作:
img_new = np.array([i.sum() for i in img])
>>> img_new
array([61029, 61218, 61218, ..., 61214, 61214, 61214], dtype=uint64)
这正是我想要的。但这太慢了(大约需要 10 秒)。我可以使用更快的方法吗?我在上面包含了 img.shape
这样你就知道了这个 numpy 数组的大小。
编辑 - 附加信息:
我的 img
数组也可以是 4x4、5x5、7x7.. 等子矩阵形式的 3D 数组。这由变量 sub_rows
和 sub_cols
.
img.sum(axis=(1, 2))
sum
允许您指定要求和的一个或多个轴,而不仅仅是对整个数组求和。这允许 NumPy 循环遍历 C 中的数组,每次求和仅执行几条机器指令,而不必通过 Python 字节码评估循环并创建大量包装对象以粘贴在列表中。
使用 numpy 方法 (apply_over_axes
) 通常更快,这里确实如此。我刚刚在 4000x2x2 阵列上进行了测试:
img = np.random.rand(4000,2,2)
timeit(np.apply_along_axis(np.sum, img, [1,2]))
# 1000 loops, best of 3: 721 us per loop
timeit(np.array([i.sum() for i in img]))
# 100 loops, best of 3: 17.2 ms per loop
可以使用np.einsum
-
img_new = np.einsum('ijk->i',img)
验证结果
In [42]: np.array_equal(np.array([i.sum() for i in img]),np.einsum('ijk->i',img))
Out[42]: True
运行时测试
In [34]: img = np.random.randint(0,10000,(10000,2,2)).astype('uint16')
In [35]: %timeit np.array([i.sum() for i in img]) # Original approach
10 loops, best of 3: 92.4 ms per loop
In [36]: %timeit img.sum(axis=(1, 2)) # From other solution
1000 loops, best of 3: 297 µs per loop
In [37]: %timeit np.einsum('ijk->i',img)
10000 loops, best of 3: 102 µs per loop