Skip to content

Instantly share code, notes, and snippets.

@saulshanabrook
Created November 25, 2015 02:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save saulshanabrook/ef7583280530cfd4b513 to your computer and use it in GitHub Desktop.
Save saulshanabrook/ef7583280530cfd4b513 to your computer and use it in GitHub Desktop.
{-|
> ```
Consider a simple model for whether a person has the flu or not. Let F=1
indicate that a person has the flu and F=0 indicate that they don't have the
flu. Let C=1 indicate that the person has a cough and C=0 indicate that they
don't have a cough. Let M=1 indicate that the person has muscle pain and M=0
indicate that they don't have muscle pain. Assume that C and M are conditionally
independent given F so that the probability model is
P(C=c,M=m,F=f)=P(C=c|F=f)P(M=m|F=f)P(F=f).
Suppose that we ask two different doctors to supply probabilities for this model
and we obtain the following results:
Doctor 1:
P(F=1)=0.4
P(C=1|F=0)=0.2, P(C=1|F=1)=0.8
P(M=1|F=0)=0.3, P(M=1|F=1)=0.9
Doctor 2:
P(F=1)=0.5
P(C=1|F=0)=0.1, P(C=1|F=1)=0.7
P(M=1|F=0)=0.2, P(M=1|F=1)=0.8
Suppose we also have access to 10 patient records recording both the symptoms
and whether each patient was diagnosed with flu or not as shown below:
Patient C M F
1 1 0 0
2 1 1 1
3 1 1 1
4 0 1 0
5 0 1 1
6 1 0 1
7 0 0 0
8 1 0 0
9 0 0 0
10 1 1 1
```
-}
import Html exposing (text)
{-| There are three different types of events that can happen
-}
type EventType = C | M | F
{-| An event is a fact about what happened with a certain patient.
-}
type Event a = Event EventType a
{-| A patient is a a combination of three events: C, M, and F
We represent it as a List, instead of a record, so that we have the
types C M and F represent event types throughout.
-}
type alias Patient = List (Event Int)
{-| Checks if an event happened for a patient.
-}
event_happened : Patient -> Event Int -> Bool
event_happened patient event =
List.member event patient
{-| A known probability
A marginal probability
P(C=True) = 0.8
can be written as
MarginalProb (C True) 0.8
A Conditional probability
P(C=True|A=False) = 0.5
can be written as
ConditionalProb (C True) (A False) 0.5
-}
type EventProb a
= MarginalProb (Event a) Float
| ConditionalProb (Event a) (Event a) Float
{-|
A combination of statements about the world.
P(C=c|F=f)P(M=m|F=f)P(F=f)
-}
type alias Model a = List (EventProb a)
type alias Doctor = Model Int
{-|
Given some known probabilities about the world,
return the probability of each of the patients, assuming they are independent
-}
likelihood_patients : Doctor -> List Patient -> Float
likelihood_patients m ps =
ps
|> List.map (likelihood_patient m)
|> List.product
{-|
Given some known probabilities about the world,
return the probability of the patient.
-}
likelihood_patient : Doctor -> Patient -> Float
likelihood_patient model patient =
let
happened = event_happened patient
event_prob event prob = if (happened event) then prob else 1 - prob
in
Debug.log ("patient: " ++ (toString patient))
model
|> Debug.log "model: "
-- remove all conditional events where the condition isnt true
|> List.filter
(\ep -> case ep of
MarginalProb _ _ -> True
ConditionalProb _ given _ -> happened given
)
|> Debug.log "filtered: "
-- give the probability of the event, if it happened
-- and 1 - probability if it didnt happen
|> List.map
(\ep -> case ep of
MarginalProb event prob -> event_prob event prob
ConditionalProb event _ prob -> event_prob event prob
)
|> Debug.log "mapped: "
|> List.product
main : Html.Html
main =
let
doctor1 : Doctor
doctor1 =
[ MarginalProb (Event F 1) 0.4
, ConditionalProb (Event C 1) (Event F 0) 0.2
, ConditionalProb (Event C 1) (Event F 1) 0.8
, ConditionalProb (Event M 1) (Event F 0) 0.3
, ConditionalProb (Event M 1) (Event F 1) 0.9
]
patients : List Patient
patients =
[ [1, 0, 0]
, [1, 1, 1]
, [1, 1, 1]
, [0, 1, 0]
, [0, 1, 1]
, [1, 0, 1]
, [0, 0, 0]
, [1, 0, 0]
, [0, 0, 0]
, [1, 1, 1]
]
|> List.map
(\l -> case l of
c :: m :: f :: [] ->
[ Event C c
, Event M m
, Event F f
]
_ ->
Debug.crash ""
)
prob_patients_doctor1 = likelihood_patients doctor1 patients
doctor2 : Doctor
doctor2 =
[ MarginalProb (Event F 1) 0.5
, ConditionalProb (Event C 1) (Event F 0) 0.1
, ConditionalProb (Event C 1) (Event F 1) 0.7
, ConditionalProb (Event M 1) (Event F 0) 0.2
, ConditionalProb (Event M 1) (Event F 1) 0.8
]
prob_patients_doctor2 = likelihood_patients doctor2 patients
doctorTest =
[ MarginalProb (Event F 1) 1
, ConditionalProb (Event C 1) (Event F 0) 1
, ConditionalProb (Event C 1) (Event F 1) 1
, ConditionalProb (Event M 1) (Event F 0) 1
, ConditionalProb (Event M 1) (Event F 1) 1
]
test_prob = likelihood_patients doctorTest [[Event C 1, Event M 1, Event F 1]]
test_prob_2 = likelihood_patients doctorTest [[Event C 0, Event M 0, Event F 0]]
in
text
( "doctor1: "
++ (toString prob_patients_doctor1)
++ " doctor2: "
++ (toString prob_patients_doctor2)
--++ "test1: " ++ (toString test_prob)
--++ "test2: " ++ (toString test_prob_2)
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment