天天看点

《树莓派开发实战(第2版)》——1.3 Figaro简介:一种概率编程语言

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

在本书中,您将使用一种称为figaro的概率编程系统。(我用莫扎特的歌剧《费加罗的婚礼》中的角色为其命名。我喜爱莫扎特,并在该剧于波士顿的一次演出中饰演巴尔托洛医生。)本书的主要目标是教授概率编程的原则,在本书中学到的技术应该可以在其他概率编程系统上沿用。附录b简单描述了现有的一些系统。但是,本书还有第二个目标——帮助您获得创建使用概率程序的亲身体验,并提供可以立即使用的工具。因此,许多例子都用figaro代码实现。

figaro是从2009年开始开发的一个开源软件,在github上维护。它以scala库的形式实现。图1-9说明figaro如何使用scala实现概率编程系统。该图详细说明了图1-7,后者描述了概率编程系统的主要组成部分。让我们从概率模型开始,在figaro中,该模型由任意数量的数据结构(称作“元素”)组成。每个元素代表在您的情境中可取任意数量值的一个变量。这些数据结构用scala实现,您可以用这些数据结构编写scala程序创建模型。可以通过关于元素值的信息提供证据,也可以指定希望在查询中了解的元素。至于推理算法,您可以选择一个figaro内建推理算法并应用到模型上,根据证据回答您的查询。推理算法以scala实现,其调用就是一个scala函数调用。推理结果是查询元素不同值的概率。

《树莓派开发实战(第2版)》——1.3 Figaro简介:一种概率编程语言

figaro内嵌于scala提供了一些重大优势。其中一些来自内嵌于通用宿主语言相对于独立概率语言的优势。其他优势则是因为scala的良好特性。下面是在通用宿主语言中内嵌概率编程语言的好处。

证据可以用宿主语言的程序得出。例如,您可以编写一个程序读取一个数据文件,以某种方式处理其中的值,并将其作为证据提供给figaro模型。在独立语言中,这一任务要难得多。

类似地,您可以在一个程序中使用figaro提供的答案。例如,如果您有一个供足球队经理使用的程序,该程序可以取得进球概率,向经理提出建议。

可以在概率程序中嵌入通用代码。例如,假设您有一个模拟头球在空中飞行轨迹的物理模型,可以在figaro元素中加入这个模型。

可以使用通用编程技术构建figaro模型。例如,您可能有一个映射,包含对应于球队中所有球员的figaro元素,并根据情况中涉及的球员选择对应的元素。

下面是选择scala作为内嵌概率编程系统的宿主语言的一些理由。

scala是一个函数式编程语言,因此figaro也能得到函数式编程的好处。正如我在第2部分中所说明的,函数式编程对概率编程有帮助,许多模型可以自然地以函数式风格编写。

scala是面向对象的,其优点之一是既是函数式语言,又具有面向对象的特征。figaro也是面向对象的。正如第2部分中将要说明的,面向对象是表达概率编程中多种设计模式的有用手段。

最后,figaro还有嵌入scala之外的一些优势,包括:

figaro能够表示极其广泛的概率模型。figaro元素的值可以为任何类型,包括布尔型、整数、双精度数、数组、树、图等。这些元素之间的关系可以由任何函数定义。

figaro提供了使用其条件和约束规定证据的丰富框架。

figaro有多种多样的推理算法。

figaro能够表示和推理随时间变化的动态模型。

figaro能够在其模型中包含明确决策,并支持最优决策的推断。

由于多种原因,figaro是学习概率编程的出色语言。

figaro以scala库的形式实现,可以用于java和scala程序,很容易与应用程序集成。

由于以程序库而非独立语言的形式实现,figaro提供了宿主编程语言的全部功能,可以用来构建模型。scala是高级的现代化语言,具有许多有用的程序组织功能,使用figaro时可以自动获得这些好处。

从所提供算法的范围来看,figaro 堪称全能。

本书强调使用的技术和实用的示例。只要有可能,我都会解释建模的一般原则,并描述在figaro中的实现方法。不管您最终使用哪一种概率编程系统,这对您都将大有裨益。并不是所有系统都能轻松地实现本书中的所有技术。例如,现有的面向对象概率编程系统很少。但是有了好的基础,您就可以找出用所选语言表达需求的方法。

使用scala

因为figaro是一个scala库,需要scala的知识才能使用figaro。本书是关于概率编程的,所以在本书中不教授scala的知识。scala的出色学习资源很多,比如twitter的scala school。但是为了防止您对scala不自信,我在本书中对代码中使用的scala功能加以说明。即使您还不了解scala,也能够跟上本书的进度。

从概率编程和figaro中获益并不要求您是一位scala奇才,在本书中也避免使用一些较为高级和晦涩的特性。但是,增强scala技能有助于成为更好的figaro程序员。您甚至会发现,阅读本书也可以提高scala的技能。

figaro与java的对比:构建简单的概率编程系统

为了说明概率编程和figaro的好处,我将展示以两种方式编写的简单概率应用。首先,我说明用java(您可能对它很熟悉)编写这种应用的方法。然后,我将展示用figaro编写的scala应用。尽管scala相对java有一定的优势,但是这不是我要指出的主要差别。关键的思路是,figaro提供了表示概率模型和用这些模型进行推理的能力,如果没有概率编程,这些能力就不存在。

我们的小应用将作为figaro的“hello,world”示例。想象一下,有个人早上起床,查看天气是否晴朗,并根据天气发出问候。每天发出连续两天的问候。而且,第二天的天气取决于第一天:如果第一天是晴天,第二天就更可能是晴天。这些陈述可以由表1-1中的数字量化。

《树莓派开发实战(第2版)》——1.3 Figaro简介:一种概率编程语言

下面几章将明确解释这些数字的含义。现在,我们直观地认为今天是晴天的概率为0.2,也就是说,今天有20%的可能放晴。同样,如果明天是晴天,明天的问候语为“hello, world!”的概率为0.6,也就是说问候语为“hello, world!”有60%的可能性,“howdy, universe!”的可能性为40%。

我们为自己设定了用这个模型执行3种推理任务的目标。在1.1.3小节中您已经知道,用概率模型能够进行3类推理:预测未来,推断导致观测结果的过去事件,从过去事件中学习以更好地预测未来。您将用我们的简单模型完成这三种任务。具体任务如下。

1.预测今天的问候语。

2.如果观测发现今天的问候语是“hello, world!”,推断今天是不是晴天。

3.从今天对问候语是“hello, world!”这一观测值的学习,预测明天的问候语。

下面是用java完成这些任务的方法。

程序清单1-1 用java实现的hello world 程序

import com.cra.figaro.language.{flip, select}

import com.cra.figaro.library.compound.if

import com.cra.figaro.algorithm.factored.variableelimination ◁——● //导入figaro结构

object helloworld {

val sunnytoday = flip(0.2)

val greetingtoday = if(sunnytoday,

val sunnytomorrow = if(sunnytoday, flip(0.8), flip(0.05))

val greetingtomorrow = if(sunnytomorrow,

def predict() { ◁——● //用推理算法预测今天的问候语

}

}<code>`</code>

我将等到下一章才详细解释这段代码。现在,我希望指出,它解决了java代码的两个问题。首先,模型定义准确描述了对应于表1-1的模型结构。您定义了4个变量:sunnytoday、greetingtoday、sunnytomorrow和greetingtomorrow,它们都对应于表1-1。例如,greetingtoday的定义如下: