# 不确定性问题 上一讲中,我们讨论了人工智能如何表示和推导新知识。然而,在现实中,人工智能往往对世界只有部分了解,这给不确定性留下了空间。尽管如此,我们还是希望我们的人工智能在这些情况下做出尽可能好的决定。例如,在预测天气时,人工智能掌握了今天的天气信息,但无法 100% 准确地预测明天的天气。尽管如此,我们可以做得比偶然更好,今天的讲座是关于我们如何创造人工智能,在有限的信息和不确定性的情况下做出最佳决策。 ## 概率 (Probability) 不确定性可以表示为多个事件以及每一个事件发生的可能性或概率。 ### 概率世界 每一种可能的情况都可以被视为一个世界,由小写的希腊字母$ω$表示。例如,掷骰子可以产生六个可能的世界:骰子出现 1 的世界,骰子出现 2 的世界,依此类推。为了表示某个世界的概率,我们写$P(ω)$。 ### 概率公理 - $0
$。为了便于解释,这些值有一个固定的顺序(在我们的情况下,准时、延迟、取消)。 ### 独立性 (Independence) 独立性是指一个事件的发生不会影响另一个事件发生的概率。例如,当掷两个骰子时,每个骰子的结果与另一个骰子的结果是独立的。用第一个骰子掷出 4 不会影响我们掷出的第二个骰子的值。这与依赖事件相反,比如早上的云和下午的雨。如果早上多云,下午更有可能下雨,所以这些事件是有依赖性的。 独立性可以用数学定义:事件$a$和$b$是独立的,当且仅当$a$并且$b$的概率等于$a$的概率乘以$b$的概率:$P(a∧b)=P(a)P(b)$。 ## 贝叶斯规则 (Bayes’Rule) 贝叶斯规则在概率论中常用来计算条件概率。换句话说,贝叶斯规则说,给定$b$条件下$a$的概率等于给定$a$的条件下$b$概率,乘以$b$的概率除以$a$ 的概率。 $P(b|a)=\frac{P(a|b)P(b)}{P(a)}$ 例如,如果早上有云,我们想计算下午下雨的概率,或者$P(雨 | 云)$。我们从以下信息开始: - 80% 的雨天下午开始于多云的早晨,或$P(云 | 雨)$。 - 40% 的日子早晨多云,或$P(云)$。 - 10% 的日子有下雨的下午,或$P(雨)$。 应用贝叶斯规则,我们计算$\frac{0.8*0.1}{0.4}=0.2$。也就是说,考虑到早上多云,下午下雨的可能性是 20%。 除了$P(a)$和$P(b)$之外,知道$P(a|b)$还允许我们计算$P(b|a)$。这是有帮助的,因为知道给定未知原因的可见效应的条件概率$P(可见效应 | 未知原因)$,可以让我们计算给定可见效应的未知原因的概率$P(未知原因 | 可见效应)$。例如,我们可以通过医学试验来学习$P(医学测试结果 | 疾病)$,在医学试验中,我们对患有该疾病的人进行测试,并观察测试结果发生的频率。知道了这一点,我们就可以计算出$P(疾病 | 医学检测结果)$,这是有价值的诊断信息。 ## 联合概率 (Joint Probability) 联合概率是指多个事件全部发生的可能性。 让我们考虑下面的例子,关于早上有云,下午有雨的概率。 | C=云 | C=$\lnot$云 | | ---- | ----------- | | 0.4 | 0.6 | | R=雨 | R=$\lnot$雨 | | ---- | ----------- | | 0.1 | 0.9 | 从这些数据来看,我们无法判断早上的云是否与下午下雨的可能性有关。为了做到这一点,我们需要看看这两个变量所有可能结果的联合概率。我们可以将其表示在下表中: | | R=雨 | R=$\lnot$ 雨 | | ----------- | ---- | ------------ | | C=云 | 0.08 | 0.32 | | C=$\lnot$云 | 0.02 | 0.58 | 现在我们可以知道有关这些事件同时发生的信息了。例如,我们知道某一天早上有云,下午有雨的概率是 0.08。早上没有云,下午没有雨的概率是 0.58。 使用联合概率,我们可以推导出条件概率。例如,如果我们感兴趣的是在下午下雨的情况下,早上云层的概率分布。$P(C|雨)=\frac{P(C,雨)}{P(雨)}$旁注:在概率上,逗号和$∧$可以互换使用。因此,$P(C,雨)=P(C\land 雨)$。换句话说,我们将降雨和云层的联合概率除以降雨的概率。 在最后一个方程中,可以将$P(雨)$视为$P(C,雨)$乘以的某个常数$\alpha=\frac{1}{P(雨)}$。因此,我们可以重写$P(C|雨)=\frac{P(C,雨)}{P(雨)}=αP(C,雨)$,或$α<0.08,0.02>=<0.8,0.2>$。考虑到下午有雨,将$α$分解后,我们可以得到 C 的可能值的概率比例。也就是说,如果下午有雨,那么早上有云和早上没有云的概率的比例是$0.08:0.02$。请注意,0.08 和 0.02 的总和不等于 1;然而,由于这是随机变量 C 的概率分布,我们知道它们应该加起来为 1。因此,我们需要通过算$α$来归一化这些值,使得$α0.08+α0.02=1$。最后,我们可以说$P(C|雨)=<0.8,0.2>$。 ## 概率规则 (Probability Rules) - 否定 (Negation): $P(\lnot a)=1-P(a)$。这源于这样一个事实,即所有可能世界的概率之和为 1,互补事件$\lnot a$和 $a$ 包括所有可能世界。 - 包含 - 排除 Inclusion-Exclusion:$P(a\lor b)=P(a)+P(b)-P(a\land b)$。这可以用以下方式解释:$a$或$b$为真的世界等于$a$为真的所有世界,加上$b$为真的所有世界。然而,在这种情况下,有些世界被计算两次(a 和$b$都为真的世界)。为了消除这种重叠,我们将$a$和$b$ 都为真的世界减去一次(因为它们被计算了两次)。 > 下面是一个例子,可以说明这一点。假设我 80% 的时间吃冰淇淋,70% 的时间吃饼干。如果我们计算今天我吃冰淇淋或饼干的概率,不减去$P(冰淇淋∧饼干)$,我们错误地得出 0.7+0.8=1.5。这与概率在 0 和 1 之间的公理相矛盾。为了纠正我同时吃冰淇淋和饼干的天数计算两次的错误,我们需要减去$P(冰淇淋∧饼干)$一次。 - 边缘化 (Marginalization):$P(a)=P(a,b)+P(a,\lnot b)$。这里的观点是,$b$和$\lnot b$是独立的概率。也就是说,$b$和$\lnot b$同时发生的概率为 0。我们也知道$b$和$\lnot b$的总和为 1。因此,当$a$发生时,$b$可以发生也可以不发生。当我们把$a$和$b$发生的概率加上$a$和$\lnot b$的概率时,我们得到的只是$a$ 的概率。 随机变量的边缘化可以用:$P(X=x_i)=\sum_jP(X=x_i,Y=y_j)$表示 方程的左侧表示“随机变量$X$具有$x_i$值的概率”例如,对于我们前面提到的变量 C,两个可能的值是早上有云和早上没有云。等式的正确部分是边缘化的概念。$P(X=x_i)$等于$x_i$以及随机变量$Y$的每一个值的所有联合概率之和。例如,$P(C=云)=P(C=云,R=雨)+P(C=云,R=\lnot 雨)=0.08+0.32=0.4$。 - 条件边缘化:$P(a)=P(a|b)P(b)+P(a|\lnot b)P(\lnot b)$。这是一个类似于边缘化的想法。事件$a$发生的概率等于给定$b$的概率乘以$b$的概率,再加上给定$\lnot b$的概率乘以$\lnot b$ 的概率。 $P(X=x_i)=\sum_jP(X=x_i|Y=y_i)P(Y=y_i)$ 在这个公式中,随机变量$X$取$x_i$值概率等于$x_i$以及随机变量$Y$的每个值的联合概率乘以变量$Y$取该值的概率之和。如果我们还记得$P(a|b)=\frac{P(a,b)}{P(b)}$,就可以理解这个公式。如果我们将这个表达式乘以$P(b)$,我们得到$P(a,b)$,从这里开始,我们做的与边缘化相同。 ## 贝叶斯网络 (Bayesian Networks) 贝叶斯网络是一种表示随机变量之间相关性的数据结构。贝叶斯网络具有以下属性: - 它们是有向图。 - 图上的每个节点表示一个随机变量。 - 从 X 到 Y 的箭头表示 X 是 Y 的父对象。也就是说,Y 的概率分布取决于 X 的值。 - 每个节点 X 具有概率分布$P(X|Parents(X))$。 让我们考虑一个贝叶斯网络的例子,该网络包含影响我们是否按时赴约的随机变量。  让我们从上到下描述这个贝叶斯网络: - rain 是这个网络的根节点。这意味着它的概率分布不依赖于任何先前的事件。在我们的例子中,Rain 是一个随机变量,可以采用以下概率分布的值$\set{none,light,heavy}$: | none | light | heavy | | ---- | ----- | ----- | | 0.7 | 0.2 | 0.1 | - Maintenance 对是否有列车轨道维护进行编码,取值为$\set{yes,no}$。Rain 是 Maintenance 的父节点,这意味着 Maintenance 概率分布受到 Rain 的影响。 | R | yes | no | | ----- | --- | --- | | none | 0.4 | 0.6 | | light | 0.2 | 0.8 | | heavy | 0.1 | 0.9 | - Train 是一个变量,用于编码列车是准时还是晚点,取值为$\set{on\ time,delayed}$。请注意,列车上被“Maintenance”和“rain”指向。这意味着两者都是 Train 的父对象,它们的值会影响 Train 的概率分布。 | R | M | On time | Delayed | | ------ | --- | ------- | ------- | | none | yes | 0.8 | 0.2 | | none | no | 0.9 | 0.1 | | light | yes | 0.6 | 0.4 | | light | no | 0.7 | 0.3 | | heavry | yes | 0.4 | 0.6 | | heavy | no | 0.5 | 0.5 | - Appointment 是一个随机变量,表示我们是否参加约会,取值为$\set{attend, miss}$。请注意,它唯一的父级是 Train。关于贝叶斯网络的这一点值得注意:父子只包括直接关系。的确,Maintenance 会影响 Train 是否准时,而 Train 是否准时会影响我们是否赴约。然而,最终,直接影响我们赴约机会的是 Train 是否准时,这就是贝叶斯网络所代表的。例如,如果火车准时到达,可能会有大雨和轨道维护,但这对我们是否赴约没有影响。 | T | attend | miss | | ------- | ------ | ---- | | on time | 0.9 | 0.1 | | delayed | 0.6 | 0.4 | 例如,如果我们想找出在没有维护和小雨的一天火车晚点时错过约会的概率,或者$P(light,no,delayed,miss)$,我们将计算如下:$P(light)P(no|light)P(delayed|light,no)P(miss|delayed)$。每个单独概率的值可以在上面的概率分布中找到,然后将这些值相乘以产生$P(light,no,delayed,miss)$。 ### 推理 (Inference) 在知识推理,我们通过蕴含来看待推理。这意味着我们可以在现有信息的基础上得出新的信息。我们也可以根据概率推断出新的信息。虽然这不能让我们确切地知道新的信息,但它可以让我们计算出一些值的概率分布。推理具有多个属性。 - Query 查询变量 $X$:我们要计算概率分布的变量。 - Evidence variables 证据变量$E$: 一个或多个观测到事件$e$ 的变量。例如,我们可能观测到有小雨,这一观测有助于我们计算火车延误的概率。 - Hidden variables 隐藏变量 $H$: 不是查询结论的变量,也没有被观测到。例如,站在火车站,我们可以观察是否下雨,但我们不知道道路后面的轨道是否有维修。因此,在这种情况下,Maintenance 将是一个隐藏的变量。 - The goal 目标:计算$P(X|e)$。例如,根据我们知道有小雨的证据 $e$ 计算 Train 变量 (查询) 的概率分布。 举一个例子。考虑到有小雨和没有轨道维护的证据,我们想计算 Appointment 变量的概率分布。也就是说,我们知道有小雨,没有轨道维护,我们想弄清楚我们参加约会和错过约会的概率是多少,$P(Appointment|light,no)$。从联合概率部分中,我们知道我们可以将约会随机变量的可能值表示为一个比例,将$P(Appointment|light,no)$重写为$αP(Appointment,light,no)$。如果 Appointment 的父节点仅为 Train 变量,而不是 Rain 或 Maintenance,我们如何计算约会的概率分布?在这里,我们将使用边缘化。$P(Appointment,light,no)$的值等于$α[P(Appointment,light,no,delay)+P(Appointment,light,no,on\ time)]$。 ### 枚举推理 枚举推理是在给定观测证据$e$和一些隐藏变量$Y$的情况下,找到变量$X$ 的概率分布的过程。 $P(X|e)=\alpha P(X,e)=\alpha \sum_yP(X,e,y)$ 在这个方程中,$X$代表查询变量,$e$代表观察到的证据,$y$代表隐藏变量的所有值,$α$归一化结果,使我们最终得到的概率加起来为 1。用文字来解释这个方程,即给定$e$的$X$的概率分布等于$X$和$e$的归一化概率分布。为了得到这个分布,我们对$X、e$和$y$的归一化概率求和,其中$y$每次取隐藏变量$Y$ 的不同值。 Python 中存在多个库,以简化概率推理过程。我们将查看库 `pomegranate`,看看如何在代码中表示上述数据。 ```python from pomegranate import * '''创建节点,并为每个节点提供概率分布''' # Rain 节点没有父节点 rain = Node(DiscreteDistribution({ "none": 0.7, "light": 0.2, "heavy": 0.1 }), name="rain") # Track maintenance 节点以 rain 为条件 maintenance = Node(ConditionalProbabilityTable([ ["none", "yes", 0.4], ["none", "no", 0.6], ["light", "yes", 0.2], ["light", "no", 0.8], ["heavy", "yes", 0.1], ["heavy", "no", 0.9] ], [rain.distribution]), name="maintenance") # Train node 节点以 rain 和 maintenance 为条件 train = Node(ConditionalProbabilityTable([ ["none", "yes", "on time", 0.8], ["none", "yes", "delayed", 0.2], ["none", "no", "on time", 0.9], ["none", "no", "delayed", 0.1], ["light", "yes", "on time", 0.6], ["light", "yes", "delayed", 0.4], ["light", "no", "on time", 0.7], ["light", "no", "delayed", 0.3], ["heavy", "yes", "on time", 0.4], ["heavy", "yes", "delayed", 0.6], ["heavy", "no", "on time", 0.5], ["heavy", "no", "delayed", 0.5], ], [rain.distribution, maintenance.distribution]), name="train") # Appointment 节点以列车为条件 appointment = Node(ConditionalProbabilityTable([ ["on time", "attend", 0.9], ["on time", "miss", 0.1], ["delayed", "attend", 0.6], ["delayed", "miss", 0.4] ], [train.distribution]), name="appointment") '''我们通过添加所有节点来创建模型,然后通过在节点之间添加边来描述哪个节点是另一个节点的父节点(回想一下,贝叶斯网络是一个有向图,节点之间由箭头组成)。''' # 创建贝叶斯网络并添加状态 model = BayesianNetwork() model.add_states(rain, maintenance, train, appointment) # 添加连接节点的边 model.add_edge(rain, maintenance) model.add_edge(rain, train) model.add_edge(maintenance, train) model.add_edge(train, appointment) # 最终确定模型 model.bake() '''模型可以计算特定条件下的概率''' # 计算给定观测的概率 probability = model.probability([["none", "no", "on time", "attend"]]) print(probability) '''我们可以使用该模型为所有变量提供概率分布,给出一些观测到的证据。在以下情况下,我们知道火车晚点了。给定这些信息,我们计算并打印变量 Rain、Maintenance 和 Appointment 的概率分布。''' # 根据火车晚点的证据计算预测 predictions = model.predict_proba({ "train": "delayed" }) # 打印每个节点的预测 for node, prediction in zip(model.states, predictions): # 预测已确定时返回字符串 if isinstance(prediction, str): print(f"{node.name}: {prediction}") else: # 预测不确定时返回概率分布 print(f"{node.name}") for value, probability in prediction.parameters[0].items(): print(f" {value}: {probability:.4f}") ``` 上面的代码使用了枚举推理。然而,这种计算概率的方法效率很低,尤其是当模型中有很多变量时。另一种方法是放弃精确推理,转而采用近似推理。这样做,我们在生成的概率中会失去一些精度,但这种不精确性通常可以忽略不计。相反,我们获得了一种可扩展的概率计算方法。 ### 采样 (Sampling) 采样是一种近似推理技术。在采样中,根据每个变量的概率分布对其值进行采样。 > 要使用骰子采样生成分布,我们可以多次掷骰子,并记录每次获得的值。假设我们把骰子掷了 600 次。我们计算得到 1 的次数,应该大约是 100,然后对其余的值 2-6 重复采样。然后,我们将每个计数除以投掷的总数。这将生成掷骰子的值的近似分布:一方面,我们不太可能得到每个值发生概率为 1/6 的结果(这是确切的概率),但我们会得到一个接近它的值。 如果我们从对 Rain 变量进行采样开始,则生成的值 none 的概率为 0.7,生成的值 light 的概率为 0.2,而生成的值 heavy 的概率则为 0.1。假设我们的采样值为 none。当我们得到 Maintenance 变量时,我们也会对其进行采样,但只能从 Rain 等于 none 的概率分布中进行采样,因为这是一个已经采样的结果。我们将通过所有节点继续这样做。现在我们有一个样本,多次重复这个过程会生成一个分布。现在,如果我们想回答一个问题,比如什么是$P(Train=on\ time)$,我们可以计算变量 Train 具有准时值的样本数量,并将结果除以样本总数。通过这种方式,我们刚刚生成了$P(Train=on\ {time})$的近似概率。
![]() |
![]() |
![]() |
![]() |