python知識備忘集合(持續更新)
======================deque=========================================
強化學習的experience replay 模組, 之前考慮到執行的速度,我一直用numpy陣列實現,但用起來並不方便,程式碼也不簡潔。用deque必然方便多了,但執行速度怎樣?試過才知道。
from collections import deque
import time
d = deque(maxlen=1000000)
d.append('abc')
print d
d.extend([1,2,3])
print d
d.rotate(1)
print d
print d.count(1)
d.remove(2)
print d
d.pop()
print d
簡單記錄deque的主要操作,都很直觀的。remove()方法會從左至右丟棄第一個匹配的物件。extend()方法可以新增一個序列(用list包裝),rotate(1)方法類似於把佇列中所有元素的序號+1
值得注意的是:和使用陣列一樣,可以使用d[0]方法讀取和更改佇列中元素的值。
from collections import deque
import time
d = deque(maxlen=1000000)
d.append('abc')
d.append('aaa')
print d[0]
d[0] = '666'
print d[0]
print d
關於deque的速度:
之前看過一些資料,說deque是雙向的連結串列。那麼我相信入隊和出隊的速度是迅速的。連結串列的問題在於增刪查改佇列中間的物件是很慢的。
1,增和刪
deque沒有直接在佇列中間增加一個元素的方法,但可以通過rotate()方法調整佇列中元素的序號,再使用append新增
from collections import deque
import time
d = deque(maxlen=1000000)
for i in xrange(1000000):
d.append('aaa')
t1 = time .time()
d.rotate(500000)
t2 = time.time()
print t2 - t1
d.append('lll')
t3 = time.time()
print t3 - t2
結果是
0.000247955322266
2.40802764893e-05
因此,對於1000000個元素的佇列,增和刪的操作,在最差的情況下,在耗時在
2,查和改
from collections import deque
import time
d = deque(maxlen=1000000)
for i in xrange(1000000):
d.append('aaa')
t1 = time.time()
print d[500000]
t2 = time.time()
print t2 - t1
t3 = time.time()
d[500001] = '333'
t4 = time.time()
print t4 - t3
結果是:
0.00019097328186
0.00026798248291
對於1000000個元素的佇列,在最壞的情況下,查和改的耗時在
3,取樣
from collections import deque
import time
import random
d = deque(maxlen=1000000)
for i in xrange(1000000):
d.append('aaa')
t1 = time.time()
random.sample(d,64)
t2 = time.time()
print t2 - t1
結果是:0.0023889541626
random.sample()方法是未經優化的,用下面這個方法可以獲得更快的速度
def sample(d,k):
s_list = numpy.random.randint(0,len(d)*2/k,k).tolist()
#print s_list
result_list = []
for i in s_list:
d.rotate(i)
result_list.append(d[0])
return result_list
用這個方法耗時:0.00147318840027
以上時間的測量結果是有小幅波動的,並不十分精確
總結,1000000個元素,基本就是experience replay 的規模了。deque和list相比,優勢在於1執行緒安全2從兩段存取資料是O(1)速度。而list從左邊存取是O(n)速度,從右邊存取是O(1)速度。