The joint probability\(\mathbb{P}(A, B)\) of two events \(A \in \mathcal{F}\) and \(B \in \mathcal{F}\) is defined as the probability of the intersection of those two events \(\mathbb{P}(A, B) = \mathbb{P}(A \cap B)\), which must be defined give that \(\mathcal{F}\) is closed under countable intersection.
Define FiniteMeasurableSpace
from typing import Iterablefrom itertools import chain, combinationsfrom functools importreduceSampleSpace =frozenset[str]Event =frozenset[str]SigmaAlgebra =frozenset[Event]def powerset(iterable: Iterable) -> Iterable:"""The power set of a set See https://docs.python.org/3/library/itertools.html#itertools-recipes Parameters ---------- iterable The set to take the power set of """ s =list(iterable)return chain.from_iterable(combinations(s, r) for r inrange(len(s)+1))class FiniteMeasurableSpace:"""A finite measurable space Parameters ---------- atoms The atoms of the space sigma_algebra The σ-algebra of the space """def__init__(self, atoms: SampleSpace, sigma_algebra: SigmaAlgebra):self._atoms = atomsself._sigma_algebra = sigma_algebraself._validate()def _validate(self):for subset inself._sigma_algebra:# check powerset conditionifnot subset <=self._atoms:raiseValueError("All events must be a subset of the atoms")# check closure under complementifnot (self._atoms - subset) inself._sigma_algebra:raiseValueError("The σ-algebra must be closed under complements")for subsets in powerset(self._sigma_algebra): subsets =list(subsets)# python doesn't like to reduce empty iterablesifnot subsets:continue# check closure under finite union union =frozenset(reduce(frozenset.union, subsets))if union notinself._sigma_algebra:raiseValueError("The σ-algebra must be closed under countable union" )# check closure under finite intersection intersection =frozenset(reduce(frozenset.intersection, subsets))if intersection notinself._sigma_algebra:raiseValueError("The σ-algebra must be closed under countable intersection" )@propertydef atoms(self) -> SampleSpace:returnself._atoms@propertydef sigma_algebra(self) -> SigmaAlgebra:returnself._sigma_algebra
Define ProbabilityMeasure
from typing import Dictfrom itertools import combinationsclass ProbabilityMeasure:"""A probability measure with finite support Parameters ---------- domain The domain of the probability measure measure The graph of the measure """def__init__(self, domain: FiniteMeasurableSpace, measure: Dict[Event, float]):self._domain = domainself._measure = measureself._validate()def__call__(self, event: Event) ->float:returnself._measure[event]def _validate(self):# check that the measure covers the domainfor event inself._domain.sigma_algebra:if event notinself._measure:raiseValueError("Probability measure must be defined for all events.")# check the assumption of unit measureifself._measure[frozenset(self._domain.atoms)] !=1:raiseValueError("The probability of the sample space must be 1.")# check assumption of 𝜎-additivityfor events in powerset(self._domain.sigma_algebra): events =list(events)ifnot events:continueifnotany(e1.intersection(e2) for e1, e2 in combinations(events, 2)): prob_union =self._measure[reduce(frozenset.union, events)] prob_sum =sum(self._measure[e] for e in events)ifround(prob_union, 4) !=round(prob_sum, 4):raiseValueError("The measure does not satisfy 𝜎-additivity.")def are_mutually_exclusive(self, *events: Iterable[Event]):self._validate_events(events)returnnotany(e1.intersection(e2) for e1, e2 in combinations(events, 2))def _validate_events(self, events: Iterable[Event]):for i, event inenumerate(events):if event notinself._domain.sigma_algebra:raiseValueError(f"event{i} is not in the event space.")
class ProbabilityMeasure(ProbabilityMeasure):def__call__(self, *events: Iterable[Event]) ->float:self._validate_events(events) intersection =reduce(frozenset.intersection, events)returnself._measure[intersection]
In our running example, the probability of a high back vowel is the joint probability \(\mathbb{P}(H, B)\).
Define generate_sigma_algebra
def generate_sigma_algebra(family: SigmaAlgebra) -> SigmaAlgebra:"""Generate a σ-algebra from a family of sets Parameters ---------- family The family of sets from which to generate the σ-algebra """ sigma_algebra =set(family) old_sigma_algebra =set(family) complete =Falsewhilenot complete:for subsets in powerset(old_sigma_algebra): subsets =list(subsets)ifnot subsets:continue union =reduce(frozenset.union, subsets) sigma_algebra.add(union) intersection =reduce(frozenset.intersection, subsets) sigma_algebra.add(intersection) complete = sigma_algebra == old_sigma_algebra old_sigma_algebra =set(sigma_algebra)returnfrozenset(sigma_algebra)
measure_highness_backness = ProbabilityMeasure( highness_backness_space, {e: len(e)/len(highness_backness_space.atoms)for e in highness_backness_space.sigma_algebra})measure_highness_backness(frozenset(high), frozenset(back))
0.18181818181818182
Conditional probability
The probability of an event \(A \in \mathcal{F}\)conditioned on (or given) an event \(B \in \mathcal{F}\) is defined as \(\mathbb{P}(A \mid B) = \frac{\mathbb{P}(A, B)}{\mathbb{P}(B)}\). Note that \(\mathbb{P}(A \mid B)\) is undefined if \(\mathbb{P}(B) = 0\).
class ProbabilityMeasure(ProbabilityMeasure):def__or__(self, conditions: Iterable[Event]) -> ProbabilityMeasure: condition =reduce(frozenset.intersection, conditions)self._validate_condition(condition) measure = { event: self(event, condition)/self(condition)for event inself._domain.sigma_algebra }return ProbabilityMeasure(self._domain, measure)def _validate_condition(self, condition: Event):if condition notinself._domain.sigma_algebra:raiseValueError("The conditions must be in the event space.")ifself._measure[condition] ==0:raiseZeroDivisionError("Conditions cannot have probability 0.")
In our running example, the probability that a vowel is high given that it is back is the conditional probability \(\mathbb{P}(H \mid B) = \frac{\mathbb{P}(H, B)}{\mathbb{P}(B)}\).
From this definition, it immediately follows that \(\mathbb{P}(A, B) = \mathbb{P}(A \mid B)\mathbb{P}(B) = \mathbb{P}(B \mid A)\mathbb{P}(A)\), which in turn implies Bayes’ theorem.
\[\mathbb{P}(A \mid B) = \frac{\mathbb{P}(A, B)}{\mathbb{P}(B)} = \frac{\mathbb{P}(B \mid A)\mathbb{P}(A)}{\mathbb{P}(B)}\]
Bayes’ theorem will be very important in this course.
Another important consequence of the definition of conditional probability is the chain rule:
The chain rule will also be very important in this course.
Independence
An event \(A \in \mathcal{F}\) is independent of an event \(B \in \mathcal{F}\) (under \(\mathbb{P}\)) if \(\mathbb{P}(A \mid B) = \mathbb{P}(A)\). A theoreom that immediately follows from this definition is that \(A\) and \(B\) are independent under \(\mathbb{P}\) if and only if \(\mathbb{P}(A, B) = \mathbb{P}(A \mid B)\mathbb{P}(B) = \mathbb{P}(A)\mathbb{P}(B)\).
class ProbabilityMeasure(ProbabilityMeasure):def are_independent(self, *events):self._validate_events(events) joint =self(*events) product =reduce(lambda x, y: x * y, [self(e) for e in events])return joint == product
In our running example of an event space structured by high and back vowels, assuming all vowels are equiprobable, none of the events are independent. In the discrete event space, many events will be independent.
measure_highness_backness = ProbabilityMeasure( highness_backness_space, {e: len(e)/len(highness_backness_space.atoms)for e in highness_backness_space.sigma_algebra})measure_highness_backness.are_independent(frozenset(high), frozenset(back))
False
Note that independence is not the same as mutual exclusivity; indeed, mutually exclusive events are not independent, since \(\mathbb{P}(A \mid B) = \frac{\mathbb{P}(A, B)}{\mathbb{P}(B)} = \frac{0}{\mathbb{P}(B)} = 0\) (or is undefined if \(\mathbb{P}(B) = 0\)) regardless of \(\mathbb{P}(A)\), and therefore either \(\mathbb{P}(A \mid B)\) does not equal \(\mathbb{P}(A)\) or \(\mathbb{P}(B \mid A)\) is undefined (because \(\mathbb{P}(A) = 0\)), even when \(\mathbb{P}(B)\) is.