博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《树莓派开发实战(第2版)》——2.3 使用基本构件:原子元素
阅读量:6638 次
发布时间:2019-06-25

本文共 4445 字,大约阅读时间需要 14 分钟。

本节书摘来异步社区《概率编程实战》一书中的第2章,第2.3节,作者:【美】Avi Pfeffer(艾维·费弗),更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.3 使用基本构件:原子元素

现在正是积累Figaro元素知识的时机。我将首先介绍模型的基本构件——原子元素。原子这一名称意味着,它们不依赖于任何其他元素,完全是独立的。在此我不提供完整的原子元素列表,只介绍最常见的例子。

原子元素根据值的类型分为离散元素和连续元素。离散原子元素取Boolean和Integer等类型的值,而连续原子元素通常使用Double类型的值。从技术上说,离散意味着值之间有很清晰的分隔。例如,整数1和2有很清晰的分隔,其中没有任何整数。而连续意味着值处于一个没有分隔的连续域中,如实数。在任何两个实数之间都有更多的实数。离散和连续元素之间的差异造成了概率定义的差异,第4章中将做介绍。

有些人认为离散就意味着有限。这是错误的。例如,整数有无穷多个,但是它们是清晰分隔的,所以是离散值。

关键定义
原子元素——不依赖于任何其他元素的独立元素。

复合元素——由其他元素构成的元素。

离散元素——值类型清晰分隔的元素。

连续元素——值类型没有分隔的元素。

2.3.1 离散原子元素

让我们来看一些离散原子元素的例子:Flip、Select和Binomial。

Flip

您已经看到了离散原子元素Flip。Flip包含在com.cra.figaro.language包中,该包中有许多最常用的元素。我建议始终在程序开始处导入该包的所有内容。一般来说,Flip取一个参数p,表示元素值为真的概率。p应该是0和1(包含)之间的数值。该元素值为假的概率是1-p。例如:

import com.cra.figaro.language._val sunnyToday = Flip(0.2)println(VariableElimination.probability(sunnyToday, true))// prints 0.2println(VariableElimination.probability(sunnyToday, false))// prints 0.8```Flip(0.2)的正式类型是AtomicFlip,是Element[Boolean]的子类。这使其区别于后面将会看到的CompoundFlip。Select您已经在Hello World程序中看到了Select元素。下面是一个例子:``Select(0.6 -> "Hello, world!", 0.3 -> "Howdy, universe!", 0.1 -> "Oh no, not again")``。图2-5展示了这个元素的构成。在圆括号中是一些子句。每个子句由一个概率、一个右箭头和一个可能结果组成。子句的数量是可变的,您可以使用任意个子句。图中有3个子句。因为所有结果的类型都是String,所以这个元素是Element[String]。同样,其正式类型是AtomicSelect[String]——Element[String]的子类。
很自然,Select元素对应于一个过程,其中每个可能的结果按照对应的概率而选择。下面是其工作方式:

val greeting = Select(0.6 -> "Hello, world!", 0.3 -> "Howdy, universe!", 0.1

-> "Oh no, not again")

println(VariableElimination.probability(greeting, "Howdy, universe!"))

// prints 0.30000000000000004`
注意,在Select中,概率累加起来不一定等于1。如果它们加起来不等于1,概率将被规格化——加起来等于1,同时保持概率之间的比例。在下面的例子中,每个概率都等于前一个例子中的两倍,因此加总起来等于2。规格化之后恢复成前一个例子中的概率,因此得到相同的结果。

val greeting = Select(1.2 -> "Hello, world!", 0.6 -> "Howdy, universe!", 0.2     -> "Oh no, not again")println(VariableElimination.probability(greeting, "Howdy, universe!"))//prints 0.30000000000000004Binomial

Binomial是一个有用的离散元素。想象一下一周有7天,每天都有一个“晴天”元素Flip(0.2)。现在您想要一个元素,其值为一周中放晴的天数。这可以用元素Binomial(7, 0.2)实现。这个元素的值是总共尝试7次,每次尝试为true的概率为0.2的情况下,尝试结果为true的次数。可以这样使用它:

import com.cra.figaro.library.atomic.discrete.Binomialval numSunnyDaysInWeek = Binomial(7, 0.2)   println(VariableElimination.probability(numSunnyDaysInWeek, 3))//prints 0.114688```一般来说,Binomial取两个参数:尝试次数和每次尝试得出结果true的概率。Binomial的定义假定所有尝试是独立的,第一次尝试为真不会改变第二次尝试得出true的概率。####2.3.2 连续原子元素本节介绍两个连续原子元素的常见例子——Normal和Uniform。第4章详细说明连续元素。连续概率分布与离散分布略有不同,指定的不是每个值的概率,而是每个值的概率密度,概率密度描述的是以该值为中心的每个区间的概率。您仍然可以将概率密度视为和常规概率类似的概念,表明某个值与其他值可能性的对比。因为本章是Figaro的教程,第4章解释概率模型,我将把进一步的讨论推迟到那个时候。请放心,在后面这一点将会更加清晰。Normal正态分布是您可能熟悉的一种连续概率分布。正态分布还有其他一些名称,包括钟形曲线和高斯分布。图2-6展示了正态分布的概率密度函数。(如果非要吹毛求疵,可能称之为“单变量正态分布”更为合适,因为它定义了单一实数变量上的概率,您还可以在多个变量上定义多变量正态分布,但是我们不是那样的人,所以就称之为正态分布。)这个函数有一个均值——中心点(图中为1),以及一个标准差——函数沿中心点分布的程度(图中为0.5)。大约有68%的情况下,从正态分布生成一个值将得到与均值相差一个标准差的区间内的值。在统计和概率推理中,正态分布通常用均值和方差描述,后者是标准差的平方。图中的标准差为0.5,方差为0.25。因此,这个特定正态分布的标准规格描述是Normal(1,0.25)。
Figaro遵循上述约定。它提供一个Normal元素,以均值和方差作为参数。可以这样定义Normal元素:

import com.cra.figaro.library.atomic.continuous.Normal

val temperature = Normal(40, 100)`
均值为40,方差为100,意味着标准差为10。现在,假定您想要用这一元素进行推理。Figaro的变量消除算法只适用于可能取值个数有限的元素。特别是,它不能用于连续元素。所以,需要一个不同的算法。您将使用称作重要性抽样的算法,这是一种很适合于连续元素的近似算法。算法的运行方法如下:

import com.cra.figaro.algorithm.sampling.Importancedef greaterThan50(d: Double) = d > 50println(Importance.probability(temperature, greaterThan50 _))```重要性抽样是一种每次产生不同答案的随机算法,这些答案通常应该在真值的附近。您得到的答案应该与0.1567接近,但是很有可能得到稍有不同的答案。注意,这里的查询和之前略有不同。对于连续元素,取特定值(如50)的概率通常为0。原因是,连续元素中有无穷多个没有分隔的值。该过程得出50而非50.000000000000001或者之间其他值的可能性无限小。所以,通常不要向连续元素发出特定值概率的查询。相反,您可以查询该值落入某个区间的概率。例子中的查询是预测greaterThan50,这个预测以双精度(Double)类型值作为参数,如果参数大于50则返回true。预测是一个元素值的布尔函数。当您查询某个元素是否满足预测时,询问的是将预测应用到某个元素值返回true的概率。在这个例子中,您的查询计算温度高于50的概率。Scala注释:greaterThan50之后的下划线告诉Scala,greaterThan50是一个传递给Importance. probability方法的函数值。如果没有这个下划线,Scala可能认为您试图将该函数应用到0参数上,从而出错。有时候,Scala可能自动理解这一点而无需明确地提供下划线。但有时候它无法做到,而会告诉您提供下划线。Uniform我们再来介绍一个同样熟悉的连续元素例子。Uniform元素取指定区间中的值,区间中的每个值可能性相同。您可以这样创建和使用Uniform元素:

import com.cra.figaro.library.atomic.continuous.Uniform

val temperature = Uniform(10, 70)
Importance.probability(temperature, greaterThan50 _)
// prints something like 0.3334`
Uniform元素取两个参数:最小值和最大值。从最小值到最大值的所有值概率密度相同。在前一个例子中,最小值为10,最大值为70,所以范围的大小为60。您的查询预测是该值是否在50~70——区间大小为20。所以,预测的概率为20/60或者1/3,可以看到,重要性抽样得到的结果与此接近。

最后说明一下:这个元素的官方名称是连续均匀分布(continuous uniform)。在com.cra.figaro.library.atomic.discrete包中还可以找到离散均匀分布。正如您的预期,离散均匀分布明确列出一组值,其中的每个值出现可能性相同。

好了,现在您已经了解了构件,下面我们来看看如何组合它们,创建更大的模型。

转载地址:http://rxpvo.baihongyu.com/

你可能感兴趣的文章
柱、锥、台、球的体积公式推导(不用积分)
查看>>
jqgrid 中的事件
查看>>
Ubuntu docker Postgresql
查看>>
java使用Arrays.asList快速创建List集合
查看>>
【HDOJ】1260 Tickets
查看>>
sql逻辑查询 理论知识
查看>>
HDU3694 Fermat Point in Quadrangle(求四边形费马点)
查看>>
Swift 之惰性求值
查看>>
vue 打包
查看>>
nodejs 箭头函数
查看>>
学习记录(十三)
查看>>
setTimeout与setInterval的区别浅析
查看>>
存储的基本概念
查看>>
入门训练 Fibonacci数列
查看>>
漂浮广告
查看>>
jQuery - 获取内容和属性
查看>>
C++基础入门
查看>>
字符环
查看>>
mysql 创建备份表 更新数据 查看编码格式
查看>>
oracle死锁的检测查询及处理
查看>>