在Python≥3.5中,
deque
上的
sample()
函数效果很好,速度也相当快。
在Python 3.4中,您可以使用以下代码,其运行速度大约与
sample()
相同:
sample_indices = sample(range(len(deq)), 50)
[deq[index] for index in sample_indices]
在我的 MacBook 上使用 Python 3.6.8,这种解决方案比 Eli Korvigo 的解决方案快了超过44倍。 :)
我使用了一个包含100万个项的双端队列(deque),并随机取样了50个项:
from random import sample
from collections import deque
deq = deque(maxlen=1000000)
for i in range(1000000):
deq.append(i)
sample_indices = set(sample(range(len(deq)), 50))
%timeit [deq[i] for i in sample_indices]
1.68 ms ± 23.8 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)
%timeit sample(deq, 50)
1.94 ms ± 60.7 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
%timeit sample(range(len(deq)), 50)
44.9 µs ± 549 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
%timeit [val for index, val in enumerate(deq) if index in sample_indices]
75.1 ms ± 410 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
尽管如此,正如其他人指出的那样,deque
并不适合随机访问。如果您想要实现回放记忆,可以使用类似这样的旋转列表:
class ReplayMemory:
def __init__(self, max_size):
self.buffer = [None] * max_size
self.max_size = max_size
self.index = 0
self.size = 0
def append(self, obj):
self.buffer[self.index] = obj
self.size = min(self.size + 1, self.max_size)
self.index = (self.index + 1) % self.max_size
def sample(self, batch_size):
indices = sample(range(self.size), batch_size)
return [self.buffer[index] for index in indices]
如果有一百万个项目,取样50个项目速度非常快:
%timeit mem.sample(50)
sample(list(the_deque), k)
。 - kennytmrandom.sample(deq, size)
对我有效。已确认在3.4上无效。 - juanpa.arrivillaga