python - مولتيكي مولتيفالو غير محددة بيثون القاموس




dictionary data-structures (3)

إذا كان من الممكن تغيير بنية البيانات، فإنه سيكون من الأسهل أن يكون الدالة إعادة البيانات التي تحتاج إليها. وهذا سيكون مرنا تماما ويمكن أن تستوعب أي نوع من البيانات، إذا كنت بحاجة إلى تغييرها في وقت لاحق.

import random

def myfunc(*args):
    if 'red' in args:
        return 'blue'
    elif 'green' in args or 'violet' in args:
        return 'violet'
    else:
        r = random.random()
        if 0 < r < 0.2:
            return 'blue'
        else:
            return 'green'

print(myfunc('green', 'blue'))
print(myfunc('yellow'))

الإخراج (من الواضح أن السطر الثاني يتغير):

violet
blue

هناك بالفعل ديكت مفتاح متعدد في الثعبان وأيضا ديكت متعدد القيم. كنت في حاجة الى قاموس الثعبان الذي على حد سواء:

مثال:

# probabilistically fetch any one of baloon, toy or car
d['red','blue','green']== "baloon" or "car" or "toy"  

احتمال د ['ريد'] == d ['غرين'] مرتفع واحتمال d ['ريد']! = d ['ريد'] منخفض ولكن ممكن

يجب أن تكون قيمة الناتج المفرد محددة بشكل احتمالي (غامض) استنادا إلى قاعدة من المفاتيح على سبيل المثال: في القاعدة أعلاه يمكن أن تكون القاعدة إذا كانت المفاتيح "الحمراء" و "الزرقاء" ثم يعود "بالون" 80٪ من الوقت إذا الأزرق فقط ثم العودة "لعبة" 15٪ من الوقت آخر "سيارة" 5٪ من الوقت.

وينبغي تصميم طريقة الضبط بحيث يكون ذلك ممكنا:

d["red", "blue"] =[
    ("baloon",haseither('red','green'),0.8),
    ("toy",.....)
    ,....
]

أعلاه يعين قيم متعددة إلى القاموس مع وظيفة المسند والاحتمال المقابل. وبدلا من قائمة الاحالة المذكورة أعلاه حتى القاموس كما ان الاحالة سيكون من الأفضل:

d["red", "blue"] ={ 
    "baloon": haseither('red','green',0.8),
    "toy": hasonly("blue",0.15),
    "car": default(0.05)
}

في البالون أعلاه سوف تعاد 80٪ من الوقت إذا كان "الأحمر" أو الأخضر هو الحاضر، العودة لعبة 15٪ من الوقت إذا الأزرق الحاضر والعودة السيارة 5٪ من الوقت دون أي شرط.

هل هناك أي هياكل بيانات قائمة تستوفي المتطلبات المذكورة أعلاه في الثعبان؟ إذا كان لا ثم كيف يمكن تعديل رمز مولتيكيديكت لتلبية المتطلبات المذكورة أعلاه في الثعبان؟

إذا كان استخدام القاموس ثم يمكن أن يكون هناك ملف التكوين أو استخدام الديكورات المتداخلة المناسبة التي تقوم بتكوين المنطق المسند الاحتمالي أعلاه دون الحاجة إلى التعليمات البرمجية الصلبة إذا بيانات \ إلس.

ملاحظة: أعلاه هو الآلي مفيدة لقاعدة تعتمد على تطبيق الرد التلقائي وبالتالي اسمحوا لي أن أعرف إذا كان أي إطار قاعدة تستند مماثلة متاح في الثعبان حتى لو كان لا يستخدم بنية القاموس؟


يجب أن تكون قيمة الناتج المفرد محددة بشكل احتمالي (غامض) استنادا إلى قاعدة من المفاتيح على سبيل المثال: في القاعدة أعلاه يمكن أن تكون القاعدة إذا كانت المفاتيح "الحمراء" و "الزرقاء" ثم يعود "بالون" 80٪ من الوقت إذا الأزرق فقط ثم العودة "لعبة" 15٪ من الوقت آخر "سيارة" 5٪ من الوقت.

عارية في الاعتبار تحليل قضيتك ليست كاملة، وانها غامضة، ولكن يمكنك أن تفعل ما يلي "في الروح" (تلخيص النتائج المرجوة):

import random

def randomly_return(*colors):
    colors = set(*colors)
    if 'red' in colors and 'blue' in colors:
        if random.random() < 0.8:  # 80 % of the time
            return "baloon"

    if 'blue' in colors and len(colors) == 1:  # only blue in colors
        if random.random() < 0.15:
            return "toy"
        else:
            if random.random() < 0.05:
                return "car"

# other cases to consider

وأود أن تبقي هذا كدالة، لأنها وظيفة! ولكن إذا كنت تصر على جعلها ديكت مثل، ثم الثعبان دعونا القيام بذلك عن طريق تجاوز __getitem__ (المنظمة البحرية الدولية انها ليست بيثونيك).

class RandomlyReturn(object):
    def __getitem__(self, *colors):
        return randomly_return(*colors)

>>> r = RandomlyReturn()
>>> r["red", "blue"]  # 80% of the time it'll return "baloon"
"baloon"

من التوضيح الخاص بك، أوب يريد أن يمر وتوليد:

randreturn ((haseither (الأحمر والأزرق)، بالون: 0.8)، ((hasonly (الأزرق)، لعبة: 0.15))، (الافتراضي ()، سيارة: 0.05)))

تريد إنشاء وظيفة على النحو التالي:

funcs = {"haseither": lambda needles, haystack: any(n in haystack for n in needles),
         "hasonly": lambda needles, haystack: len(needles) == 1 and needles[1] in haystack}

def make_random_return(crits, default):
    def random_return(*colors):
        colors = set(*colors)
        for c in crits:
            if funcs[c["func"]](c["args"], colors) and random.random() > c["with_prob"]:
                return c["return_value"]
        return default
    return random_return

حيث تكون الحرجة والتخلف في هذه الحالة:

crit = [{"func": "haseither", "args": ("red", "blue"), "return_value": "baloon", "with_prob": 0.8}, ...]
default = "car"  # ??
my_random_return = make_random_return(crits, default)

كما أقول، احتمالاتك غامضة / لا تضيف ما يصل، لذلك أنت على الأرجح سوف تحتاج إلى قرص هذا ...

يمكنك توسيع تعريف الفئة عن طريق تمرير الحفرة والافتراض عند المثيل:

class RandomlyReturn(object):
    def __init__(self, crit, default):
        self.randomly_return = make_random_return(crit, default)
    def __getitem__(self, *colors):
        return self.randomly_return(*colors)

>>> r = RandomlyReturn(crit, default)
>>> r["red", "blue"]  # 80% of the time it'll return "baloon"
"baloon"

محاكاة مولتيكي قاموس

لم يسمح __getitem__() بمفاتيح متعددة في أونسيس ...

(مثل d["red", "green"] )

ويمكن محاكاة مفتاح متعدد مع tuple أو set مفاتيح. إذا كان الأمر لا يهم، set يبدو أفضل (في الواقع مجموعة قابلة للتجزئة قابلة للتجزئة، بحيث [ "red", "blue"] هو نفسه ["blue", "red"] .

محاكاة مولتيفال قاموس

القيم المتعددة متأصلة باستخدام أنواع بيانات معينة، يمكن أن يكون أي عنصر تخزين يمكن فهرسة بشكل ملائم. وينبغي أن ينص هذا المعيار على ذلك.

غير الحتمية

باستخدام توزيع الاحتمالات التي تحددها القواعد والافتراضات 1 ، يتم إجراء اختيار غير حتمي باستخدام هذه الوصفة من مستندات الثعبان.

MultiKeyMultiValNonDeterministicDict فئة

ياله من إسم. \ o / -nice!

وتتخذ هذه الفئة مفاتيح متعددة تحدد مجموعة قواعد احتمالية من قيم متعددة. أثناء إنشاء البند ( __setitem__() ) يتم حساب جميع احتمالات القيمة قبل كل توليفات المفاتيح 1 . أثناء الوصول إلى البند ( __getitem__() ) يتم اختيار توزيع الاحتمالات قبل __getitem__() ويتم تقييم النتيجة على أساس اختيار مرجح عشوائي.

فريف

import random
import operator
import bisect
import itertools

# or use itertools.accumulate in python 3
def accumulate(iterable, func=operator.add):
    'Return running totals'
    # accumulate([1,2,3,4,5]) --> 1 3 6 10 15
    # accumulate([1,2,3,4,5], operator.mul) --> 1 2 6 24 120
    it = iter(iterable)
    try:
        total = next(it)
    except StopIteration:
        return
    yield total
    for element in it:
        total = func(total, element)
        yield total

class MultiKeyMultiValNonDeterministicDict(dict):

    def key_combinations(self, keys):
        """get all combinations of keys"""
        return [frozenset(subset) for L in range(0, len(keys)+1) for subset in itertools.combinations(keys, L)]

    def multi_val_rule_prob(self, rules, rule):
        """
        assign probabilities for each value, 
        spreading undefined result probabilities
        uniformly over the leftover results not defined by rule.
        """
        all_results = set([result for result_probs in rules.values() for result in result_probs])
        prob = rules[rule]
        leftover_prob = 1.0 - sum([x for x in prob.values()])
        leftover_results = len(all_results) - len(prob)
        for result in all_results:
            if result not in prob:
                # spread undefined prob uniformly over leftover results
                prob[result] = leftover_prob/leftover_results
        return prob

    def multi_key_rule_prob(self, key, val):
        """
        assign probability distributions for every combination of keys,
        using the default for combinations not defined in rule set
        """ 
        combo_probs = {}
        for combo in self.key_combinations(key):
            if combo in val:
                result_probs = self.multi_val_rule_prob(val, combo).items()
            else:
                result_probs = self.multi_val_rule_prob(val, frozenset([])).items()
            combo_probs[combo] = result_probs
        return combo_probs

    def weighted_random_choice(self, weighted_choices):
        """make choice from weighted distribution"""
        choices, weights = zip(*weighted_choices)
        cumdist = list(accumulate(weights))
        return choices[bisect.bisect(cumdist, random.random() * cumdist[-1])]

    def __setitem__(self, key, val):
        """
        set item in dictionary, 
        assigns values to keys with precomputed probability distributions
        """

        precompute_val_probs = self.multi_key_rule_prob(key, val)        
        # use to show ALL precomputed probabilities for key's rule set
        # print precompute_val_probs        

        dict.__setitem__(self, frozenset(key), precompute_val_probs)

    def __getitem__(self, key):
        """
        get item from dictionary, 
        randomly select value based on rule probability
        """
        key = frozenset([key]) if isinstance(key, str) else frozenset(key)             
        val = None
        weighted_val = None        
        if key in self.keys():
            val = dict.__getitem__(self, key)
            weighted_val = val[key]
        else:
            for k in self.keys():
                if key.issubset(k):
                    val = dict.__getitem__(self, k)
                    weighted_val = val[key]

        # used to show probabality for key
        # print weighted_val

        if weighted_val:
            prob_results = self.weighted_random_choice(weighted_val)
        else:
            prob_results = None
        return prob_results

استعمال

d = MultiKeyMultiValNonDeterministicDict()

d["red","blue","green"] = {
    # {rule_set} : {result: probability}
    frozenset(["red", "green"]): {"ballon": 0.8},
    frozenset(["blue"]): {"toy": 0.15},
    frozenset([]): {"car": 0.05}
}

اختبارات

تحقق من الاحتمالات

N = 10000
red_green_test = {'car':0.0, 'toy':0.0, 'ballon':0.0}
red_blue_test = {'car':0.0, 'toy':0.0, 'ballon':0.0}
blue_test = {'car':0.0, 'toy':0.0, 'ballon':0.0}
red_blue_green_test = {'car':0.0, 'toy':0.0, 'ballon':0.0}
default_test = {'car':0.0, 'toy':0.0, 'ballon':0.0}

for _ in xrange(N):
    red_green_test[d["red","green"]] += 1.0
    red_blue_test[d["red","blue"]] += 1.0
    blue_test[d["blue"]] += 1.0
    default_test[d["green"]] += 1.0
    red_blue_green_test[d["red","blue","green"]] += 1.0

print 'red,green test      =', ' '.join('{0}: {1:05.2f}%'.format(key, 100.0*val/N) for key, val in red_green_test.items())
print 'red,blue test       =', ' '.join('{0}: {1:05.2f}%'.format(key, 100.0*val/N) for key, val in red_blue_test.items())
print 'blue test           =', ' '.join('{0}: {1:05.2f}%'.format(key, 100.0*val/N) for key, val in blue_test.items())
print 'default test        =', ' '.join('{0}: {1:05.2f}%'.format(key, 100.0*val/N) for key, val in default_test.items())
print 'red,blue,green test =', ' '.join('{0}: {1:05.2f}%'.format(key, 100.0*val/N) for key, val in red_blue_green_test.items())
red,green test      = car: 09.89% toy: 10.06% ballon: 80.05%
red,blue test       = car: 05.30% toy: 47.71% ballon: 46.99%
blue test           = car: 41.69% toy: 15.02% ballon: 43.29%
default test        = car: 05.03% toy: 47.16% ballon: 47.81%
red,blue,green test = car: 04.85% toy: 49.20% ballon: 45.95%

الاحتمالات قواعد المباراة!

الحواشي

  1. توزيع الافتراض

    وبما أن مجموعة القواعد غير معرفة بشكل كامل، يتم افتراض توزيعات الاحتمالات، ويتم معظمها في multi_val_rule_prob() . في الأساس أي احتمال غير محدد سوف ينتشر بشكل موحد على القيم المتبقية. ويتم ذلك لجميع تركيبات المفاتيح، ويخلق واجهة رئيسية معممة لاختيار عشوائي المرجحة.

    نظرا لمجموعة قواعد المثال

    d["red","blue","green"] = {
        # {rule_set} : {result: probability}
        frozenset(["red", "green"]): {"ballon": 0.8},
        frozenset(["blue"]): {"toy": 0.15},
        frozenset([]): {"car": 0.05}
    }

    سيؤدي ذلك إلى إنشاء التوزيعات التالية

    'red'           = [('car', 0.050), ('toy', 0.475), ('ballon', 0.475)]
    'green'         = [('car', 0.050), ('toy', 0.475), ('ballon', 0.475)]
    'blue'          = [('car', 0.425), ('toy', 0.150), ('ballon', 0.425)]
    'blue,red'      = [('car', 0.050), ('toy', 0.475), ('ballon', 0.475)]
    'green,red'     = [('car', 0.098), ('toy', 0.098), ('ballon', 0.800)]
    'blue,green'    = [('car', 0.050), ('toy', 0.475), ('ballon', 0.475)]
    'blue,green,red'= [('car', 0.050), ('toy', 0.475), ('ballon', 0.475)]
     default        = [('car', 0.050), ('toy', 0.475), ('ballon', 0.475)]

    إذا كان هذا غير صحيح، يرجى تقديم المشورة.







fuzzy-logic