import matplotlib.pyplot as plt
import networkx as nx
from pgmpy.factors.discrete import TabularCPD
from pgmpy.inference import CausalInference
from pgmpy.models import BayesianNetwork

%load_ext lab_black

5. Manufacturing Bayes*#

From Unit 3 - manufacturingbayes.odc.

Associated lecture videos: Unit 3 lessons 3 and 5.


Three types of machines produce items. The first type makes 30% of the items, the second 50%, and the third 20%. The probability of an item conforming to standards is 0.94 if it comes from a type-1 machine, 0.95 from a type-2 machine, and 0.97 from a type-3 machine.

An item from the production is selected at random.

  1. What is the probability that it was conforming?

  2. If it was found that the item is conforming, what is the probability that it was produced on a type-1 machine?

The code below uses pgmpy. Jacob Harris, a student in the Fall 2021 class, also managed to get this working in PyMC3.

# Defining network structure
mb_model = BayesianNetwork([("Machine", "Conforming")])

# Defining the parameters
cpd_machine = TabularCPD(
    variable="Machine", variable_card=3, values=[[0.3], [0.5], [0.2]]
)

cpd_conforming = TabularCPD(
    variable="Conforming",
    variable_card=2,
    values=[[0.06, 0.05, 0.03], [0.94, 0.95, 0.97]],
    evidence=["Machine"],
    evidence_card=[3],
)

# Associating the parameters with the model structure
mb_model.add_cpds(cpd_machine, cpd_conforming)

mb_model.check_model()

print(f"Nodes: {mb_model.nodes()}")
print(f"Edges: {mb_model.edges()}")
Nodes: ['Machine', 'Conforming']
Edges: [('Machine', 'Conforming')]
options = {
    "arrowsize": 40,
    "font_size": 8,
    "font_weight": "bold",
    "node_size": 4000,
    "node_color": "white",
    "edgecolors": "black",
    "linewidths": 2,
    "width": 5,
    "alpha": 0.9,
}

# plot the network
nx.draw_circular(mb_model, with_labels=True, **options)

# Set margins for the axes so that nodes aren't clipped
ax = plt.gca()
ax.margins(0.20)
plt.axis("off")
plt.show()
../_images/4ae99f33bef687740d25fed34d8aadbb1d47323c64aab473da80dd238be99c91.png

Make sure the above visualization makes sense!

See Networkx docs for more details on plotting.

mb_infer = CausalInference(mb_model)

# probability a random item is conforming
q = mb_infer.query(variables=["Conforming"])
print("P(C):")
print(q)

# probability a conforming item came from the different machine types
q = mb_infer.query(variables=["Machine"], evidence={"Conforming": True})
print("P(M|C) (0-indexed, so Machine 1 is listed as Machine(0) and so on):")
print(q)
P(C):
+---------------+-------------------+
| Conforming    |   phi(Conforming) |
+===============+===================+
| Conforming(0) |            0.0490 |
+---------------+-------------------+
| Conforming(1) |            0.9510 |
+---------------+-------------------+
P(M|C) (0-indexed, so Machine 1 is listed as Machine(0) and so on):
+------------+----------------+
| Machine    |   phi(Machine) |
+============+================+
| Machine(0) |         0.2965 |
+------------+----------------+
| Machine(1) |         0.4995 |
+------------+----------------+
| Machine(2) |         0.2040 |
+------------+----------------+

Note that this doesn’t exactly match the BUGS results in U3L5, because BUGS is sampling from random variables rather than performing exact calculations.

%load_ext watermark
%watermark -n -u -v -iv -p pgmpy
Last updated: Sat Mar 18 2023

Python implementation: CPython
Python version       : 3.8.16
IPython version      : 8.11.0

pgmpy: 0.1.21

matplotlib: 3.7.0
networkx  : 3.0