The following is part of a on-going collection of Jupyter notebooks. The goal being to have a library of notebooks as an introduction to Mathematics and technology. These were all created by Gavin Waters. If you use these notebooks, be nice and throw up a credit somewhere on your page.
import numpy as np
from scipy import stats
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
%matplotlib inline
Imagine you have a dice with 3 sides, you know the dice is fair but you would like to figure out what is the probability space of the outcome. One way to do it, is just by assigining each of sides 33% and call it a day.
Another way to do this is by rolling the dice for a number of times and finding the culmative proabilities for each side.
dice = {1:0,2:0,3:0}
for count in range(10):
roll = np.random.randint(1,4)
dice.update({roll:dice[roll]+1})
print(roll)
dice
1 2 2 1 2 1 3 2 3 3
{1: 3, 2: 4, 3: 3}
As you can see from above the probabilities are definately not at 33%
In fact the probabilities are..
for R in dice.keys():
print('The probability of rolling a ', R, ' is ',dice[R]/10)
The probability of rolling a 1 is 0.3 The probability of rolling a 2 is 0.4 The probability of rolling a 3 is 0.3
Another way to look at this by keeping track of the rolling probabilities.
dice = {1:0,2:0,3:0}
for count in range(10):
roll = np.random.randint(1,4)
dice.update({roll:dice[roll]+1})
print(roll)
for R in dice.keys():
print('The probability of rolling a ', R, ' is ',dice[R]/(count+1))
1 The probability of rolling a 1 is 1.0 The probability of rolling a 2 is 0.0 The probability of rolling a 3 is 0.0 3 The probability of rolling a 1 is 0.5 The probability of rolling a 2 is 0.0 The probability of rolling a 3 is 0.5 1 The probability of rolling a 1 is 0.6666666666666666 The probability of rolling a 2 is 0.0 The probability of rolling a 3 is 0.3333333333333333 3 The probability of rolling a 1 is 0.5 The probability of rolling a 2 is 0.0 The probability of rolling a 3 is 0.5 2 The probability of rolling a 1 is 0.4 The probability of rolling a 2 is 0.2 The probability of rolling a 3 is 0.4 1 The probability of rolling a 1 is 0.5 The probability of rolling a 2 is 0.16666666666666666 The probability of rolling a 3 is 0.3333333333333333 1 The probability of rolling a 1 is 0.5714285714285714 The probability of rolling a 2 is 0.14285714285714285 The probability of rolling a 3 is 0.2857142857142857 2 The probability of rolling a 1 is 0.5 The probability of rolling a 2 is 0.25 The probability of rolling a 3 is 0.25 2 The probability of rolling a 1 is 0.4444444444444444 The probability of rolling a 2 is 0.3333333333333333 The probability of rolling a 3 is 0.2222222222222222 2 The probability of rolling a 1 is 0.4 The probability of rolling a 2 is 0.4 The probability of rolling a 3 is 0.2
This would get very clumbersome, but looking at a graph would seem to be a better option.
x1 = np.array([])
x2 = np.array([])
x3 = np.array([])
dice = {1:0,2:0,3:0}
for count in range(0,10):
roll = np.random.randint(1,4)
dice.update({roll:dice[roll]+1})
x1=np.append(x1,dice[1]/(count+1))
x2=np.append(x2,dice[2]/(count+1))
x3=np.append(x3,dice[3]/(count+1))
plt.plot(x1,'.-',color='b',label='1')
plt.plot(x2,'.-',color='g',label='2')
plt.plot(x3,'.-',color='r',label='3')
plt.xlabel('# dice rolls')
plt.ylabel('culmative probaility')
plt.legend()
print("Final count",dice)
Final count {1: 4, 2: 2, 3: 4}
Notice that for each roll of the dice, the probability will always equal one. Now, the probability will eventually go to 0.33, or at least it should, given that our random generator is uniform. If we allow the simulator to run for 10,000 rolls of the dice, we can see that the proabailities converge.
x1 = np.array([])
x2 = np.array([])
x3 = np.array([])
x4 = np.array([])
dice = {1:0,2:0,3:0}
for count in range(0,10000):
roll = np.random.randint(1,4)
dice.update({roll:dice[roll]+1})
x1=np.append(x1,dice[1]/(count+1))
x2=np.append(x2,dice[2]/(count+1))
x3=np.append(x3,dice[3]/(count+1))
plt.plot(x1,'.-',color='b',label='1')
plt.plot(x2,'.-',color='g',label='2')
plt.plot(x3,'.-',color='r',label='3')
plt.xlabel('# dice rolls')
plt.ylabel('culmative probaility')
plt.legend()
print("Final count",dice)
plt.show()
print("The final probability for rolling a 1 is ", x1[-1])
print("The final probability for rolling a 2 is ", x2[-1])
print("The final probability for rolling a 3 is ", x3[-1])
Final count {1: 3252, 2: 3350, 3: 3398}
The final probability for rolling a 1 is 0.3252 The final probability for rolling a 2 is 0.335 The final probability for rolling a 3 is 0.3398
As you can see, if given enough time, you can get a fairly accurate proability. Here is the problem, what if this was a trial of some kind. 10,000 trials would be nice but expensive, also this is a very discrete answer with only 3 outcomes. What if our choices were on a continuous spectrum?
I am just going to introduce you to the methodology about this, the theory is for another notebook.
The question I have is, "Can we generate a continous probability space given some discrete data points we have collected."
Markov Chain Monte Carlo methods is a process that we can set loose random sample walks and determine probability spaces from it. First we will consider the fair dice method, then we shall use the finite data collection example.
First let us assume that there is an equal 33% chance of obtaining any number. Let $P(x_1)$ be the probability of rolling a $1$. The main idea of MCMC is to randomly choose another point in the probability space and then weight the decision on wether to move there or not. When you have the weight, randomly choose whether you move or not, based upon that weight, and then repeat.
So for our example, we first choose a starting probabilty point in our proability space. Since we only have 3 dimensions and they all have to add up to one, I can simply represent this probability space in a 2-D space. So the x-axis will represent $P(x_1)$ and the y-axis will be the $P(x_2)$. We know that $P(x_3)=1-P(x_1)-P(x_2)$
First our starting point,
p1,p2 = 0.1,0.6
Since we are walking about our two dimensional proability space, we need to able to choose a random $x_1$ and $x_2$ measurement. Lets make it normal with mean of zero and standard deviation of 0.2.
p1walk = np.random.normal(0,0.2,1)[0]
p2walk = np.random.normal(0,0.2,1)[0]
Now we always have to check to see wether or not the jump will place us ourside of our probability space.
if p1+p1walk in range(0,1) and p2+p2walk in range(0,1) and 1-p1-p1walk-p2-p2walk in range(0,1):
p1jump, p2jump = p1+p1walk, p2+p2walk
else:
p1jump,p2jump=p1,p2
Now, what we need is to place a weight on whether or not we should jump. Usually this would be "Given our data, is it more probable that the place we are going to go to is more likely than not"
If it is, then lets find the probability that that happens and roll a random number to see it we move.
If not, lets stay where we are and not move.
The trinomial joint probability mass function is the following $$f(x_1,x_2)=P(X=x_1,Y=x_2)=\dfrac{n!}{x_1!x_2!(n-x_1-x_2)!} p^{x_1}_1 p^{x_2}_2 (1-p_1-p_2)^{n-x_1-x_2}$$
Where there is n experiments, with $x_1$ outcomes with associated $p_1$ probability
Because this is uniform, we can just assume $n= x_1+x_2+x_3$ trials with $x_1=x_2=1-x_1-x_2$ outcomes.
This helps because then our probability to move reduces quite a bit.
$$ P = \left(\dfrac{p_1p_2(1-p_1-p_2)}{p^*_1p^*_2(1-p^*_1-p^*_2)}\right)^{x_1}$$For our example lets say that there was 100 trails with $x_1=33$
prob_move = ((p1*p2*(1-p1-p2))/(p1jump*p2jump*(1-p1jump-p2jump)))**33
Now we have to put it all together and record the path
p1=0.71
p2=0.1
MCMCp1=[p1]
MCMCp2=[p2]
MCMCp3=[1-p1-p2]
while len(MCMCp1)<10:
p1walk = np.random.normal(0,0.15,1)[0]
p2walk = np.random.normal(0,0.15,1)[0]
if p1+p1walk>0 and p1+p1walk<1 and p2+p2walk>0 and p2+p2walk<1 and 1-p1-p1walk-p2-p2walk>0 and 1-p1-p1walk-p2-p2walk<1:
p1jump, p2jump = p1+p1walk, p2+p2walk
else:
p1jump,p2jump=p1,p2
prob_move = ((p1jump*p2jump*(1-p1jump-p2jump))/(p1*p2*(1-p1-p2)))**33
MCMCp1.append(p1)
MCMCp2.append(p2)
MCMCp3.append(1-p1-p2)
if min(1,prob_move)>=np.random.random():
p1,p2=p1jump,p2jump
plt.plot(MCMCp1,range(0,len(MCMCp1)),'.-',c='b',alpha=0.51)
plt.xlabel('proability')
plt.ylabel('sample step')
plt.xlim(0,1)
(0, 1)
As you can see from above, the random walk started and then moved only if it was benificial to do so. This is only 10 steps, if we extend to 100 you should be able to see some convergengce
p1=0.71
p2=0.1
MCMCp1=[p1]
MCMCp2=[p2]
MCMCp3=[1-p1-p2]
while len(MCMCp1)<100:
p1walk = np.random.normal(0,0.15,1)[0]
p2walk = np.random.normal(0,0.15,1)[0]
if p1+p1walk>0 and p1+p1walk<1 and p2+p2walk>0 and p2+p2walk<1 and 1-p1-p1walk-p2-p2walk>0 and 1-p1-p1walk-p2-p2walk<1:
p1jump, p2jump = p1+p1walk, p2+p2walk
else:
p1jump,p2jump=p1,p2
prob_move = ((p1jump*p2jump*(1-p1jump-p2jump))/(p1*p2*(1-p1-p2)))**33
MCMCp1.append(p1)
MCMCp2.append(p2)
MCMCp3.append(1-p1-p2)
if min(1,prob_move)>=np.random.random():
p1,p2=p1jump,p2jump
plt.plot(MCMCp1,range(0,len(MCMCp1)),'.-',c='b',alpha=0.31)
plt.xlabel('proability')
plt.ylabel('sample step')
plt.xlim(0,1)
(0, 1)
The graph seems to be converging to our projected probability of 33%, lets run out to 1,000 samples and also show the other probabilities
p1=0.71
p2=0.1
MCMCp1=[p1]
MCMCp2=[p2]
MCMCp3=[1-p1-p2]
while len(MCMCp1)<1000:
p1walk = np.random.normal(0,0.15,1)[0]
p2walk = np.random.normal(0,0.15,1)[0]
if p1+p1walk>0 and p1+p1walk<1 and p2+p2walk>0 and p2+p2walk<1 and 1-p1-p1walk-p2-p2walk>0 and 1-p1-p1walk-p2-p2walk<1:
p1jump, p2jump = p1+p1walk, p2+p2walk
else:
p1jump,p2jump=p1,p2
prob_move = ((p1jump*p2jump*(1-p1jump-p2jump))/(p1*p2*(1-p1-p2)))**33
MCMCp1.append(p1)
MCMCp2.append(p2)
MCMCp3.append(1-p1-p2)
if min(1,prob_move)>=np.random.random():
p1,p2=p1jump,p2jump
plt.plot(MCMCp1,range(0,len(MCMCp1)),'.-',c='b',alpha=0.051)
plt.plot(MCMCp2,range(0,len(MCMCp1)),'.-',c='r',alpha=0.051)
plt.plot(MCMCp3,range(0,len(MCMCp1)),'.-',c='g',alpha=0.051)
plt.xlabel('proability')
plt.ylabel('sample step')
plt.xlim(0,1)
(0, 1)
While this is interesting that the samples may converge, there is a theorem out there that shows that this random sampling will converge to the sample distributions of 33% each. We can see this by plotting a KDE distribution plot of the solution of the samples for each axis
sns.distplot(MCMCp1)
sns.distplot(MCMCp2)
sns.distplot(MCMCp3)
print("The mean proability for a roll of 1 is : ",np.mean(MCMCp1))
print("The mean proability for a roll of 2 is : ",np.mean(MCMCp2))
print("The mean proability for a roll of 3 is : ",np.mean(MCMCp3))
The mean proability for a roll of 1 is : 0.345032153016 The mean proability for a roll of 2 is : 0.319687709448 The mean proability for a roll of 3 is : 0.335280137537
Lets look at the random walks in a 2-d probability space.
plt.plot(MCMCp1,MCMCp2,'.-' ,alpha=0.051)
plt.xlabel('Prob of rolling a 1')
plt.ylabel('Prob of rolling a 2')
plt.xlim(0,1)
plt.ylim(0,1)
(0, 1)
By bumping it up to 100,000 samples or higher, we get a normal distribution about our desired probability
p1=0.71
p2=0.1
MCMCp1=[p1]
MCMCp2=[p2]
MCMCp3=[1-p1-p2]
while len(MCMCp1)<100000:
p1walk = np.random.normal(0,0.15,1)[0]
p2walk = np.random.normal(0,0.15,1)[0]
if p1+p1walk>0 and p1+p1walk<1 and p2+p2walk>0 and p2+p2walk<1 and 1-p1-p1walk-p2-p2walk>0 and 1-p1-p1walk-p2-p2walk<1:
p1jump, p2jump = p1+p1walk, p2+p2walk
else:
p1jump,p2jump=p1,p2
prob_move = ((p1jump*p2jump*(1-p1jump-p2jump))/(p1*p2*(1-p1-p2)))**33
MCMCp1.append(p1)
MCMCp2.append(p2)
MCMCp3.append(1-p1-p2)
if min(1,prob_move)>=np.random.random():
p1,p2=p1jump,p2jump
plt.plot(MCMCp1,range(0,len(MCMCp1)),'.-',c='b',alpha=0.11)
plt.plot(MCMCp2,range(0,len(MCMCp1)),'.-',c='r',alpha=0.11)
plt.plot(MCMCp3,range(0,len(MCMCp1)),'.-',c='g',alpha=0.11)
plt.xlabel('proability')
plt.ylabel('sample step')
plt.xlim(0,1)
(0, 1)
sns.distplot(MCMCp1)
sns.distplot(MCMCp2)
sns.distplot(MCMCp3)
print("The mean proability for a roll of 1 is : ",np.mean(MCMCp1))
print("The mean proability for a roll of 2 is : ",np.mean(MCMCp2))
print("The mean proability for a roll of 3 is : ",np.mean(MCMCp3))
The mean proability for a roll of 1 is : 0.333502506998 The mean proability for a roll of 2 is : 0.332823825552 The mean proability for a roll of 3 is : 0.33367366745
plt.plot(MCMCp1,MCMCp2,'.-' ,alpha=0.051)
plt.xlabel('Prob of rolling a 1')
plt.ylabel('Prob of rolling a 2')
plt.xlim(0,1)
plt.ylim(0,1)
(0, 1)
It also does not matter where we start in our probability space, eventually the sample will converge.
p1=np.random.random()
p2=(1-p1)*np.random.random()
first_start = (p1,p2,1-p1-p2)
MCMCp1=[p1]
MCMCp2=[p2]
MCMCp3=[1-p1-p2]
while len(MCMCp1)<10000:
p1walk = np.random.normal(0,0.15,1)[0]
p2walk = np.random.normal(0,0.15,1)[0]
if p1+p1walk>0 and p1+p1walk<1 and p2+p2walk>0 and p2+p2walk<1 and 1-p1-p1walk-p2-p2walk>0 and 1-p1-p1walk-p2-p2walk<1:
p1jump, p2jump = p1+p1walk, p2+p2walk
else:
p1jump,p2jump=p1,p2
prob_move = ((p1jump*p2jump*(1-p1jump-p2jump))/(p1*p2*(1-p1-p2)))**33
MCMCp1.append(p1)
MCMCp2.append(p2)
MCMCp3.append(1-p1-p2)
if min(1,prob_move)>=np.random.random():
p1,p2=p1jump,p2jump
first_mean = (np.mean(MCMCp1),np.mean(MCMCp2),np.mean(MCMCp3))
p1=np.random.random()
p2=(1-p1)*np.random.random()
second_start = (p1,p2,1-p1-p2)
MCMCp1=[p1]
MCMCp2=[p2]
MCMCp3=[1-p1-p2]
while len(MCMCp1)<10000:
p1walk = np.random.normal(0,0.15,1)[0]
p2walk = np.random.normal(0,0.15,1)[0]
if p1+p1walk>0 and p1+p1walk<1 and p2+p2walk>0 and p2+p2walk<1 and 1-p1-p1walk-p2-p2walk>0 and 1-p1-p1walk-p2-p2walk<1:
p1jump, p2jump = p1+p1walk, p2+p2walk
else:
p1jump,p2jump=p1,p2
prob_move = ((p1jump*p2jump*(1-p1jump-p2jump))/(p1*p2*(1-p1-p2)))**33
MCMCp1.append(p1)
MCMCp2.append(p2)
MCMCp3.append(1-p1-p2)
if min(1,prob_move)>=np.random.random():
p1,p2=p1jump,p2jump
second_mean = (np.mean(MCMCp1),np.mean(MCMCp2),np.mean(MCMCp3))
print("Starting at: ",first_start, ' will obtain a mean of:', first_mean)
print("Starting at: ",second_start, ' will obtain a mean of: ', second_mean)
Starting at: (0.4250742886722887, 0.20376721681336835, 0.37115849451434296) will obtain a mean of: (0.33466056383847093, 0.33413180454468672, 0.33120763161684247) Starting at: (0.397920712931619, 0.4964567692452362, 0.1056225178231448) will obtain a mean of: (0.33371930330573513, 0.33288224706969183, 0.33339844962457299)
Consider that you rolled a 3-d 30 times and came up with the following data:
dice = {1:0,2:0,3:0}
for count in range(30):
roll = np.random.randint(1,4)
dice.update({roll:dice[roll]+1})
dice
{1: 9, 2: 11, 3: 10}
From first impressions, we can see that the proabilities are not equally uniform(hopefully)
We can change our previous code to take in this data and generate probability distributions using MCMC samples. it should not really matter where our chain starts.
p1=0.71
p2=0.1
MCMCp1=[p1]
MCMCp2=[p2]
MCMCp3=[1-p1-p2]
while len(MCMCp1)<10000:
p1walk = np.random.normal(0,0.105,1)[0]
p2walk = np.random.normal(0,0.105,1)[0]
if p1+p1walk>0 and p1+p1walk<1 and p2+p2walk>0 and p2+p2walk<1 and 1-p1-p1walk-p2-p2walk>0 and 1-p1-p1walk-p2-p2walk<1:
p1jump, p2jump = p1+p1walk, p2+p2walk
else:
p1jump,p2jump=p1,p2
prob_move = ((p1jump**dice[1]*p2jump**dice[2]*(1-p1jump-p2jump)**dice[3])/(p1**dice[1]*p2**dice[2]*(1-p1-p2)**dice[3]))
MCMCp1.append(p1)
MCMCp2.append(p2)
MCMCp3.append(1-p1-p2)
if min(1,prob_move)>=np.random.random():
p1,p2=p1jump,p2jump
plt.plot(MCMCp1,range(0,len(MCMCp1)),'.-',c='b',alpha=0.11)
plt.plot(MCMCp2,range(0,len(MCMCp1)),'.-',c='r',alpha=0.11)
plt.plot(MCMCp3,range(0,len(MCMCp1)),'.-',c='g',alpha=0.11)
plt.xlabel('proability')
plt.ylabel('sample step')
plt.xlim(0,1)
(0, 1)
sns.distplot(MCMCp1)
sns.distplot(MCMCp2)
sns.distplot(MCMCp3)
print("The mean proability for a roll of 1 is : ",np.mean(MCMCp1))
print("The mean proability for a roll of 2 is : ",np.mean(MCMCp2))
print("The mean proability for a roll of 3 is : ",np.mean(MCMCp3))
The mean proability for a roll of 1 is : 0.301482542217 The mean proability for a roll of 2 is : 0.3647429778 The mean proability for a roll of 3 is : 0.333774479983
plt.plot(MCMCp1,MCMCp2,'.-' ,alpha=0.11)
plt.xlabel('Prob of rolling a 1')
plt.ylabel('Prob of rolling a 2')
plt.xlim(0,1)
plt.ylim(0,1)
(0, 1)
Putting all this code in one cell.
dice = {1:0,2:0,3:0}
dicerolls=30
for count in range(dicerolls):
roll = np.random.randint(1,4)
dice.update({roll:dice[roll]+1})
print(dice)
p1=0.71
p2=0.1
MCMCp1=[p1]
MCMCp2=[p2]
MCMCp3=[1-p1-p2]
while len(MCMCp1)<10000:
p1walk = np.random.normal(0,0.105,1)[0]
p2walk = np.random.normal(0,0.105,1)[0]
if p1+p1walk>0 and p1+p1walk<1 and p2+p2walk>0 and p2+p2walk<1 and 1-p1-p1walk-p2-p2walk>0 and 1-p1-p1walk-p2-p2walk<1:
p1jump, p2jump = p1+p1walk, p2+p2walk
else:
p1jump,p2jump=p1,p2
prob_move = ((p1jump**dice[1]*p2jump**dice[2]*(1-p1jump-p2jump)**dice[3])/(p1**dice[1]*p2**dice[2]*(1-p1-p2)**dice[3]))
MCMCp1.append(p1)
MCMCp2.append(p2)
MCMCp3.append(1-p1-p2)
if min(1,prob_move)>=np.random.random():
p1,p2=p1jump,p2jump
plt.plot(MCMCp1,range(0,len(MCMCp1)),'.-',c='b',alpha=0.11)
plt.plot(MCMCp2,range(0,len(MCMCp1)),'.-',c='r',alpha=0.11)
plt.plot(MCMCp3,range(0,len(MCMCp1)),'.-',c='g',alpha=0.11)
plt.xlim(0,1)
plt.xlabel('proability')
plt.ylabel('sample step')
plt.show()
sns.distplot(MCMCp1)
sns.distplot(MCMCp2)
sns.distplot(MCMCp3)
print("The mean proability for a roll of 1 is : ",np.mean(MCMCp1))
print("The mean proability for a roll of 2 is : ",np.mean(MCMCp2))
print("The mean proability for a roll of 3 is : ",np.mean(MCMCp3))
plt.show()
plt.plot(MCMCp1,MCMCp2,'.-' ,alpha=0.11)
plt.xlim(0,1)
plt.ylim(0,1)
plt.xlabel('Prob of rolling a 1')
plt.ylabel('Prob of rolling a 2')
plt.show()
{1: 9, 2: 8, 3: 13}
The mean proability for a roll of 1 is : 0.304464138469 The mean proability for a roll of 2 is : 0.273592700287 The mean proability for a roll of 3 is : 0.421943161245
You should notice that the standard deviation of these probability distributions are quite high.
print('The standard deviation of the probability distribution of rolling a "1" is:', np.std(MCMCp1))
The standard deviation of the probability distribution of rolling a "1" is: 0.082326772896
This is primarily because there is not enough data points to have much convergence on our samples. We are only looking at 30 trials.
If we use the same proportions but increase the trials we should get faster convergence of our samples and thus smaller standard deviation of our probability distributions.
factor = 10
dice.update({1:dice[1]*factor})
dice.update({2:dice[2]*factor})
dice.update({3:dice[3]*factor})
print(dice)
p1=0.71
p2=0.1
MCMCp1=[p1]
MCMCp2=[p2]
MCMCp3=[1-p1-p2]
while len(MCMCp1)<10000:
p1walk = np.random.normal(0,0.105,1)[0]
p2walk = np.random.normal(0,0.105,1)[0]
if p1+p1walk>0 and p1+p1walk<1 and p2+p2walk>0 and p2+p2walk<1 and 1-p1-p1walk-p2-p2walk>0 and 1-p1-p1walk-p2-p2walk<1:
p1jump, p2jump = p1+p1walk, p2+p2walk
else:
p1jump,p2jump=p1,p2
prob_move = ((p1jump**dice[1]*p2jump**dice[2]*(1-p1jump-p2jump)**dice[3])/(p1**dice[1]*p2**dice[2]*(1-p1-p2)**dice[3]))
MCMCp1.append(p1)
MCMCp2.append(p2)
MCMCp3.append(1-p1-p2)
if min(1,prob_move)>=np.random.random():
p1,p2=p1jump,p2jump
plt.plot(MCMCp1,range(0,len(MCMCp1)),'.-',c='b',alpha=0.11)
plt.plot(MCMCp2,range(0,len(MCMCp1)),'.-',c='r',alpha=0.11)
plt.plot(MCMCp3,range(0,len(MCMCp1)),'.-',c='g',alpha=0.11)
plt.xlim(0,1)
plt.xlabel('proability')
plt.ylabel('sample step')
plt.show()
sns.distplot(MCMCp1)
sns.distplot(MCMCp2)
sns.distplot(MCMCp3)
print("The mean proability for a roll of 1 is : ",np.mean(MCMCp1))
print("The mean proability for a roll of 2 is : ",np.mean(MCMCp2))
print("The mean proability for a roll of 3 is : ",np.mean(MCMCp3))
plt.show()
plt.plot(MCMCp1,MCMCp2,'.-' ,alpha=0.11)
plt.xlim(0,1)
plt.ylim(0,1)
plt.xlabel('Prob of rolling a 1')
plt.ylabel('Prob of rolling a 2')
plt.show()
print('The standard deviation of the probability distribution of rolling a "1" is:', np.std(MCMCp1))
{1: 90, 2: 80, 3: 130}
The mean proability for a roll of 1 is : 0.301861921185 The mean proability for a roll of 2 is : 0.267647469486 The mean proability for a roll of 3 is : 0.430490609329
The standard deviation of the probability distribution of rolling a "1" is: 0.0293988365767