2012-07-07 11 views
32

का उपयोग करके निर्दिष्ट वजन के साथ असतत यादृच्छिक चर उत्पन्न करना मैं एक साधारण फ़ंक्शन ढूंढ रहा हूं जो निर्दिष्ट (भी निर्दिष्ट) संभावनाओं के आधार पर निर्दिष्ट यादृच्छिक मानों की एक सरणी उत्पन्न कर सकता है। मुझे केवल फ्लोट वैल्यू जेनरेट करने की आवश्यकता है, लेकिन मुझे नहीं लगता कि यह किसी भी स्केलर को उत्पन्न करने में सक्षम क्यों नहीं होना चाहिए। मैं मौजूदा कार्यों से इसे बनाने के कई तरीकों के बारे में सोच सकता हूं, लेकिन मुझे लगता है कि शायद मुझे एक स्पष्ट SciPy या NumPy फ़ंक्शन याद आया।SciPy या NumPy

उदा .:

>>> 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) 

नोट: मैं scipy.stats.rv_discrete पाया, लेकिन मुझे समझ नहीं आता कि यह कैसे काम करता है। ,

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

तो rv_discrete क्या मैं का उपयोग कर किया जाना चाहिए है कि तुम मुझे एक साधारण उदाहरण और ऊपर "का स्पष्टीकरण भी उपलब्ध कराएं: विशेष रूप से, मैं समझता हूँ कि नहीं इस (नीचे) क्या मतलब है और न ही यह क्या करना चाहिए आकार "कथन?

उत्तर

42

एक अलग वितरण से चित्रण सीधे numpy में बनाया गया है। फ़ंक्शन को random.choice कहा जाता है (numpy दस्तावेज़ों में अलग वितरण के किसी भी संदर्भ के बिना खोजने के लिए मुश्किल)।

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

महान! लेकिन, सही वाक्यविन्यास है: np.random.choice (तत्व, 10, पी = सूची (संभावनाएं)) – Sina

+0

अच्छा। मुझे लगता है कि मैंने अपना मूल प्रश्न पोस्ट करने के बाद यह संस्करण सामने आया (मुझे लगता है कि इसे पहली बार 1.7.0 में रिलीज़ किया गया था जो मुझे विश्वास है कि 2013 में आया था)। – TimY

+0

बहुत अच्छा! सूची में कास्टिंग किए बिना भी काम करने लगता है: np.random।पसंद (तत्व, 10, पी = संभावनाएं))। – zeycus

24

यहां एक छोटा, अपेक्षाकृत सरल कार्य है जो भारित मान देता है, यह न्यूमपी के digitize, accumulate, और 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] 

यह इस तरह काम करता है:

  1. पहले accumulate का उपयोग कर हम डिब्बे पैदा करते हैं।
  2. फिर हम (0 के बीच, और 1) यादृच्छिक संख्या का एक समूह बनाने के random_sample
  3. का उपयोग कर हम digitize का उपयोग जो डिब्बे इन नंबरों में गिर जाते हैं को देखने के लिए।
  4. और संबंधित मान वापस करें।
+1

हां यह मूल रूप से मैं क्या सोच रहा था, लेकिन मैंने सोचा कि एक अंतर्निहित कार्य हो सकता है जो वास्तव में करता है। इसकी आवाज़ से, ऐसी कोई बात नहीं है। मुझे स्वीकार करना होगा - मैं इसे सुंदर ढंग से नहीं किया होता। - धन्यवाद – TimY

+0

NumPy सीधे 'numpy.cumsum()' प्रदान करता है, जिसका उपयोग 'np.add.accumulate()' ('np.add()' के बजाय किया जा सकता है, इसलिए आमतौर पर उपयोग नहीं किया जाता है, इसलिए मैं 'cumsum () ')। उपयोगी 'numpy.digitize() 'के लिए – EOL

+0

+1! हालांकि, SciPy वास्तव में एक ऐसा फ़ंक्शन प्रदान करता है जो सीधे प्रश्न का उत्तर देता है-मेरा जवाब देखें। – EOL

3

सबसे आसान DIY तरीका संभावित संचरण में संभाव्यताओं को जोड़ना होगा। इस तरह, आप यूनिट अंतराल को अपनी मूल संभावनाओं के बराबर लंबाई के उप-अंतराल में विभाजित करते हैं। अब [0,1) पर एक यादृच्छिक संख्या वर्दी उत्पन्न करें, और देखें कि यह किस अंतराल पर है।

+1

हां यह मूल रूप से मैं सोच रहा था, लेकिन मैंने सोचा कि एक अंतर्निहित फ़ंक्शन हो सकता है जो वास्तव में करता है। इसकी आवाज़ से, ऐसी कोई बात नहीं है। – TimY

14

आप एक अच्छी दिशा में जा रहे थे: अंतर्निहित scipy.stats.rv_discrete() काफी सीधे एक पृथक यादृच्छिक चर बनाता है। यह ऐसे काम करता है:

>>> 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] 

वितरण distrib ऊपर इस प्रकार अनुक्रमित रिटर्न values सूची से।

आम तौर पर, rv_discrete()पूर्णांक के अनुक्रम लेता है इसकी values=(…,…) तर्क के पहले तत्व में मूल्यों और ये मान देता है, इस मामले में; विशिष्ट (फ्लोट) मानों में कनवर्ट करने की कोई आवश्यकता नहीं है। यहां एक उदाहरण दिया गया है:

>>> 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]) 

जहां (पूर्णांक) इनपुट मान सीधे वांछित संभावना के साथ वापस आते हैं।

+4

नोट: मैंने उस पर टाइमिट चलाने की कोशिश की, और यह फ्रैक्सेल के पूरी तरह से numpy संस्करण की तुलना में एक अच्छा 100x धीमी प्रतीत होता है। क्या आप किसी भी मौके से जानते हैं कि वह क्यों है? – TimY

+0

वाह, दिलचस्प! 10k तत्वों पर, मुझे 300x धीमी गति का कारक भी मिलता है। मैंने कोड पर एक त्वरित नज़र डाली: कई चेक किए गए हैं, लेकिन मुझे लगता है कि वे समय चलने में इतने बड़े अंतर की व्याख्या नहीं कर सकते हैं; मैं Scipy कोड में पर्याप्त गहराई से नहीं गया था यह देखने में सक्षम था कि अंतर कहां से आ सकता है ... – EOL

+0

@TimY मेरा बेवकूफ अनुमान यह है कि धीमेपन शुद्ध पायथन में अधिक काम करने के कारण है, कम काम किया जा रहा है (नीचे हुड) सी में (पाइथन में गणितीय/वैज्ञानिक पैकेज सी कोड लपेटते हैं।) – dbliss

4

आप Lea का भी उपयोग कर सकते हैं, एक शुद्ध पायथन पैकेज जो संभावित संभाव्यता वितरण को समर्पित करने के लिए समर्पित है।

>>> 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) 

एट देखा!

संबंधित मुद्दे