OpenAI发布了一套名为“Open AI Gym”的机器学习/强化学习环境。一些环境是基于图像的,因此当与存储10万或数百万帧的环境观察的算法一起使用时,可能具有非常大的存储器占用空间。
在深入学习DeepQ Learning的参考实现时,我找到了一对类,LazyFrameStack
和LazyFrames
声称“确保观察之间的公共帧只存储一次......以优化内存使用,这对于DQN的1M帧来说可能是巨大的重播缓冲区。“
在参考实现中,DeepQ代理获取以四个为一组堆叠在一起的帧,然后将这些帧放入重放缓冲区。看过这两个类的实现后,对我来说这些如何节省内存并不明显 - 如果有的话,因为LazyFrames
基本上是围绕一组四个numpy
数组的容器对象,不应该LazyFrame
有更大的内存占用量吗?
在Python中,对象作为引用传递。这意味着即使LazyFrame对象可能是一个非常大的numpy数组的列表,LazyFrame对象本身的大小也很小,因为它只存储对np.ndarray
s的引用。换句话说,您可以将LazyFrame视为仅指向np.ndarray
数据,而不是实际存储单个数组的每个副本。
import numpy as np
a = np.ones((2,3))
b = np.ones((2,3))
X = [a, b]
print(X)
>>> [array([[1., 1., 1.],
[1., 1., 1.]]),
array([[1., 1., 1.],
[1., 1., 1.]])]
X_stacked = np.stack(X)
print(X_stacked)
>>> array([[[1., 1., 1.],
[1., 1., 1.]],
[[1., 1., 1.],
[1., 1., 1.]]])
a[0] = 2
print(X)
>>> [array([[2., 2., 2.],
[1., 1., 1.]]),
array([[1., 1., 1.],
[1., 1., 1.]])]
print(X_stacked)
>>> array([[[1., 1., 1.],
[1., 1., 1.]],
[[1., 1., 1.],
[1., 1., 1.]]])
正如你在这里看到的,X
(这是一个数组列表)只存储对a
和b
的引用,因此当我们做a[0] = 2
时,可以通过打印X
看到变化。但是,一旦堆叠数组,实际上就会创建一个具有大量内存的新数组。
为了更好地解决你的“如何节省内存”的问题,这是一个例子。
import sys
a = np.random.randn(210, 160, 3)
b = np.random.randn(210, 160, 3)
X = [a,b]
X_stacked = np.stack(X)
print(sys.getsizeof(X))
>>> 80
print(sys.getsizeof(X_stacked))
>>> 1612944