【问题标题】:How to vstack efficiently a sequence of large numpy array chunks?如何有效地 vstack 一系列大型 numpy 数组块?
【发布时间】:2016-07-31 03:34:02
【问题描述】:

我正在生成一系列 numpy 数组,如下所示:

def chunker(seq, size):
    return (seq[pos:pos + size] for pos in range(0, len(seq), size))

for i in chunker(X,10000):
    e = function(i)
    print('new marix',e)

new matrix (10000, 3208)
new matrix (10000, 3208)
new matrix (10000, 3208)
new matrix (10000, 3208)
new matrix (10000, 3208)
new matrix (10000, 3208)
new matrix (10000, 3208)
new matrix (10000, 3208)
...
new matrix (10000, 3208)

我想将vstack 上述n 矩阵合并为一个。因此,我尝试了以下方法:

    X = np.vstack(e)

但是,当我打印 X 时,我又得到了:

new matrix (10000, 3208)
new matrix (10000, 3208)
new matrix (10000, 3208)
new matrix (10000, 3208)
new matrix (10000, 3208)
new matrix (10000, 3208)
new matrix (10000, 3208)
new matrix (10000, 3208)
...
new matrix (10000, 3208)

而不是新的 vstacked 单矩阵。知道如何 vstack 这个 numpy 数组序列吗?

更新

根据 jedward 的回答,我将代码编辑如下:

将 numpy 导入为 np

def chunker(seq, size):
    return (seq[pos:pos + size] for pos in range(0, len(seq), size))

for (r,i) in enumerate(chunker(X,10000)):
    e = function(i)
    print('new matrix',e)
    X[r,:] = e

print(X)

【问题讨论】:

  • vstack 的输入应该是最后一维匹配的数组列表。 e 看起来不像。您需要将个人e 收集到一个列表中。
  • 在你的循环中,e 的形状是什么? X的? X[r,:]?
  • X.shape = (878049, 3208), e.shape = (10000, 3208), 合并[r,:].shape = (3208,)。内核似乎已经死了。它将自动重新启动。感谢@hpaulj 的帮助!我也得到:The kernel appears to have died. It will restart automatically.
  • e 必须放入X 中的chunk 大小的插槽中,而不仅仅是一行。我建议在较小的测试用例上进行测试。

标签: python python-3.x numpy scipy


【解决方案1】:

一种方法,虽然可能不是最有效的,但是是创建一个您想要堆叠的列表的列表,然后在循环外堆叠一次。

例如:

import numpy as np

def chunker(seq, size):
    return (seq[pos:pos + size] for pos in range(0, len(seq), size))

# Some fake function (n.b. this is a silly way to reverse a list)
def function(arr):
    arr.reverse()
    return arr

# Generate fake X
X = list(range(100))

chunks = []
for i in chunker(X,10):
    e = function(i)
    print('new matrix',e)
    chunks.append(e)

merged = np.vstack(chunks)
print(merged)

输出:

新矩阵 [9, 8, 7, 6, 5, 4, 3, 2, 1, 0] 新矩阵 [19, 18, 17, 16, 15, 14, 13, 12, 11, 10] 新矩阵 [29, 28, 27, 26, 25, 24, 23, 22, 21, 20] 新矩阵 [39, 38, 37, 36, 35, 34, 33, 32, 31, 30] 新矩阵 [49, 48, 47, 46, 45, 44, 43, 42, 41, 40] 新矩阵 [59, 58, 57, 56, 55, 54, 53, 52, 51, 50] 新矩阵 [69, 68, 67, 66, 65, 64, 63, 62, 61, 60] 新矩阵 [79, 78, 77, 76, 75, 74, 73, 72, 71, 70] 新矩阵 [89, 88, 87, 86, 85, 84, 83, 82, 81, 80] 新矩阵 [99, 98, 97, 96, 95, 94, 93, 92, 91, 90] [[ 9 8 7 6 5 4 3 2 1 0] [19 18 17 16 15 14 13 12 11 10] [29 28 27 26 25 24 23 22 21 20] [39 38 37 36 35 34 33 32 31 30] [49 48 47 46 45 44 43 42 41 40] [59 58 57 56 55 54 53 52 51 50] [69 68 67 66 65 64 63 62 61 60] [79 78 77 76 75 74 73 72 71 70] [89 88 87 86 85 84 83 82 81 80] [99 98 97 96 95 94 93 92 91 90]]

或者创建中间列表:

merged = np.zeros([0,10])
for i in chunker(X,10):
    e = function(i)
    print('new matrix',e)
    merged = np.vstack([merged, e])

print(merged)

但最有效的方法是在循环之前初始化一个 numpy 数组,然后在循环内设置该数组的行。您需要先计算最终 merged 数组的尺寸(这里我只是将其创建为 10x10 矩阵,因为我知道大小)。

merged = np.zeros([10,10])
for (r,i) in enumerate(chunker(X,10)):
    e = function(i)
    print('new matrix',e)
    merged[r,:] = e

print(merged)

【讨论】:

  • 这些是非常大的数组,有没有更有效的方法?
  • 我添加了两个附加选项。底部是迄今为止最有效的。
  • 我遇到了这个异常:ValueError: could not broadcast input array from shape (100) into shape (3208) 知道如何继续吗?...感谢您的帮助!
  • 您需要更改此行 merged = np.zeros([10,10]) 以匹配最终合并数组的行和列。根据您的错误,这两个数字的乘积至少应为 3208。[10,10] 中的第二个数字可能与您传递给 chunker 的第二个参数匹配(在您发布的代码中,即 10。所以您可能会写:merged = np.zeros([321,10])
  • 您可以将您现在拥有的代码编辑到您的问题中吗?
【解决方案2】:

我不确定是否有一种非常有效的方法可以在不求助于 cython、numba 或朋友的情况下做到这一点。

也许最轻的内存可能正在执行以下操作(不确定):

import numpy as np
from functools import reduce

large_array = reduce(lambda a1, a2: np.vstack([a1,a2]), array_iterable)

也就是说,您似乎知道结果数组的大小,因此生成一个空数组并使用 chunk 方法填充您的跟随会更有效

large_array = np.zeros((1000,1000,3208))

for i in chunker(X, 1000):
    large_array[i,:,:] = function(i)

您可以使用concurrent.futures 进一步加快速度,function() 中的 cpu/IO 负载越重,改进越大。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-31
    • 2011-05-20
    • 2020-06-19
    • 1970-01-01
    • 1970-01-01
    • 2020-10-07
    • 1970-01-01
    相关资源
    最近更新 更多