2012-07-07 32 views
32

Tôi đang tìm một hàm đơn giản có thể tạo ra một mảng các giá trị ngẫu nhiên được chỉ định dựa trên xác suất tương ứng (cũng được xác định). Tôi chỉ cần nó để tạo ra các giá trị float, nhưng tôi không thấy tại sao nó không thể tạo ra bất kỳ vô hướng nào. Tôi có thể nghĩ về nhiều cách để xây dựng điều này từ các chức năng hiện có, nhưng tôi nghĩ rằng tôi có thể chỉ bỏ qua một chức năng SciPy hoặc NumPy rõ ràng.Tạo các biến ngẫu nhiên rời rạc với các trọng số xác định bằng SciPy hoặc NumPy

ví dụ .:

>>> values = [1.1, 2.2, 3.3] 
>>> probabilities = [0.2, 0.5, 0.3] 
>>> print some_function(values, probabilities, size=10) 
(2.2, 1.1, 3.3, 3.3, 2.2, 2.2, 1.1, 2.2, 3.3, 2.2) 

Lưu ý: Tôi tìm thấy scipy.stats.rv_discrete nhưng tôi không hiểu tại sao nó hoạt động. Cụ thể, tôi không hiểu những gì này (dưới đây) có nghĩa là cũng không gì nó nên làm:

numargs = generic.numargs 
[ <shape(s)> ] = ['Replace with resonable value', ]*numargs 

Nếu rv_discrete là những gì tôi nên sử dụng, bạn có thể vui lòng cung cấp cho tôi với một ví dụ đơn giản và giải thích những điều trên " hình dạng "tuyên bố?

Trả lời

42

Vẽ từ bản phân phối rời rạc được xây dựng trực tiếp thành gọn gàng. Chức năng này được gọi là random.choice (khó tìm mà không có bất kỳ tham chiếu nào đến các bản phân phối rời rạc trong tài liệu gọn gàng).

elements = [1.1, 2.2, 3.3] 
probabilities = [0.2, 0.5, 0.3] 
np.random.choice(elements, 10, p=probabilities) 
+3

Tuyệt quá! Tuy nhiên, cú pháp chính xác là: np.random.choice (các phần tử, 10, p = danh sách (xác suất)) – Sina

+0

Tốt. Tôi nghĩ rằng phiên bản này xuất hiện sau khi tôi đăng câu hỏi ban đầu của mình (tôi nghĩ rằng điều này đã được phát hành lần đầu tiên trong 1.7.0 mà tôi tin là đến năm 2013). – TimY

+0

Rất đẹp! Dường như cũng làm việc mà không cần đưa vào danh sách: np.random.lựa chọn (các phần tử, 10, p = xác suất)). – zeycus

24

Dưới đây là một hàm ngắn, tương đối đơn giản trả về các giá trị có trọng số, nó sử dụng số digitize, accumulate của NumPy và random_sample.

import numpy as np 
from numpy.random import random_sample 

def weighted_values(values, probabilities, size): 
    bins = np.add.accumulate(probabilities) 
    return values[np.digitize(random_sample(size), bins)] 

values = np.array([1.1, 2.2, 3.3]) 
probabilities = np.array([0.2, 0.5, 0.3]) 

print weighted_values(values, probabilities, 10) 
#Sample output: 
[ 2.2 2.2 1.1 2.2 2.2 3.3 3.3 2.2 3.3 3.3] 

Nó hoạt động như thế này:

  1. đầu tiên sử dụng accumulate chúng ta tạo ra thùng.
  2. Sau đó, chúng tôi tạo ra một loạt các con số ngẫu nhiên (giữa 0, và 1) sử dụng random_sample
  3. Chúng tôi sử dụng digitize để xem những thùng những con số này rơi vào.
  4. Và trả về các giá trị tương ứng.
+1

Có điều này về cơ bản là những gì tôi đang nghĩ đến, nhưng tôi chỉ nghĩ rằng có thể có một hàm tích hợp thực hiện chính xác điều đó. Từ âm thanh của nó, không có thứ gì như vậy cả. Tôi phải thừa nhận - tôi sẽ không làm điều đó một cách tao nhã. - Cảm ơn – TimY

+0

NumPy cung cấp trực tiếp 'numpy.cumsum()', có thể được sử dụng thay cho 'np.add.accumulate()' ('np.add()' không được sử dụng phổ biến, vì vậy tôi khuyên bạn nên sử dụng 'cumsum () '). – EOL

+0

+1 cho 'numpy.digitize()' hữu ích! Tuy nhiên, SciPy thực sự cung cấp một hàm trả lời trực tiếp câu hỏi — xem câu trả lời của tôi. – EOL

3

Cách tự làm đơn giản nhất là tổng hợp xác suất thành phân phối tích lũy. Bằng cách này, bạn chia khoảng thời gian đơn vị thành các khoảng thời gian phụ có độ dài bằng với xác suất ban đầu của bạn. Bây giờ tạo ra một đồng phục số ngẫu nhiên đơn trên [0,1), và và xem khoảng thời gian nó đến.

+1

Có điều này về cơ bản là những gì tôi đã nghĩ đến, nhưng tôi chỉ nghĩ rằng có thể có một chức năng tích hợp thực hiện chính xác điều đó. Từ âm thanh của nó, không có thứ gì như vậy cả. – TimY

14

Bạn đang đi theo một hướng tốt: được xây dựng trong scipy.stats.rv_discrete() khá trực tiếp tạo ra một biến ngẫu nhiên rời rạc. Dưới đây là cách hoạt động:

>>> from scipy.stats import rv_discrete 

>>> values = numpy.array([1.1, 2.2, 3.3]) 
>>> probabilities = [0.2, 0.5, 0.3] 

>>> distrib = rv_discrete(values=(range(len(values)), probabilities)) # This defines a Scipy probability distribution 

>>> distrib.rvs(size=10) # 10 samples from range(len(values)) 
array([1, 2, 0, 2, 2, 0, 2, 1, 0, 2]) 

>>> values[_] # Conversion to specific discrete values (the fact that values is a NumPy array is used for the indexing) 
[2.2, 3.3, 1.1, 3.3, 3.3, 1.1, 3.3, 2.2, 1.1, 3.3] 

Sự phân bố distrib trên do đó trả về chỉ số từ danh sách values.

Nói chung, rv_discrete() nhận một chuỗi gồm số nguyên giá trị trong các thành phần đầu tiên của đối số values=(…,…) và trả về các giá trị này, trong trường hợp này; không cần phải chuyển đổi thành các giá trị (float) cụ thể. Dưới đây là ví dụ:

>>> values = [10, 20, 30] 
>>> probabilities = [0.2, 0.5, 0.3] 
>>> distrib = rv_discrete(values=(values, probabilities)) 
>>> distrib.rvs(size=10) 
array([20, 20, 20, 20, 20, 20, 20, 30, 20, 20]) 

trong đó giá trị đầu vào (số nguyên) được trả về trực tiếp với xác suất mong muốn.

+4

LƯU Ý: Tôi đã thử chạy thời gian trên nó, và nó có vẻ là một tốt hơn 100x chậm hơn so với phiên bản hoàn toàn sần của fraxel. Bạn có cơ hội nào biết tại sao không? – TimY

+0

Chà, thú vị! Trên 10k yếu tố, tôi thậm chí còn có được một yếu tố chậm hơn 300x. Tôi đã xem nhanh mã: có nhiều kiểm tra được thực hiện, nhưng tôi đoán rằng họ không thể giải thích sự khác biệt lớn trong thời gian chạy; Tôi đã không đi sâu vào mã Scipy để có thể thấy sự khác biệt có thể đến từ đâu… – EOL

+0

@TimY đoán ngây thơ của tôi là sự chậm chạp là do nhiều công việc đang được thực hiện trong Python tinh khiết, ít công việc đang được thực hiện (theo mui xe) trong C. (các gói toán học/khoa học trong Python có khuynh hướng bọc mã C.) – dbliss

4

Bạn cũng có thể sử dụng Lea, gói Python thuần túy dành riêng cho phân phối xác suất riêng biệt.

>>> distrib = Lea.fromValFreqs((1.1,2),(2.2,5),(3.3,3)) 
>>> distrib 
1.1 : 2/10 
2.2 : 5/10 
3.3 : 3/10 
>>> distrib.random(10) 
(2.2, 2.2, 1.1, 2.2, 2.2, 2.2, 1.1, 3.3, 1.1, 3.3) 

Et voilà!

Các vấn đề liên quan