Probability Dictionary

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
anogayales
User
Beiträge: 456
Registriert: Mittwoch 15. April 2009, 14:11

Hallo liebe Python Gemeinde :)

Ich arbeite gerade an einem Dictionary, dass bestimmte Schlüssel mit einer bestimmten Wahrscheinlichkeit zurück liefern. Leider bin ich mit dem Ansatz noch nicht ganz zufrieden. Außerdem möchte ich noch wissen, wie ich Objekte mit bestimmten Wahrscheinlichkeiten nun letztendlich ausgeben kann.

Mein Ansatz:

Code: Alles auswählen

class ProbabilityDictionary(defaultdict):

    def __init__(self, *args):
        defaultdict.__init__(self, list, args)

    def normalize_probabilities(self):
        for key, value in self.items():
            probability_sum = sum([probability for successor, probability  in value])
            for pair in value:
                #gefällt mir ganz und gar nicht
                pair[0] /= float(probability_sum)

    def get_probable_item(self, key):
         random_float = random.random()
         value = self.__getitem__(key)
         random.shuffle(value)
         for successor, probability in value:
             if probability > random_float:
                 return successor
         return random.choice(value)[0] 
Verwendung:

Code: Alles auswählen

probability_mapping = ProbabilityDictionary()
probability_mapping[1].append([20, 0.75])
probability_mapping[1].append([19, 0.25])
probability_mapping.normalize_probabilities()
probability_mapping.get_probable_item(1)
Hat jemand Vorschläge? Ich glaub ich hab sowas ähnliches schonmal hier gesehen, leider aber nicht gefunden.

Edit:
Um das ganze ein bisschen benutzerfreundlicher zu machen, habe ich meiner Klasse eine weitere Methode spendiert. Hier muss der Benutzer nicht extra eine Liste anlegen, würde er ein Tupel nehmen würde es beim Normalisieren krachen. Lösung:

Code: Alles auswählen

    def add_item(self, key, value, probability=1):
        self[key].append([value, probability])
Grüße,
anogayales
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Ich würde sagen, dass hier ein Dictionary die falsche Datenstruktur ist.

Code: Alles auswählen

>>> elements = [(0.1, 1), (0.3, 2), (0.4, 3), (0.2, 4)]
>>> def sort(data):
...     result = []
...     p = 0.0
...     for q, v in data:
...         p += q
...         result.append((p, v))
...     return result
... 
>>> probs = sort(elements)
>>> probs
[(0.1, 1), (0.4, 2), (0.8, 3), (1.0, 4)]                                                                  
>>> import bisect                                                                                         
>>> import random                                                                                         
>>> def get(data):                                                  
...     ps = [p for (p, _) in data]                                              
...     return data[bisect.bisect_left(ps, random.random())][1]                             
...                                                                                                                                                                                                           
>>> [get(probs) for _ in range(20)]
[4, 4, 3, 1, 3, 3, 3, 3, 2, 3, 4, 3, 4, 3, 3, 2, 2, 3, 1, 1]
Natürlich kann man das alles noch ein wenig besser kapseln.
Das Leben ist wie ein Tennisball.
anogayales
User
Beiträge: 456
Registriert: Mittwoch 15. April 2009, 14:11

Moment :)

Ein Dictionary verwende ich nur um verschiedene Klassen zu trennen. Für jede Klasse verwalte ich ja auch eine Liste. Du zeigst in deinem Beispiel ja nur einer dieser Klassen.

Aber trotzdem danke! Die Vorverarbeitung und die Auswahl ist auf jeden Fall besser als bei mir :)

Grüße,
anogayales
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Ich hatte ganz übersehen, dass du nicht die Wahrscheinlichkeiten als Schlüssel nimmst. Dann kann man natürlich ein Dictionary verwenden. Das hindert dich ja aber nicht daran, meinen Ansatz im Hintergrund zu verwenden.
Das Leben ist wie ein Tennisball.
Antworten