首页 > 解决方案 > 有没有更好的方法来围绕列表编写这个循环,这样它就不会出现内存错误?

问题描述

我有以下 Python 代码:

for i in range(0, len(oscillations) - sequence_length):
    a = patterns[i:i + sequence_length]
    b = oscillations[i:i + sequence_length]
    sequence_in = [a+b for a,b in zip(a,b)]
    sequence_out = oscillations[i + sequence_length]  
    network_input.append(sequence_in)
    network_output.append(sequence_out)

振荡的长度为 212922。振荡的每个元素的长度为 25。模式的长度完全相同。两个列表具有相同的结构,但具有不同的数据。

上面的代码代码失败,它给了我一个 MemoryError。有时在遍历循环时,有时在返回两个列表时。

如果我将列表缩短到大约 100000 个元素,那么它就可以工作。

我知道这可能是我试图在内存中分配太多,但我的问题是,是否有更聪明的方法来浏览我的列表,这样它就不需要分配那么多内存。

标签: pythonpython-3.xoptimization

解决方案


正如一些评论者指出的那样,您可能不需要构建整个列表network_inputnetwork_output. 对内存消耗的最大改进是yield

def stuff(oscillations, sequence_length, patterns):
    for i in range(0, len(oscillations) - sequence_length):
        a = patterns[i:i + sequence_length]
        b = oscillations[i:i + sequence_length]
        sequence_in = [a + b for a, b in zip(a, b)]
        sequence_out = oscillations[i + sequence_length]
        yield (sequence_in, sequence_out)

for s in stuff(oscillations, sequence_length, patterns):
    print(s)

通过注意到您多次对两个集合中的相同元素进行切片和求和,可以获得其他较小的改进。a并且b在迭代之间仅相差一个元素。您可以使用简单的移动和算法:

def moving_stuff(oscillations, sequence_length, patterns):
    ops = []
    sums = []
    for op in zip(oscillations, patterns):
        ops.append(op)
        if len(ops) > sequence_length:
            sequence_in = sums[:]
            sequence_out = op[0]
            yield (sequence_in, sequence_out)
            ops.pop(0)
            sums.pop(0)
        sums.append(sum(op))

推荐阅读