<jupyter_start><jupyter_text>Exploration of Collider Bias with discrete Bayes Nets using `pomegranate` Collider bias[Collider bias](https://en.wikipedia.org/wiki/Collider_(statistics) ) can be seen as a form of selection bias. In a causal network, if we have the structure `A -> Collider <- B`, then "conditioning on the collider opens the path between A and B [which can] introduce bias when estimating the causal association between A and B, potentially introducing associations where there are none." The `pomegranate` packageHere we use the Python package [pomegranate](https://pomegranate.readthedocs.io/en/latest/) (GitHub repo [here](https://github.com/jmschrei/pomegranate)). It allows us to specify a Bayesian Net structure, along with the conditional probability distributions. Amongst other things, we can  query the net, conditional upon certain observations.<jupyter_code>import pomegranate as pg<jupyter_output><empty_output><jupyter_text>Example 2: Does collider bias make it look like nicotine is protective of COVID![](img/bayes_net_1.png)Here we have a prior probability of 25% of being a smoker. **Independently**, there is a 10% prior probability of having Covid-19. The vector `[0.9, 0.1, 0.9, 0.01]` specifies the probability of being in hospital as a function of smoking and covid status:- smoking, covid. High probability of being in hospital.- smoking, ¬covid. Moderate probability of being in hospital- ¬smoking, covid. High probability of being in hospital- ¬smoking, ¬covid. Low probability of being in hospitalOne of the key points here is that of people who do not have covid, smokers are expected to have a higher probability of being in hospital than non-smokers.<jupyter_code>smokeD = pg.DiscreteDistribution({'yes': 0.25, 'no': 0.75})
covidD = pg.DiscreteDistribution({'yes': 0.1, 'no': 0.9})
hospitalD = pg.ConditionalProbabilityTable(
    [['yes', 'yes', 'yes', 0.9], ['yes', 'yes', 'no', 0.1],
     ['yes', 'no', 'yes', 0.1], ['yes', 'no', 'no', 0.9],
     ['no', 'yes', 'yes', 0.9], ['no', 'yes', 'no', 0.1],
     ['no', 'no', 'yes', 0.01], ['no', 'no', 'no', 0.99]],
    [smokeD, covidD])

smoke = pg.Node(smokeD, name="smokeD")
covid = pg.Node(covidD, name="covidD")
hospital = pg.Node(hospitalD, name="hospitalD")

model = pg.BayesianNetwork("Covid Collider")
model.add_states(smoke, covid, hospital)
model.add_edge(smoke, hospital)
model.add_edge(covid, hospital)
model.bake()<jupyter_output><empty_output><jupyter_text>Sanity checkProbability you have covid depending on if you are a smoker or non-smoker. These should be equal as our Bayes Net specifies that smoking and covid are independent.<jupyter_code>beliefs = model.predict_proba({'smokeD': 'yes'})
model.plot()
beliefs = map(str, beliefs)

print("\n".join("{}\t{}".format(state.name, belief) 
                for state, belief, in zip(model.states, beliefs) ))<jupyter_output>smokeD	yes
covidD	{
    "class" :"Distribution",
    "dtype" :"str",
    "name" :"DiscreteDistribution",
    "parameters" :[
        {
            "yes" :0.10000000000000035,
            "no" :0.8999999999999996
        }
    ],
    "frozen" :false
}
hospitalD	{
    "class" :"Distribution",
    "dtype" :"str",
    "name" :"DiscreteDistribution",
    "parameters" :[
        {
            "no" :0.8199999999999997,
            "yes" :0.18000000000000022
        }
    ],
    "frozen" :false
}<jupyter_text>Calculate P(covid|smoking, hospital) and P(covid|¬smoking, hospital)If you condition upon being in hospital (ie only observer people who are in hospital), then it might be that we see different probabilities of having covid based on whether you smoke or not.<jupyter_code>model.predict_proba({'smokeD': 'yes', 'hospitalD': 'yes'})
model.predict_proba({'smokeD': 'no', 'hospitalD': 'yes'})<jupyter_output><empty_output>
StarcoderdataJupyterStructuredCleanDedup