pythonnaivebayes

Naive Bayes method for two dice


I need a help with realization of naïve Bayes method for two dice - one of them is a 'normal' die with six sides such that each of the sides comes up with equal probability of 1/6. The other one is a loaded die that gives the outcome 6 with every second try.

My program should get as its input the choice of the die and then simulates a sequence of ten rolls.

I have to start from the odds 1:1, and then apply the Naive Bayes method to update the odds after each outcome to decide which of the dice was chose (most likely). It should return True if the most likely die is the loaded one, and False otherwise.

My code:

import numpy as np

p1 = [1/6, 1/6, 1/6, 1/6, 1/6, 1/6]   # normal
p2 = [1/10, 1/10, 1/10, 1/10, 1/10, 1/2]   # loaded

def roll(loaded):
    if loaded:
        print("a loaded die")
        p = p2
    else:
        print("a normal die")
        p = p1

    # roll the dice 10 times
    sequence = np.random.choice(6, size=10, p=p) + 1 
    for roll in sequence:
        print("rolled %d" % roll)
        
    return sequence

def bayes(sequence):
    odds = 1.0           # start with odds 1:1
    for roll in sequence:
        for i in range(len(p1)):
            r = p1[i]/p2[i]
        if r == 10/6:
            odds = 1.0*(10/6)**roll
        elif r == 1/3:
            odds = 1.0*(1/3)**roll
    if odds > 1:
        return True
    else:
        return False

sequence = roll(True)
if bayes(sequence):
    print("More likely loaded")
else:
    print("More likely normal")

The idea was to distinguish between the case of 0.1 and 0.5 probabilities for the loaded dice, but unfortunately the code doesn't properly work. Could you help me, please?


Solution

  • if r == 10/6:
        odds = 1.0*(10/6)**roll
    elif r == 1/3:
        odds = 1.0*(1/3)**roll
    

    Did you consider the possibility that neither of these is the case? Let's examine it directly:

    >>> ((1/6) / (1/10)) == 10/6
    False
    

    Huh. It turns out you can't expect floating-point numbers to do that.

    But there is no reason to perform this conditional check anyway, because you want to do fundamentally the same thing regardless of the value of r.

    Simply:

    odds = 1.0 * r**roll
    

    Separately, you don't need Numpy for this (check out random.choices). There's also a Fraction type provided in the standard library.