From 382f1b6c1e30d5281107db0c193eddee974e373d Mon Sep 17 00:00:00 2001 From: camera-2018 <2907618001@qq.com> Date: Sat, 6 May 2023 12:51:26 +0800 Subject: [PATCH] =?UTF-8?q?chore=20=E4=B8=8D=E7=A1=AE=E5=AE=9A=E6=80=A7?= =?UTF-8?q?=E6=9C=89=E9=97=AE=E9=A2=98=20=E7=9C=9F=E5=96=9C=E6=AC=A2?= =?UTF-8?q?=E7=94=A8=E6=97=A0=E5=BA=8F=E5=88=97=E8=A1=A8=E5=95=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vitepress/config.js | 11 + 4.人工智能/4.3.3.1程序示例.md | 53 + 4.人工智能/4.3.3.2项目:遗传.md | 93 ++ 4.人工智能/4.3.3不确定性问题.md | 1049 +++++++++++++++++ .../static/AptYbb5MZoylvex7LvPcSqivnef.png | Bin 0 -> 127216 bytes .../static/CreObGAg4oXB0oxe2hMcQbYZnAc.png | Bin 0 -> 103872 bytes .../static/E0TtbfgiCoV2dtxbbPHcjPgXnQe.png | Bin 0 -> 55277 bytes .../static/FNyab3RWQo3EA8xu8T7cyLwhnyh.png | Bin 0 -> 96735 bytes .../static/FnyrbYSEWohimaxIYPSchotGnse.png | Bin 0 -> 61377 bytes .../static/GKc6be6ueopUYZxxQg4cS4AVnmb.png | Bin 0 -> 106118 bytes .../static/GqlRbfW7Yom5a9xKCBHckMBuniF.png | Bin 0 -> 168885 bytes .../static/Ilj3bPKuwo0l6Dx13rZcVXfenOb.png | Bin 0 -> 116193 bytes .../static/KsELbuMTCoKZkGxU9U5czQpanKg.png | Bin 0 -> 21367 bytes .../static/MkZ6bIPFroAm3lxzLydcsn5QnNg.png | Bin 0 -> 73208 bytes .../static/MrP0b2FbXofDsOxgnmncufUynAB.png | Bin 0 -> 103945 bytes .../static/PUesbhgsFoiucAxWBKYcUUU3nMd.png | Bin 0 -> 46840 bytes .../static/VBGxbrNgAovuKXxnTKYcm7UinFd.png | Bin 0 -> 59701 bytes .../static/Vr96bdSafoV4kBxJ3x2cAU0TnOg.png | Bin 0 -> 117359 bytes .../static/XBghbKBaVoz0C4xa85rch804ngd.png | Bin 0 -> 36217 bytes .../static/XZfhbR6sBorTI9x7hVVchGLUn3b.png | Bin 0 -> 91838 bytes .../static/Y8EbbcnUsoHHlFxHCrGcIUDNn0f.png | Bin 0 -> 100531 bytes .../5.2New meaning of C.md | 161 +++ .../5.3还玩裸机?上操作系统!.md | 172 +++ .../static/CZ3cbiEhsoWDgJxhwXIcpUkAnMg.png | Bin 0 -> 4932 bytes .../static/HTFUbsQCNouQVzx0QYiciQWOnZf.png | Bin 0 -> 42727 bytes .../static/LJ1SbFfv6oUIgtx8CstcbWTNnRg.png | Bin 0 -> 71967 bytes .../static/MyDMbeCKLowC1Mx7Q6Ec9BLPn4g.png | Bin 0 -> 156348 bytes .../static/boxcnFySF1Cd02I052V0a9glH1c.png | Bin 0 -> 28283 bytes .../static/boxcnRy7E27xggqNshXX3cu4J5Q.png | Bin 0 -> 697891 bytes .../static/boxcntQgR61yRboDpyb1bpI10Xp.png | Bin 0 -> 59947 bytes 30 files changed, 1539 insertions(+) create mode 100644 4.人工智能/4.3.3.1程序示例.md create mode 100644 4.人工智能/4.3.3.2项目:遗传.md create mode 100644 4.人工智能/4.3.3不确定性问题.md create mode 100644 4.人工智能/static/AptYbb5MZoylvex7LvPcSqivnef.png create mode 100644 4.人工智能/static/CreObGAg4oXB0oxe2hMcQbYZnAc.png create mode 100644 4.人工智能/static/E0TtbfgiCoV2dtxbbPHcjPgXnQe.png create mode 100644 4.人工智能/static/FNyab3RWQo3EA8xu8T7cyLwhnyh.png create mode 100644 4.人工智能/static/FnyrbYSEWohimaxIYPSchotGnse.png create mode 100644 4.人工智能/static/GKc6be6ueopUYZxxQg4cS4AVnmb.png create mode 100644 4.人工智能/static/GqlRbfW7Yom5a9xKCBHckMBuniF.png create mode 100644 4.人工智能/static/Ilj3bPKuwo0l6Dx13rZcVXfenOb.png create mode 100644 4.人工智能/static/KsELbuMTCoKZkGxU9U5czQpanKg.png create mode 100644 4.人工智能/static/MkZ6bIPFroAm3lxzLydcsn5QnNg.png create mode 100644 4.人工智能/static/MrP0b2FbXofDsOxgnmncufUynAB.png create mode 100644 4.人工智能/static/PUesbhgsFoiucAxWBKYcUUU3nMd.png create mode 100644 4.人工智能/static/VBGxbrNgAovuKXxnTKYcm7UinFd.png create mode 100644 4.人工智能/static/Vr96bdSafoV4kBxJ3x2cAU0TnOg.png create mode 100644 4.人工智能/static/XBghbKBaVoz0C4xa85rch804ngd.png create mode 100644 4.人工智能/static/XZfhbR6sBorTI9x7hVVchGLUn3b.png create mode 100644 4.人工智能/static/Y8EbbcnUsoHHlFxHCrGcIUDNn0f.png create mode 100644 5.富有生命的嵌入式/5.2New meaning of C.md create mode 100644 5.富有生命的嵌入式/5.3还玩裸机?上操作系统!.md create mode 100644 5.富有生命的嵌入式/static/CZ3cbiEhsoWDgJxhwXIcpUkAnMg.png create mode 100644 5.富有生命的嵌入式/static/HTFUbsQCNouQVzx0QYiciQWOnZf.png create mode 100644 5.富有生命的嵌入式/static/LJ1SbFfv6oUIgtx8CstcbWTNnRg.png create mode 100644 5.富有生命的嵌入式/static/MyDMbeCKLowC1Mx7Q6Ec9BLPn4g.png create mode 100644 5.富有生命的嵌入式/static/boxcnFySF1Cd02I052V0a9glH1c.png create mode 100644 5.富有生命的嵌入式/static/boxcnRy7E27xggqNshXX3cu4J5Q.png create mode 100644 5.富有生命的嵌入式/static/boxcntQgR61yRboDpyb1bpI10Xp.png diff --git a/.vitepress/config.js b/.vitepress/config.js index cb7de6c..7b68de9 100644 --- a/.vitepress/config.js +++ b/.vitepress/config.js @@ -305,6 +305,15 @@ export default defineConfig({ { text: '4.3.2.2项目:扫雷,骑士与流氓问题', link: '/4.人工智能/4.3.2.2项目:扫雷,骑士与流氓问题' }, ] }, + { + text: '4.3.3不确定性问题', + collapsed: true, + items: [ + { text: '4.3.3不确定性问题', link: '/4.人工智能/4.3.3不确定性问题' }, + { text: '4.3.3.1程序示例', link: '/4.人工智能/4.3.3.1程序示例' }, + { text: '4.3.3.2项目:遗传', link: '/4.人工智能/4.3.3.2项目:遗传' }, + ] + }, ] }, { text: '4.4FAQ:常见问题', link: '/4.人工智能/4.4FAQ:常见问题' }, @@ -558,6 +567,8 @@ export default defineConfig({ items: [ { text: '5.富有生命的嵌入式', link: '/5.富有生命的嵌入式/5.富有生命的嵌入式' }, { text: '5.1嵌入式是什么?可以吃吗?', link: '/5.富有生命的嵌入式/5.1嵌入式是什么?可以吃吗?' }, + { text: '5.2New meaning of C', link: '/5.富有生命的嵌入式/5.2New meaning of C' }, + { text: '5.3还玩裸机?上操作系统!', link: '/5.富有生命的嵌入式/5.3还玩裸机?上操作系统!' }, ] }, { diff --git a/4.人工智能/4.3.3.1程序示例.md b/4.人工智能/4.3.3.1程序示例.md new file mode 100644 index 0000000..8e5e85f --- /dev/null +++ b/4.人工智能/4.3.3.1程序示例.md @@ -0,0 +1,53 @@ +# 程序示例 +::: tip +阅读程序,然后“玩一玩”程序! + +完成习题 +::: + +本节代码不做额外梳理,[不确定性问题](./4.3.3%E4%B8%8D%E7%A1%AE%E5%AE%9A%E6%80%A7%E9%97%AE%E9%A2%98.md) 中已有解释。 + +## Quiz + +1. 考虑一副标准的 52 张牌,在四种花色(梅花、方块、红心、黑桃)中各有 13 种牌值(A、K、Q、J 和 2-10)。如果随机抽出一张牌,它是黑桃或 2 的概率是多少? + 1. About 0.019 + 2. About 0.077 + 3. About 0.17 + 4. About 0.25 + 5. About 0.308 + 6. About 0.327 + 7. About 0.5 + 8. None of the above +2. 想象一下,抛出两枚硬币,每枚硬币都有正面和反面,50% 的时间出现正面,50% 的时间出现反面。抛出这两枚硬币后,其中一枚是正面,另一枚是反面的概率是多少? + 1. 0 + 2. 0.125 + 3. 0.25 + 4. 0.375 + 5. 0.5 + 6. 0.625 + 7. 0.75 + 8. 0.875 + 9. 1 +3. 回答关于贝叶斯网络的问题,问题如下: + +  + + 以下哪句话是真的? + + 1. 假设我们知道有轨道维护,那么是否有雨并不影响列车准时到达的概率。 + 2. 假设我们知道有雨,那么是否有轨道维修并不影响列车准时到达的概率。 + 3. 假设我们知道火车是准时的,是否有雨会影响到赴约的概率。 + 4. 假设我们知道火车是准时的,那么是否有轨道维修并不影响赴约的概率。 + 5. 假设我们知道有轨道维护,那么是否有雨并不影响参加约会的概率。 +4. 两家工厂--A 厂和 B 厂--设计用于手机的电池。A 厂生产 60% 的电池,B 厂生产另外 40%。A 厂 2% 的电池有缺陷,B 厂 4% 的电池有缺陷。一个电池既由 A 厂生产又有缺陷的概率是多少? + 1. 0.008 + 2. 0.012 + 3. 0.024 + 4. 0.028 + 5. 0.02 + 6. 0.06 + 7. 0.12 + 8. 0.2 + 9. 0.429 + 10. 0.6 + 11. None of the above diff --git a/4.人工智能/4.3.3.2项目:遗传.md b/4.人工智能/4.3.3.2项目:遗传.md new file mode 100644 index 0000000..352424e --- /dev/null +++ b/4.人工智能/4.3.3.2项目:遗传.md @@ -0,0 +1,93 @@ +# 项目:遗传 + +::: tip +我们为你提供了一个简单有趣的项目,帮助你进行知识巩固,请认真阅读文档内容。 + +如果你卡住了,请记得回来阅读文档,或请求身边人的帮助。 +::: +## 背景 + +- GJB2 基因的突变版本是导致新生儿听力障碍的主要原因之一。每个人都携带两个版本的基因,因此每个人都有可能拥有 0、1 或 2 个听力障碍版本的 GJB2 基因。不过,除非一个人接受基因测试,否则要知道一个人拥有多少个变异的 GJB2 基因并不那么容易。这是一些 "隐藏状态":具有我们可以观察到的影响(听力损伤)的信息,但我们不一定直接知道。毕竟,有些人可能有 1 或 2 个突变的 GJB2 基因,但没有表现出听力障碍,而其他人可能没有突变的 GJB2 基因,但仍然表现出听力障碍。 +- 每个孩子都会从他们的父母那里继承一个 GJB2 基因。如果父母有两个变异基因,那么他们会将变异基因传给孩子;如果父母没有变异基因,那么他们不会将变异基因传给孩子;如果父母有一个变异基因,那么该基因传给孩子的概率为 0.5。不过,在基因被传递后,它有一定的概率发生额外的突变:从导致听力障碍的基因版本转变为不导致听力障碍的版本,或者反过来。 +- 我们可以尝试通过对所有相关变量形成一个贝叶斯网络来模拟所有这些关系,就像下面这个网络一样,它考虑了一个由两个父母和一个孩子组成的家庭。 + + + +- 家庭中的每个人都有一个 `Gene` 随机变量,代表一个人有多少个特定基因(例如,GJB2 的听力障碍版本):一个 0、1 或 2 的值。家族中的每个人也有一个 `Trait` 随机变量,它是 `yes` 或 `no`,取决于该人是否表达基于该基因的性状(例如,听力障碍)。从每个人的 `Gene` 变量到他们的 `Trait` 变量之间有一个箭头,以编码一个人的基因影响他们具有特定性状的概率的想法。同时,也有一个箭头从母亲和父亲的 `Gene` 随机变量到他们孩子的 `Gene` 随机变量:孩子的基因取决于他们父母的基因。 +- 你在这个项目中的任务是使用这个模型对人群进行推断。给出人们的信息,他们的父母是谁,以及他们是否具有由特定基因引起的特定可观察特征(如听力损失),你的人工智能将推断出每个人的基因的概率分布,以及任何一个人是否会表现出有关特征的概率分布。 + +## 理解 + +- 打开 `data/family0.csv`,看看数据目录中的一个样本数据集(你可以在文本编辑器中打开,或者在 Google Sheets、Excel 或 Apple Numbers 等电子表格应用程序中打开)。注意,第一行定义了这个 CSV 文件的列:`name`, `mother`, `father`, 和 `trait`。下一行表明 Harry 的母亲是 Lily,父亲是 James,而 `Trait` 的空单元格意味着我们不知道 Harry 是否有这种性状。同时,James 在我们的数据集中没有列出父母(如母亲和父亲的空单元格所示),但确实表现出了性状(如 `Trait` 单元格中的 1 所示)。另一方面,Lily 在数据集中也没有列出父母,但没有表现出这种性状(如 `Trait` 单元格中的 0 表示)。 +- 打开 `heredity.py`,首先看一下 `PROBS` 的定义。`PROBS` 是一个包含若干常数的字典,代表各种不同事件的概率。所有这些事件都与一个人拥有多少个特定的突变基因,以及一个人是否基于该基因表现出特定的性状有关。这里的数据松散地基于 GJB2 基因的听力障碍版本和听力障碍性状的概率,但通过改变这些值,你也可以用你的人工智能来推断其他的基因和性状! +- 首先,`PROBS["gene"]` 代表了该基因的无条件概率分布(即如果我们对该人的父母一无所知的概率)。根据分布代码中的数据,在人群中,有 1% 的机会拥有该基因的 2 个副本,3% 的机会拥有该基因的 1 个副本,96% 的机会拥有该基因的零副本。 +- 接下来,`PROBS["trait"]` 表示一个人表现出某种性状(如听力障碍)的条件概率。这实际上是三个不同的概率分布:基因的每个可能值都有一个。因此,`PROBS["trait"][2]` 是一个人在有两个突变基因的情况下具有该特征的概率分布:在这种情况下,他们有 65% 的机会表现出该特征,而有 35% 的机会不表现出该特征。同时,如果一个人有 0 个变异基因,他们有 1% 的机会表现出该性状,99% 的机会不表现出该性状。 +- 最后,`PROBS["mutation"]` 是一个基因从作为相关基因突变为不是该基因的概率,反之亦然。例如,如果一个母亲有两个变异基因,并因此将其中一个传给她的孩子,就有 1% 的机会突变为不再是变异基因。相反,如果一个母亲没有任何变异基因,因此没有把变异基因传给她的孩子,但仍有 1% 的机会突变为变异基因。因此,即使父母双方都没有变异基因,他们的孩子也可能有 1 个甚至 2 个变异基因。 +- 最终,你计算的概率将以 `PROBS` 中的这些数值为基础。 +- 现在,看一下 `main` 函数。该函数首先将数据从一个文件加载到一个字典 `people` 中。`people` 将每个人的名字映射到另一个包含他们信息的字典中:包括他们的名字,他们的母亲(如果数据集中有一个母亲),他们的父亲(如果数据集中有一个父亲),以及他们是否被观察到有相关的特征(如果有则为 `True`,没有则为 `False`,如果我们不知道则为 `None`)。 +- 接下来,`main` 中定义了一个字典 `probabilities`,所有的概率最初都设置为 0。这就是你的项目最终要计算的内容:对于每个人,你的人工智能将计算他们有多少个变异基因的概率分布,以及他们是否具有该性状。例如,`probabilities["Harry"]["gene"][1]` 将是 Harry 有 1 个变异基因的概率,而 `probabilities["Lily"]["trait"][False]` 将是 Lily 没有表现出该性状的概率。 +- 如果不熟悉的话,这个 `probabilities` 字典是用 [python 字典](https://www.python.org/dev/peps/pep-0274/)创建的,在这种情况下,它为我们的 `people` 中的每个 `person` 创建一个键/值对。 +- 最终,我们希望根据一些证据来计算这些概率:鉴于我们知道某些人有或没有这种特征,我们想确定这些概率。你在这个项目中的任务是实现三个函数来做到这一点: `joint_probability` 计算一个联合概率,`update` 将新计算的联合概率添加到现有的概率分布中,然后 `normalize` 以确保所有概率分布最后和为 1。 + +## 明确 + +- 完成 `joint_probability`、`update` 和 `normalize` 的实现。 +- `joint_probability` 函数应该接受一个 `people` 的字典作为输入,以及关于谁拥有多少个变异基因,以及谁表现出该特征的数据。该函数应该返回所有这些事件发生的联合概率。 + + - 该函数接受四个数值作为输入:`people`, `one_gene`, `two_genes`, 和 `have_trait`。 + + - `people` 是一个在 "理解"一节中描述的人的字典。键代表名字,值是包含 `mother` 和 `father` 键的字典。你可以假设 `mother` 和 `father` 都是空白的(数据集中没有父母的信息),或者 `mother` 和 `father` 都会指代 `people` 字典中的其他人物。 + - `one_gene` 是一个集合,我们想计算所有集合元素有一个变异基因的概率。 + - `two_genes` 是一个集合,我们想计算所有集合元素有两个变异基因的概率。 + - `have_trait` 是一个集合,我们想计算所有集合元素拥有该性状的概率。 + - 对于不在 `one_gene` 或 t `wo_genes` 中的人,我们想计算他们没有变异基因的概率;对于不在 `have_trait` 中的人,我们想计算他们没有该性状的概率。 + + - 例如,如果这个家庭由 Harry、James 和 Lily 组成,那么在 `one_gene = {"Harry"}`、`two_genes = {"James"}` 和 `trait = {"Harry"、"James"}` 的情况下调用这个函数,应该计算出 Lily 没有变异基因、Harry 拥有一个变异基因、James 拥有两个变异基因、Harry 表现出该性状、James 表现出该性状和 Lily 没有表现出该性状的联合概率。 + - 对于数据集中没有列出父母的人,使用概率分布 `PROBS["gene"]` 来确定他们有特定数量基因的概率。 + - 对于数据集中有父母的人来说,每个父母都会把他们的两个基因中的一个随机地传给他们的孩子,而且有一个 `PROBS["mutation"]` 的机会,即它会发生突变(从变异基因变成正常基因,或者相反)。 + - 使用概率分布 `PROBS["trait"]` 来计算一个人具有或不具有形状的概率。 +- `update` 函数将一个新的联合分布概率添加到 `probabilities` 中的现有概率分布中。 + + - 该函数接受五个值作为输入:`probabilities`, `one_gene`, `two_genes`, `have_trait`, 和 `p`。 + + - `probabilities` 是一个在 "理解 "部分提到的字典。每个人都被映射到一个 `"gene"` 分布和一个 `"trait"` 分布。 + - `one_gene` 是一个集合,我们想计算所有集合元素有一个变异基因的概率。 + - `two_genes` 是一个集合,我们想计算所有集合元素有两个变异基因的概率。 + - `have_trait` 是一个集合,我们想计算所有集合元素拥有该性状的概率。 + - `p` 是联合分布的概率。 + - 对于概率中的每个人,该函数应该更新 `probabilities[person]["gene"]` 分布和 `probabilities[person]["trait"]` 分布,在每个分布中的适当数值上加上 `p`。所有其他数值应保持不变。 + - 例如,如果"Harry"同时出现在 `two_genes` 和 `have_trait` 中,那么 `p` 将被添加到 `probabilities["Harry"]["gene"][2]` 和 `probabilities["Harry"]["trait"][True]`。 + - 该函数不应返回任何值:它只需要更新 `probabilities` 字典。 +- `normalize` 函数更新 `probabilities` 字典,使每个概率分布被归一化(即和为 1,相对比例相同)。 + + - 该函数接受一个单一的值:`probabilities`。 + + - `probabilities` 是一个在"理解"部分提到的字典。每个人都被映射到一个 `"gene"` 分布和一个 `"trait"` 分布。 + - 对于 `probabilities` 中每个人的两个分布,这个函数应该将该分布归一化,使分布中的数值之和为 1,分布中的相对数值是相同的。 + - 例如,如果 `probabilities["Harry"]["trait"][True]` 等于 `0.1`,概率 `probabilities["Harry"]["trait"][False]` 等于 `0.3`,那么你的函数应该将前一个值更新为 `0.25`,后一个值更新为 `0.75`: 现在数字之和为 1,而且后一个值仍然比前一个值大三倍。 + - 该函数不应返回任何值:它只需要更新 `probabilities` 字典。 +- 除了规范中要求你实现的三个函数外,你不应该修改 `heredity.py` 中的任何其他东西,尽管你可以编写额外的函数和/或导入其他 Python 标准库模块。如果熟悉的话,你也可以导入 `numpy` 或 `pandas`,但是你不应该使用任何其他第三方 Python 模块。 + +## 一个联合概率例子 + +- 为了帮助你思考如何计算联合概率,我们在下面附上一个例子。 +- 请考虑以下 `people` 的值: + +```python +{ + 'Harry': {'name': 'Harry', 'mother': 'Lily', 'father': 'James', 'trait': None}, + 'James': {'name': 'James', 'mother': None, 'father': None, 'trait': True}, + 'Lily': {'name': 'Lily', 'mother': None, 'father': None, 'trait': False} +} +``` + +- 这里我们将展示 `joint_probability(people, {"Harry"}, {"James"}, {"James"})` 的计算。根据参数,`one_gene` 是 `{"Harry"}`,`two_genes` 是 `{"James"}`,而 `has_trait` 是 `{"James"}`。因此,这代表了以下的概率:Lily 没有变异基因,不具有该性状;Harry 有一个变异基因,不具有该性状;James 有 2 个变异基因,具有该性状。 +- 我们从 Lily 开始(我们考虑人的顺序并不重要,只要我们把正确的数值乘在一起,因为乘法是可交换的)。Lily 没有变异基因,概率为 `0.96`(这就是 `PROBS["gene"][0]`)。鉴于她没有变异基因,她没有这个性状的概率为 `0.99`(这是 `PROBS["trait"][0][False]`)。因此,她没有变异基因且没有该性状的概率是 `0.96*0.99=0.9504`。 +- 接下来,我们考虑 James。James 有 2 个变异基因,概率为 `0.01`(这是 `PROBS["gene"][2]`)。鉴于他有 2 个变异基因,他确实具有该性状的概率为 `0.65`。因此,他有 2 个变异基因并且他确实具有该性状的概率是 `0.01*0.65=0.0065`。 +- 最后,我们考虑 Harry。Harry 有 1 个变异基因的概率是多少?有两种情况可以发生。要么他从母亲那里得到这个基因,而不是从父亲那里,要么他从父亲那里得到这个基因,而不是从母亲那里。他的母亲 Lily 没有变异基因,所以 Harry 会以 `0.01` 的概率从他母亲那里得到这个基因(这是 `PROBS["mutation"]`),因为从他母亲那里得到这个基因的唯一途径是基因突变;相反,Harry 不会从他母亲那里得到这个基因,概率是 `0.99`。他的父亲 James 有 2 个变异基因,所以 Harry 会以 `0.99` 的概率从他父亲那里得到这个基因(这是 `1-PROBS["mutation"]`),但会以 `0.01` 的概率从他母亲那里得到这个基因(突变的概率)。这两种情况加在一起可以得到 `0.99*0.99+0.01*0.01=0.9802`,即 Harry 有 1 个变异基因的概率。 +- 考虑到 Harry 有 1 个变异基因,他没有该性状的概率是 `0.44`(这是 `PROBS["trait"][1][false]`)。因此,哈利有 1 个变异基因而没有该性状的概率是 `0.9802 * 0.44 = 0.431288`。 +- 因此,整个联合概率是三个人中每个人的所有这些数值相乘的结果: `0.9504 * 0.0065 * 0.431288 = 0.0026643247488`。 + +## 提示 + +- 回顾一下,要计算多个事件的联合概率,你可以通过将这些概率相乘来实现。但请记住,对于任何孩子来说,他们拥有一定数量的基因的概率是以他们的父母拥有什么基因为条件的。 diff --git a/4.人工智能/4.3.3不确定性问题.md b/4.人工智能/4.3.3不确定性问题.md new file mode 100644 index 0000000..bbfb314 --- /dev/null +++ b/4.人工智能/4.3.3不确定性问题.md @@ -0,0 +1,1049 @@ +# 不确定性问题 + +- 上一讲中,我们讨论了人工智能如何表示和推导新知识。然而,在现实中,人工智能往往对世界只有部分了解,这给不确定性留下了空间。尽管如此,我们还是希望我们的人工智能在这些情况下做出尽可能好的决定。例如,在预测天气时,人工智能掌握了今天的天气信息,但无法 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})
+ $$
+
+ 的近似概率。
+
+
+
+
+
+- 我们也可以回答涉及条件概率的问题,例如
+ $$
+ P(rain=light|train=on\ {time})
+ $$
+
+ 。在这种情况下,我们忽略 Train 值为 delay 的所有样本,然后照常进行。我们计算在
+ $$
+ Train=\text{on time}
+ $$
+
+ 的样本中有多少样本具有变量
+ $$
+ Rain=light
+ $$
+
+ ,然后除以
+ $$
+ Train=\text{on time}
+ $$
+
+ 的样本总数。
+
+
+
+
+
+去除
+$$
+T= on time
+$$
+
+的样本
+
+
+
+
+
+选择
+$$
+R=light
+$$
+
+的样本
+
+- 在代码中,采样函数可以是 `generate_sample`:
+
+```python
+'''如果你对pomegrante库不熟悉,没有关系,考虑generate_sample为一个黑盒,或者你可以在python解释器中查看model.states, state.distribution的值以了解model在该库中的实现方式'''
+import pomegranate
+from collections import Counter
+def generate_sample():
+ # 随机变量与生成的样本之间的映射
+ sample = {}
+ # 概率分布与样本的映射
+ parents = {}
+ # 为所有状态节点采样
+ for state in model.states:
+ # 如果我们有一个非根节点,则以父节点为条件进行采样
+ if isinstance(state.distribution, pomegranate.ConditionalProbabilityTable):
+ sample[state.name] = state.distribution.sample(parent_values=parents)
+ # 否则,只根据节点的概率分布单独取样
+ else:
+ sample[state.name] = state.distribution.sample()
+ # 追踪映射中的采样值
+ parents[state.distribution] = sample[state.name]
+ # 返回生成的样本
+ return sample
+# 采样
+# 观测到train=delay,计算appointment分布
+N = 10000
+data = []
+# 重复采样10000次
+for i in range(N):
+ # 根据我们之前定义的函数生成一个样本
+ sample = generate_sample()
+ # 如果在该样本中,Train的变量的值为delay,则保存样本。由于我们对给定train=delay的appointment概率分布感兴趣,我们丢弃了train=on time的采样样本。
+ if sample["train"] == "delayed":
+ data.append(sample["appointment"])
+# 计算变量的每个值出现的次数。我们可以稍后通过将结果除以保存的样本总数来进行归一化,以获得变量的近似概率,该概率加起来为1。
+print(Counter(data))
+```
+
+### 似然加权
+
+- 在上面的采样示例中,我们丢弃了与我们所掌握的证据不匹配的样本。这是低效的。解决这一问题的一种方法是使用似然加权,使用以下步骤:
+
+ - 首先固定证据变量的值。
+ - 使用贝叶斯网络中的条件概率对非证据变量进行采样。
+ - 根据其可能性对每个样本进行加权: 所有证据出现的概率。
+- 例如,如果我们观察到
+ $$
+ Train=\text{on time}
+ $$
+
+ ,我们将像之前一样开始采样。我们对给定概率分布的 Rain 值进行采样,然后对 Maintenance 进行采样,但当我们到达 Train 时,我们总是按照观测值取值。然后,我们继续进行,并在给定
+ $$
+ Train=\text{on time}
+ $$
+
+ 的情况下,根据其概率分布对 Appointment 进行采样。既然这个样本存在,我们就根据观察到的变量在给定其采样父变量的情况下的条件概率对其进行加权。也就是说,如果我们采样了 Rain 并得到了 light,然后我们采样了 Maintenance 并得到了 yes,那么我们将用
+ $$
+ P(Train=\text{on time}|light,yes)
+ $$
+
+ 来加权这个样本。
+
+## 马尔科夫模型(Markov Models)
+
+- 到目前为止,我们已经研究了概率问题,给出了我们观察到的一些信息。在这种范式中,时间的维度没有以任何方式表示。然而,许多任务确实依赖于时间维度,例如预测。为了表示时间变量,我们将创建一个新的变量
+ $$
+ X$$,并根据感兴趣的事件对其进行更改,使
+ $$
+
+ X_t
+ $$
+ 是当前事件,
+ $$
+
+ X_{t+1}$$ 是下一个事件,依此类推。为了能够预测未来的事件,我们将使用马尔可夫模型。
+
+### 马尔科夫假设(The Markov Assumption)
+
+- 马尔科夫假设是一个假设,即当前状态只取决于有限的固定数量的先前状态。想想预测天气的任务。在理论上,我们可以使用过去一年的所有数据来预测明天的天气。然而,这是不可行的,一方面是因为这需要计算能力,另一方面是因为可能没有关于基于 365 天前天气的明天天气的条件概率的信息。使用马尔科夫假设,我们限制了我们以前的状态(例如,在预测明天的天气时,我们要考虑多少个以前的日子),从而使这个任务变得可控。这意味着我们可能会得到感兴趣的概率的一个更粗略的近似值,但这往往足以满足我们的需要。此外,我们可以根据最后一个事件的信息来使用马尔可夫模型(例如,根据今天的天气来预测明天的天气)。
+
+### 马尔科夫链(Markov Chain)
+
+- 马尔科夫链是一个随机变量的序列,每个变量的分布都遵循马尔科夫假设。也就是说,链中的每个事件的发生都是基于之前事件的概率。
+- 为了构建马尔可夫链,我们需要一个过渡模型,该模型将根据当前事件的可能值来指定下一个事件的概率分布。
+
+
+
+- 在这个例子中,基于今天是晴天,明天是晴天的概率是 0.8。这是合理的,因为晴天之后更可能是晴天。然而,如果今天是雨天,明天下雨的概率是 0.7,因为雨天更有可能相继出现。使用这个过渡模型,可以对马尔可夫链进行采样。从一天是雨天或晴天开始,然后根据今天的天气,对第二天的晴天或雨天的概率进行采样。然后,根据明天的情况对后天的概率进行采样,以此类推,形成马尔科夫链:
+
+
+
+- 给定这个马尔可夫链,我们现在可以回答诸如“连续四个雨天的概率是多少?”这样的问题。下面是一个如何在代码中实现马尔可夫链的例子:
+
+```python
+from pomegranate import *
+# 定义起始概率
+start = DiscreteDistribution({
+ "sun": 0.5,
+ "rain": 0.5
+})
+# 定义过渡模型
+transitions = ConditionalProbabilityTable([
+ ["sun", "sun", 0.8],
+ ["sun", "rain", 0.2],
+ ["rain", "sun", 0.3],
+ ["rain", "rain", 0.7]
+], [start])
+# 创造马尔科夫链
+model = MarkovChain([start, transitions])
+# 采样50次
+print(model.sample(50))
+```
+
+## 隐马尔科夫模型(Hidden Markov Models)
+
+- 隐马尔科夫模型是一种具有隐藏状态的系统的马尔科夫模型,它产生了一些观察到的事件。这意味着,有时候,人工智能对世界有一些测量,但无法获得世界的精确状态。在这些情况下,世界的状态被称为隐藏状态,而人工智能能够获得的任何数据都是观察结果。下面是一些这方面的例子:
+
+ - 对于一个探索未知领域的机器人来说,隐藏状态是它的位置,而观察是机器人的传感器所记录的数据。
+ - 在语音识别中,隐藏状态是所讲的话语,而观察是音频波形。
+ - 在衡量网站的用户参与度时,隐藏的状态是用户的参与程度,而观察是网站或应用程序的分析。
+- 举个例子。我们的人工智能想要推断天气(隐藏状态),但它只能接触到一个室内摄像头,记录有多少人带了雨伞。这里是我们的传感器模型(sensor model),表示了这些概率:
+
+
+
+- 在这个模型中,如果是晴天,人们很可能不会带伞到大楼。如果是雨天,那么人们就很有可能带伞到大楼来。通过对人们是否带伞的观察,我们可以合理地预测外面的天气情况。
+
+### 传感器马尔科夫假设
+
+- 假设证据变量只取决于相应的状态。例如,对于我们的模型,我们假设人们是否带雨伞去办公室只取决于天气。这不一定反映了完整的事实,因为,比如说,比较自觉的、不喜欢下雨的人可能即使在阳光明媚的时候也会到处带伞,如果我们知道每个人的个性,会给模型增加更多的数据。然而,传感器马尔科夫假设忽略了这些数据,假设只有隐藏状态会影响观察。
+- 隐马尔科夫模型可以用一个有两层的马尔科夫链来表示。上层,变量
+ $$
+ X$$,代表隐藏状态。底层,变量
+ $$
+
+ E$$,代表证据,即我们所拥有的观察。
+
+
+
+- 基于隐马尔科夫模型,可以实现多种任务:
+
+ - 筛选 Filtering: 给定从开始到现在的观察结果,计算出当前状态的概率分布。例如,给从从特定时间开始到今天人们带伞的信息,我们产生一个今天是否下雨的概率分布。
+ - 预测 Prediction: 给定从开始到现在的观察,计算未来状态的概率分布。
+ - 平滑化 Smoothing: 给定从开始到现在的观察,计算过去状态的概率分布。例如,鉴于今天人们带了雨伞,计算昨天下雨的概率。
+ - 最可能的解释 Most likely explanation: 鉴于从开始到现在的观察,计算最可能的事件顺序。
+- 最可能的解释任务可用于语音识别等过程,根据多个波形,人工智能推断出给这些波形带来的最有可能的单词或音节的序列。接下来是一个隐马尔科夫模型的 Python 实现,我们将用于最可能的解释任务:
+
+```python
+from pomegranate import *
+# 每个状态的观测模型
+sun = DiscreteDistribution({
+ "umbrella": 0.2,
+ "no umbrella": 0.8
+})
+rain = DiscreteDistribution({
+ "umbrella": 0.9,
+ "no umbrella": 0.1
+})
+states = [sun, rain]
+# 过渡模型
+transitions = numpy.array(
+ [[0.8, 0.2], # Tomorrow's predictions if today = sun
+ [0.3, 0.7]] # Tomorrow's predictions if today = rain
+)
+# 起始概率
+starts = numpy.array([0.5, 0.5])
+# 建立模型
+model = HiddenMarkovModel.from_matrix(
+ transitions, states, starts,
+ state_names=["sun", "rain"]
+)
+model.bake()
+```
+
+- 请注意,我们的模型同时具有传感器模型和过渡模型。对于隐马尔可夫模型,我们需要这两个模型。在下面的代码片段中,我们看到了人们是否带伞到大楼的观察序列,根据这个序列,我们将运行模型,它将生成并打印出最可能的解释(即最可能带来这种观察模式的天气序列):
+
+```python
+from model import model
+# 观测到的数据
+observations = [
+ "umbrella",
+ "umbrella",
+ "no umbrella",
+ "umbrella",
+ "umbrella",
+ "umbrella",
+ "umbrella",
+ "no umbrella",
+ "no umbrella"
+]
+# 预测隐藏状态
+predictions = model.predict(observations)
+for prediction in predictions:
+ print(model.states[prediction].name)
+```
+
+- 在这种情况下,程序的输出将是 rain,rain,sun,rain,rain,rain,rain,sun,sun。根据我们对人们带伞或不带伞到大楼的观察,这一输出代表了最有可能的天气模式。
diff --git a/4.人工智能/static/AptYbb5MZoylvex7LvPcSqivnef.png b/4.人工智能/static/AptYbb5MZoylvex7LvPcSqivnef.png
new file mode 100644
index 0000000000000000000000000000000000000000..c8e147c0daec15da24d0c540a99efc7a662c7041
GIT binary patch
literal 127216
zcmd3NRaBfo6D0{DxI=IV!QCB(;O_2j!QCM^4DRmk?(V@exV!t{&XRxkf8U4QJ^S*V
z`Ff_ir@E@EyQ=ODlb01kgu{h{fPg@h5EoX2fPg%QfcOjx^Yx>JXWEPr0^&P_gs_0J
zTgK^{tG=?z( ~+uhqp9d8@9Mb^7(rmkA_{uT79>@UEa RYaIMdsLX{cI=q45iJ{Bd=?46xpA&fv!Gb#c`W~$0<|Q-5Flp7aZRW
zcOrNxO^5R)6m}D_dk14X&ev7tpM#xd_zFDJTwX~}T11P{U7xtA E5GYxi%mLv{A0ARY=XE{I&H02K}$ELS3ZMT>slAk05?P=f5ME5C325GLwCR2l@GPXjIgY
z6}#T}6%6q)6E;GHMtxCbcy9`mQH^G$wGIMt8$ze{qgkS
z+_Fw;`C~+Hd$JPG?^SK}v-jWNO&t*v_sB5zu;fj
knj#HBQtLX#~6)gsl%BKlQ8%gHMTIZN;
z)czKQSmixq5dGa2M&*=;&+TjQoEBB3-o`yqFJp1IBJ;
I!|QX9FygOr*`pDB(i`hm_Y--1l=6tjq=wM-F1mA0?x4_Tw<;gx|R=3oNqDi
zctyB*(Y(Xy*7J)bXPY4^O;jTB&Z%GndLpdX%RAZwwq2BW%7xlHQGBOm@yOwk%QfWc
z!#3`IakD;Q#=+jIuV?mG61${?>Q?KAO0RfwAzMLhG_;ev_*k}c=TT0lV{29AIb>Z-
z*KW_&!Ai1Myx8&36hGhBBNokXCrZ9C1v;Tk`jbY!+Y+NEX4Am1OCN8rjaAwTm*T1i
zD&EoRX6`RKxh?rP(lfyZH51Q`gEO)v#H6xP!kL!)Ngq1wrN5|L&j8ae$H%W6@ET+M
zJJ1$?;6dc1^CD*7Kk&Rs{TY++~wM^m=LNc>|SFVaMVjN!8*B2TlPTOaodjlT>d{*g2vq>jZ=
z{4Dt`4_U3lU)}rDenm@8&30QL6T$M!h84vfJr2w9x5QDO9@P}!jBUPD7-wv=2pnA^
zwq5QnCPeyk%Pjk)h(jd2
j^KLF~#PHDmi}T;Vrs@JT1c>{Zx66jFb~MQt!AF`W9<{
z`P&@fnpsI#UB4w4Pqqt_kD>R?mRZS^UauQdQihcku9YZnmOD3(aeUJck9hB9Tyq-G
zpgCUnU2b{^ixe)2d`@CB)hjL}mg@teix!$Bm6DdK9)*@