2012-02-17 13 views
48

मेरे पास आइटम की एक सूची है। इन वस्तुओं में से प्रत्येक की अपनी संभावना है।इसकी संभावना से कोई आइटम कैसे चुनें?

क्या कोई अपनी संभाव्यता के आधार पर कोई आइटम चुनने के लिए एल्गोरिदम सुझा सकता है?

उत्तर

27

तो प्रत्येक आइटम के साथ एक नंबर है कि अपने रिश्तेदार संभावना के निशान, उदाहरण के लिए अगर आप 3 आइटम एक दो बार के रूप में अन्य दो में से किसी के रूप में चयनित होने की संभावना होना चाहिए की दुकान तो आप अपनी सूची होगा:

[{A,1},{B,1},{C,2}] 

फिर सूची की संख्या (यानी हमारे मामले में 4) योग करें। अब यादृच्छिक संख्या उत्पन्न करें और उस अनुक्रमणिका को चुनें। int अनुक्रमणिका = rand.nextInt (4); संख्या को वापस करें जैसे कि सूचकांक सही सीमा में है।

जावा कोड:

class Item { 
    int relativeProb; 
    String name; 

    //Getters Setters and Constructor 
} 

... 

class RandomSelector { 
    List<Item> items = new List(); 
    Random rand = new Random(); 
    int totalSum = 0; 

    RandomSelector() { 
     for(Item item : items) { 
      totalSum = totalSum + item.relativeProb; 
     } 
    } 

    public Item getRandom() { 

     int index = rand.nextInt(totalSum); 
     int sum = 0; 
     int i=0; 
     while(sum < index) { 
      sum = sum + items.get(i++).relativeProb; 
     } 
     return items.get(Math.max(0,i-1)); 
    } 
} 
+1

धन्यवाद Usman। लेकिन मुझे आश्चर्य है कि मुझे आई-वें आइटम या (i-1) वें आइटम लेना चाहिए? मेरा मतलब आइटम.get (i-1) आइटम्स के बजाय है .get (i) – Ruzanna

+0

i-1 अच्छा बिंदु। –

+2

यहां 'पी' कोई यादृच्छिक संख्या है तो हम कैसे कह सकते हैं कि सबसे अधिक संभावना आइटम पहले चुना जाता है .. उदाहरण: '[{ए, 10}, {बी, 20}]' तो आप कैसे कह सकते हैं कि मान लीजिए पहले पुनरावृत्ति में 'पी = 2' तो '2 <= 10' सत्य है और पहली वस्तु' {ए, 10} 'पहले चयनित हो रही है, भले ही दूसरी वस्तु में अधिक संभाव्यता – HybrisFreelance

18

बहाना है कि हम निम्न सूची

Item A 25% 
Item B 15% 
Item C 35% 
Item D 5% 
Item E 20% 

नाटक की सुविधा देता है कि सभी संभावनाओं पूर्णांक हैं, और प्रत्येक आइटम एक "सीमा" के रूप में गणना कि आवंटित की है।

Start - Sum of probability of all items before 
End - Start + own probability 

नई संख्या के रूप में इस प्रकार है

Item A 0 to 25 
Item B 26 to 40 
Item C 41 to 75 
Item D 76 to 80 
Item E 81 to 100 

अब 100 0 से एक यादृच्छिक संख्या लेने का कहना है की सुविधा देता है कि आप आइटम बी की रेंज में 32. 32 गिरता लेने हैं।

MJ

+0

चयन के लिए @ ब्रेंट के जवाब से यह तेज़ है, लेकिन अगर यह कहता है कि यह श्रेणी 0 से दस लाख थी, तो यह बहुत अधिक मेमोरी लेगी। –

+0

संभाव्यताओं को प्रतिशत नहीं होना चाहिए। हम संख्याओं के योग के लिए 0 के बीच एक यादृच्छिक संख्या चुन सकते हैं। – WVrock

10

आप Roulette Wheel Selection कोशिश कर सकते हैं।

सबसे पहले, सभी संभावनाओं को जोड़ें, फिर योग के अनुसार प्रत्येक को विभाजित करके सभी क्षमताओं को स्केल करें। मान लीजिए संभावनाएं A(0.4), B(0.3), C(0.25) and D(0.05) हैं। फिर आप श्रेणी [0, 1] में एक यादृच्छिक फ़्लोटिंग-पॉइंट नंबर उत्पन्न कर सकते हैं। अब आप इस तरह का फैसला कर सकते हैं:

random number between 0.00 and 0.40 -> pick A 
       between 0.40 and 0.70 -> pick B 
       between 0.70 and 0.95 -> pick C 
       between 0.95 and 1.00 -> pick D 

तुम भी यादृच्छिक पूर्णांकों के साथ यह कर सकते हैं - कहते हैं कि तुम 99 (सम्मिलित) के लिए 0 के बीच एक यादृच्छिक पूर्णांक उत्पन्न करते हैं, तो आप इसके बाद के संस्करण की तरह फैसला लेने के लिए कर सकते हैं।

+0

(+1) यह मुझे परेशान करता है कि यह एल्गोरिदम लगभग हमेशा जीएएस (विकिपीडिया पर आपका लिंक और [यहां] देखें (http://www.cse.unr.edu/~banerjee/selection.htm के संदर्भ में वर्णित है।) भी)। भारित रूले व्हील एल्गोरिदम में सभी प्रकार के उपयोग होते हैं जिनके पास जीएएस (जैसे यह बहुत सवाल) से कोई लेना देना नहीं है। –

+0

हाँ, यह अजीब है। मैंने जीए का अध्ययन करते समय इसका नाम भी सीखा, लेकिन मैंने इस तकनीक का इस्तेमाल किसी अन्य कारण से पहले किया था। – 0605002

60
  1. समान रूप से वितरित यादृच्छिक संख्या उत्पन्न करें।
  2. का दौरा किया तत्वों की संचयी संभावना जब तक अपनी सूची के माध्यम से दोहराएं यादृच्छिक संख्या से अधिक है

नमूना कोड:

double p = Math.random(); 
double cumulativeProbability = 0.0; 
for (Item item : items) { 
    cumulativeProbability += item.probability(); 
    if (p <= cumulativeProbability) { 
     return item; 
    } 
} 
+0

अच्छा और हल्का वजन – myro

+1

यहां 'पी' कोई यादृच्छिक संख्या है तो हम कैसे कह सकते हैं कि सबसे अधिक संभावना आइटम पहले चुना जाता है .. उदाहरण: '[{ए, 10}, {बी, 20}]' तो आप कैसे हो सकते हैं हम कहते हैं कि पहले पुनरावृत्ति में मान लीजिए 'p = 2' तो' 2 <= 10' सत्य है और पहली वस्तु '{ए, 10}' पहले चयनित हो रही है, भले ही दूसरी वस्तु में अधिक संभाव्यता – HybrisFreelance

+5

@ U2Answer है, इस एल्गोरिदम के लिए आवश्यक है सामान्यीकृत होने की संभावनाएं (सभी संभावनाओं के योग से विभाजित)। ऐसा करके आप सुनिश्चित करते हैं कि Σp_i = 1 और फिर 0 और 1 के बीच एक यादृच्छिक संख्या चाल करेगी। – aioobe

1

ब्रेंट का जवाब अच्छा है, लेकिन यह के लिए खाते में नहीं है मामलों में 0 की संभावना के साथ गलती से किसी आइटम को चुनने की संभावना जहां पी = 0. संभावना को जांचकर (या शायद पहले स्थान को नहीं जोड़ना) को संभालने के लिए पर्याप्त आसान है:

+1

लें मुझे नहीं लगता कि आपको उस मामले के बारे में चिंता करने की आवश्यकता है जहां आइटम की संभावना शून्य है। आपको या तो पहले से ही लूप से बाहर निकलना चाहिए या आप जारी रहेंगे क्योंकि संचयी संभावनाएं नहीं बदलेगी। – rrs

5

मेरी विधि बहुत सरल है। एक यादृच्छिक संख्या उत्पन्न करें।अब जब से आपकी वस्तुओं की संभावनाएं ज्ञात हैं, तो बस संभावना की क्रमबद्ध सूची के माध्यम से पुन: प्रयास करें और उस आइटम को चुनें जिसकी संभावना यादृच्छिक रूप से जेनरेट की गई संख्या से कम है।

अधिक जानकारी के लिए, मेरा उत्तर here पढ़ें।

6

Ushman's, Brent's में वर्णित एल्गोरिदम और @ कौशया के उत्तरों Apache commons-math लाइब्रेरी में लागू किए गए हैं।

(ग्रूवी कोड इस प्रकार) EnumeratedDistribution वर्ग पर एक नज़र डालें:

def probabilities = [ 
    new Pair<String, Double>("one", 25), 
    new Pair<String, Double>("two", 30), 
    new Pair<String, Double>("three", 45)] 
def distribution = new EnumeratedDistribution<String>(probabilities) 
println distribution.sample() // here you get one of your values 

नोट संभावनाओं के उस राशि 1 या 100 के बराबर होने की जरूरत नहीं है - यह स्वचालित रूप से सामान्य हो जाएगा।

+0

@ कौशया कौन है? हो सकता है कि उसने नाम बदल दिया हो। इसलिए संबंधित उत्तरों को हाइपरलिंक करना बेहतर है। –

4

ऐसा करने का एक धीमा लेकिन सरल तरीका यह है कि प्रत्येक सदस्य अपनी संभावना के आधार पर एक यादृच्छिक संख्या चुनने और उच्चतम मूल्य वाले व्यक्ति को चुनने के लिए है।

सादृश्य:

कल्पना कीजिए 3 में से 1 लोग चुने जाने की आवश्यकता है, लेकिन वे अलग अलग संभावनाओं की है। आप उन्हें विभिन्न चेहरे के साथ मर जाते हैं। पहले व्यक्ति के पासा में 4 चेहरे, दूसरे व्यक्ति के 6, और तीसरे व्यक्ति के 8 होते हैं। वे अपने मर जाते हैं और सबसे बड़ी संख्या जीतते हैं।

चलें कहते हैं कि हम निम्न सूची है:

[{A,50},{B,100},{C,200}]

स्यूडोकोड:

A.value = random(0 to 50); 
B.value = random(0 to 100); 
C.value = random (0 to 200); 

हम उच्चतम मूल्य के साथ एक चुनना।

उपरोक्त यह विधि बिल्कुल संभावनाओं को मानचित्रित नहीं करती है। उदाहरण के लिए 100 में 50 से अधिक बार मौका नहीं होगा। लेकिन हम इसे विधि को थोड़ा-सा बदलकर कर सकते हैं।

विधि 2

इसके बजाय 0 से वजन करने के लिए एक नंबर उठा के हम उन्हें वर्तमान चर के अलावा करने के लिए पिछले चर की ऊपरी सीमा से सीमित कर सकते हैं।

[{A,50},{B,100},{C,200}]

स्यूडोकोड:

A.lowLimit= 0; A.topLimit=50; 
B.lowLimit= A.topLimit+1; B.topLimit= B.lowLimit+100 
C.lowLimit= B.topLimit+1; C.topLimit= C.lowLimit+200 

जिसके परिणामस्वरूप सीमा

A.limits = 0,50 
B.limits = 51,151 
C.limits = 152,352 

तो हम 0 से 352 के लिए एक यादृच्छिक संख्या ले सकते हैं और देखने के लिए प्रत्येक चर की सीमा के साथ उसकी तुलना चाहे यादृच्छिक संख्या इसकी सीमाओं में है।

मेरा मानना ​​है कि इस ट्वीक में बेहतर प्रदर्शन है क्योंकि केवल 1 यादृच्छिक पीढ़ी है।

अन्य उत्तरों में एक समान विधि है लेकिन इस विधि को कुल 100 या 1.00 की आवश्यकता नहीं है।

function selrnd(a::Vector{Int}) 
    c = a[:] 
    sumc = c[1] 
    for i=2:length(c) 
     sumc += c[i] 
     c[i] += c[i-1] 
    end 
    r = rand()*sumc 
    for i=1:length(c) 
     if r <= c[i] 
      return i 
     end 
    end 
end 

इस समारोह कुशलता से एक आइटम के सूचकांक रिटर्न:

+0

यह नीचे क्यों मतदान किया जाता है? मैं एक स्पष्टीकरण की सराहना करता हूं। – WVrock

+0

इंजेनिअस! मुझें यह पसंद है। – Siddhartha

+0

आपकी विधि संभाव्यताओं को जितनी आसानी से दिखाई देती है उतनी आसानी से मैप नहीं करती है। मान लीजिए कि हम दो विकल्प चाहते हैं, ए और बी ए में 2/5 = 0 से 40 है, बी में 3/5 = 0 से 60 है। अगर हम इसे आपकी विधि से अनुकरण करते हैं, तो 1/3 समय बी बी के बीच चयन करेगा और 60, सफलता की गारंटी।फिर उस समय के दूसरे 2/3, बी 0 से 40 होंगे और ए 0 से 40 होगा, जिससे उन्हें बाधाएं भी मिलेंगी, ताकि समय के 2/2 में से 1/2, बी जीत जाएगा। यह 1/3 + 1/3 = 2/3 है, जो बी 3 जीतने वाले अपेक्षित 3/5 से अलग है। –

-3

आप जूलिया कोड इस्तेमाल कर सकते हैं।

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