2013-09-04 35 views
6

Khi viết một tập lệnh, tôi phát hiện ra hàm numpy.random.choice. Tôi thực hiện nó bởi vì nó đã được sạch hơn nhiều so với tuyên bố nếu tương đương. Tuy nhiên, sau khi chạy tập lệnh, tôi nhận ra rằng đáng kể là chậm hơn câu lệnh if.Tại sao ngẫu nhiên.choice quá chậm?

Sau đây là MWE. Phương pháp đầu tiên mất 0,0 s, trong khi phương pháp thứ hai mất 7,2 s. Nếu bạn mở rộng vòng lặp i, bạn sẽ thấy tốc độ ngẫu nhiên chậm.

Mọi người có thể nhận xét về lý do ngẫu nhiên.choice chậm hơn rất nhiều không?

import numpy as np 
import numpy.random as rand 
import time as tm 

#------------------------------------------------------------------------------- 

tStart = tm.time() 
for i in xrange(100): 
    for j in xrange(1000): 
     tmp = rand.rand() 
     if tmp < 0.25: 
      var = 1 
     elif tmp < 0.5: 
      var = -1 
print('Time: %.1f s' %(tm.time() - tStart)) 

#------------------------------------------------------------------------------- 

tStart = tm.time() 
for i in xrange(100): 
    for j in xrange(1000): 
     var = rand.choice([-1, 0, 1], p = [0.25, 0.5, 0.25]) 
print('Time: %.1f s' %(tm.time() - tStart)) 
+3

Đó không thực sự là một sự so sánh công bằng. Mỗi lần, numpy phải lấy tổng tích lũy của danh sách p, đặt nó vào một vectơ mới, và sau đó lặp lại nó. Bạn đang thực hiện tiền xử lý hiệu quả bằng cách biết rằng chỉ có ba biến, và tổng của giá trị đầu tiên và thứ ba là 0,5. Ngoài ra, như được lưu ý bên dưới, phần mềm được tối ưu hóa cho các hoạt động được vector hóa, không phải để thực hiện một thao tác đơn lẻ hàng nghìn lần. –

+1

Ngoài ra, sử dụng 'timeit', không phải' thời gian'. – Marcin

Trả lời

12

Bạn đang sử dụng sai. Vectorize phẫu thuật, hoặc NumPy sẽ cung cấp không có lợi ích:

var = numpy.random.choice([-1, 0, 1], size=1000, p=[0.25, 0.5, 0.25]) 

Timing dữ liệu:

>>> timeit.timeit('''numpy.random.choice([-1, 0, 1], 
...          size=1000, 
...          p=[0.25, 0.5, 0.25])''', 
...    'import numpy', number=10000) 
2.380380242513752 

>>> timeit.timeit(''' 
... var = [] 
... for i in xrange(1000): 
...  tmp = rand.rand() 
...  if tmp < 0.25: 
...   var.append(1) 
...  elif tmp < 0.5: 
...   var.append(-1) 
...  else: 
...   var.append(0)''', 
... setup='import numpy.random as rand', number=10000) 
5.673041396894519 
+2

+1 Tốc độ này nhanh gấp 7 lần vòng lặp đầu tiên. –

+0

Như đã viết, bạn có so sánh táo với táo không? Đầu tiên tính 10^3 * 10^4 = 10^7 số ngẫu nhiên, nhưng số thứ hai tính 10^2 * 10^3 * 10^4 = 10^9 số ngẫu nhiên, không? – DSM

+0

@DSM: Rất tiếc. Đã sao chép điều sai trái theo thời gian. Đang sửa ... – user2357112

1

tôi nghi ngờ tính tổng quát của np.random.choice đang chậm nó xuống, nhiều hơn như vậy cho các mẫu nhỏ hơn những người lớn.

Một vector hóa thô của phiên bản if là:

def foo(n): 
    x = np.random.rand(n) 
    var = np.zeros(n) 
    var[x<.25] = -1 
    var[x>.75] = 1 
    return var 

Chạy trong ipython tôi nhận được:

timeit np.random.choice([-1,0,1],size=1000,p=[.25,.5,.25]) 
1000 loops, best of 3: 293 us per loop 

timeit foo(1000) 
10000 loops, best of 3: 83.4 us per loop 

timeit np.random.choice([-1,0,1],size=100000,p=[.25,.5,.25]) 
100 loops, best of 3: 11 ms per loop 

timeit foo(100000) 
100 loops, best of 3: 8.12 ms per loop 

Vì vậy, đối với kích thước 1000, choice là 3-4x chậm hơn, nhưng với vectơ lớn , sự khác biệt bắt đầu biến mất.