{ "cells": [ { "cell_type": "code", "execution_count": 27, "metadata": {}, "outputs": [], "source": [ "# This tutorial on using Bayesian network to solve the Monty Hall problem is originally from the following link:\n", "# https://www.edureka.co/blog/bayesian-networks/\n", "#\n", "# Addiitonal comments in the notebook added by Yuanpeng Zhang @ Wed 18-Dec-19.\n", "#\n", "\n", "# Import required packages\n", "import math\n", "# The following module can be installed with conda 'conda install pomegranate'.\n", "from pomegranate import *\n", " \n", "# Initially the door selected by the guest is completely random\n", "guest =DiscreteDistribution( { 'A': 1./3, 'B': 1./3, 'C': 1./3 } )\n", " \n", "# The door containing the prize is also a random process\n", "prize =DiscreteDistribution( { 'A': 1./3, 'B': 1./3, 'C': 1./3 } )\n", " \n", "# The door Monty picks, depends on the choice of the guest and the prize door\n", "monty =ConditionalProbabilityTable(\n", "[[ 'A', 'A', 'A', 0.0 ],\n", "[ 'A', 'A', 'B', 0.5 ],\n", "[ 'A', 'A', 'C', 0.5 ],\n", "[ 'A', 'B', 'A', 0.0 ],\n", "[ 'A', 'B', 'B', 0.0 ],\n", "[ 'A', 'B', 'C', 1.0 ],\n", "[ 'A', 'C', 'A', 0.0 ],\n", "[ 'A', 'C', 'B', 1.0 ],\n", "[ 'A', 'C', 'C', 0.0 ],\n", "[ 'B', 'A', 'A', 0.0 ],\n", "[ 'B', 'A', 'B', 0.0 ],\n", "[ 'B', 'A', 'C', 1.0 ],\n", "[ 'B', 'B', 'A', 0.5 ],\n", "[ 'B', 'B', 'B', 0.0 ],\n", "[ 'B', 'B', 'C', 0.5 ],\n", "[ 'B', 'C', 'A', 1.0 ],\n", "[ 'B', 'C', 'B', 0.0 ],\n", "[ 'B', 'C', 'C', 0.0 ],\n", "[ 'C', 'A', 'A', 0.0 ],\n", "[ 'C', 'A', 'B', 1.0 ],\n", "[ 'C', 'A', 'C', 0.0 ],\n", "[ 'C', 'B', 'A', 1.0 ],\n", "[ 'C', 'B', 'B', 0.0 ],\n", "[ 'C', 'B', 'C', 0.0 ],\n", "[ 'C', 'C', 'A', 0.5 ],\n", "[ 'C', 'C', 'B', 0.5 ],\n", "[ 'C', 'C', 'C', 0.0 ]], [guest, prize] )\n", " \n", "d1 = State( guest, name=\"guest\" )\n", "d2 = State( prize, name=\"prize\" )\n", "d3 = State( monty, name=\"monty\" )\n", " \n", "#Building the Bayesian Network\n", "network = BayesianNetwork( \"Solving the Monty Hall Problem With Bayesian Networks\" )\n", "network.add_states(d1, d2, d3)\n", "network.add_edge(d1, d3)\n", "network.add_edge(d2, d3)\n", "network.bake()" ] }, { "cell_type": "code", "execution_count": 23, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "guest\tA\n", "prize\t{\n", " \"class\" :\"Distribution\",\n", " \"dtype\" :\"str\",\n", " \"name\" :\"DiscreteDistribution\",\n", " \"parameters\" :[\n", " {\n", " \"A\" :0.3333333333333333,\n", " \"B\" :0.3333333333333333,\n", " \"C\" :0.3333333333333333\n", " }\n", " ],\n", " \"frozen\" :false\n", "}\n", "monty\t{\n", " \"class\" :\"Distribution\",\n", " \"dtype\" :\"str\",\n", " \"name\" :\"DiscreteDistribution\",\n", " \"parameters\" :[\n", " {\n", " \"B\" :0.49999999999999983,\n", " \"A\" :0.0,\n", " \"C\" :0.49999999999999983\n", " }\n", " ],\n", " \"frozen\" :false\n", "}\n" ] } ], "source": [ "# Given the guest selecting door 'A', we update the probability of the network.\n", "beliefs = network.predict_proba({ 'guest' : 'A' }) # The returned value 'beliefs' here is a list.\n", "beliefs = map(str, beliefs) # Map the 'beliefs' list to 'str' function for printing purpose next.\n", "print(\"\\n\".join( \"{}\\t{}\".format( state.name, belief ) for state, belief in zip(network.states, beliefs)))" ] }, { "cell_type": "code", "execution_count": 26, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "guest\tA\n", "prize\t{\n", " \"class\" :\"Distribution\",\n", " \"dtype\" :\"str\",\n", " \"name\" :\"DiscreteDistribution\",\n", " \"parameters\" :[\n", " {\n", " \"A\" :0.3333333333333334,\n", " \"B\" :0.0,\n", " \"C\" :0.6666666666666664\n", " }\n", " ],\n", " \"frozen\" :false\n", "}\n", "monty\tB\n" ] } ], "source": [ "# In previous situation, the guest selects door 'A' but monty hasn't selected the door yet. From the result above, \n", "# we know that the distribution of prize among the doors will not be influenced by the guest's choice, but the selection\n", "# of monty will. In this case, we go a bit further by specifying that monty also makes his/her choice to open the door 'B'.\n", "# In this case, the distribution of prize will for sure change, accordingly.\n", "beliefs = network.predict_proba({'guest' : 'A', 'monty' : 'B'})\n", "print(\"\\n\".join( \"{}\\t{}\".format( state.name, str(belief) ) for state, belief in zip( network.states, beliefs )))" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.3" } }, "nbformat": 4, "nbformat_minor": 2 }