以前,统计计算主要集中于数值计算。那时的计算机运行速度慢,为了获得合理的性能,人们不得不在一个相对较低水平上细心地编写程序。结果,为了效率,大多数早期的统计系统都是简单的终端机而不是严格的数值算法。使用这些系统的人们需要提交他们的统计需求,然后在当天的晚些时候或者第二天才能拿到结果。
随着计算机变得越来越快,越来越廉价,将以前花费几小时或者几天才能完成的计算工作在几分钟或几秒钟内完成已经成为可能。这种发展对统计软件提出了新的挑战。由于现在的计算机硬件能够在短期内完成不同的计算与分析任务,一个支持性的统计软件环境要使以下步骤变得简单易行——将不同的计算结果展示到计算机上,将一台计算机的计算结果传递到另一台计算机上,检测计算结果,跟踪计算过程。进一步说,随着一些计算流程的重复使用(有可能有细微的变化),将此计算流程作为一个单元来描述和请求调用,建立一个简单的抽象已经成为可能。简而言之,为了补充现代计算机硬件的能力,统计环境必须是一个带有交互能力的统计语言。
另一个重要的发展发生在对计算速度的并行性上。越来越多的统计计算是在配置了高分辨率的个人电脑和工作站上完成的。这类高分辨率显示硬件开拓了很多新的机遇。统计研究的一个最令人激动的领域就是动态计算机绘图领域和它在统计学上的应用。多年以来,绘图方法已经成为统计学上的一个重要工具。但是,传统的二维绘图的一个固有的限制就是它不能很容易地表达超过二维的信息。当代计算机显示器的这项能力——显示一个快速变化的二维图形序列的能力,开拓了一个第三维度:时间维度。动态地变化的图形可能包含几种形式,从在一个旋转的点云里系统地变化,到交互地确定的变化(通过刷新操作,在图形中一个高亮点处的刷新,在其它一些图形里同步地高亮显示)。
很多关于动态绘图显示的有思想的想法在近些年来被提出[20]。但是,为了获得这些思想所有的潜力,为了确定最富有成果的方向,这些新方法需要在更广泛的用户范围内使用,并且在各种环境下测试。大多数至今被提出的动态绘图技术都已经在相应的硬件上实现了,通常都是使用复杂的编程方法。结果,只有很少统计学家能够在实践中探索这些方法的用法,同时仍然很少有人有机会使用这些方法提到的变量进行实验。为了支持这个领域的进展,统计环境需要实现标准动态绘图方法(像点云旋转),并也需要提供基本动态绘图组件集合,可以更容易地和可移植地实现新的想法。
最近的经验表明,一个崭新的编程范式——面向对象编程,对于一般的绘图编程是非常有用的,尤其对统计绘图编程来说。面向对象方法在统计系统里还有很多其他应用。例如可以开发灵活的数据结构,表示统计模型等。
绘图编程工具和面向对象编程只不过是现代统计环境需要的众多特性中的两个而已。其它的特性还包括处理“非标准”统计数据的能力等。标准数据是数字的列表(lists)或集合(collections)形式。大多数的数据可以用这样的集合表示。在线性模型的上下文中,不同的模型也可以使用数字集合(模型系数和预测矩阵)的方式表示。但是一旦这些模型的更加广泛的类被认可的话,那么将很难找到不同模型间的数值表示。例如,一个用于拟合非线性回归模型的系统,如果这个系统需要非线性均值函数,而这个函数选自一些拟合好的数据集的话,这个系统将受到严重的限制。在这个例子中,能够以更一般的方式指定均值函数是很必要的,要么作为一个计算不同参数值的均值函数,要么作为一个表达式。一旦一门语言允许使用这样的非数值数据,很多新的机遇就产生了。例如,让程序检测模型表达式和计算表达式来作为衍生工具,抑或尝试确定一个结构来引出计算和解释上的简单化,类似上边的事情将变得可能。
上节提到的一个灵活的、现代的统计环境一定是嵌入到一个高水平的、可交互的编程语言里的。开发这样的环境可以采取两个办法。第一个办法是从头开始开发一个新的、高水品的语言,这已被S系统(比如S语言、R语言)采用;第二个方法是使用一门现存的语言进行统计计算。推荐最多的是Lisp语言。
Lisp-Stat代表了开发一个完整统计环境的尝试,该环境基于Lisp语言。它由三部分组成:
Lisp-Stat还包含一个面向对象编程系统,用来支持绘图编程和展示统计模型,比如线性和非线性回归模型。
Lisp-Stat不是一个单独的系统或者实现。相反地,它是一些基本要素的集合的规格,这个规格可以使用一个Lisp系统的变种和可视化操作系统来组合实现。在本书写作的时候,已经有一个叫XLISP-STAT的Lisp-Stat环境实现存在了(注:该处的“实现”为对规格/标准的具体实现版本)。这个系统(指XLISP-STAT)基于Lisp方言XLISP,可以在Macintosh系统和X11 可视化操作系统中使用。随着时间的推移,其它的实现可能也会变得可用。在其它可视化操作系统中使用的XLISP-STAT版本正在开发中。有一个Common Lisp版本的Lisp-Stat也正在开发中。
Lisp是一门丰富的、通用的编程语言,是一门理想的适合交互性和实验性的编程语言。它允许将函数作为数据,它具有支持多重编程范式的能力,包括面向对象编程。这些导致我们在计算机科学课程中,使用用Lisp作为介绍基础编程概念的工具,也导致一些论文作者使用和建议将Lisp语言作为统计计算的理想的基础环境。
Lisp事实上是一门非常古老的语言。它是迄今为止仍在使用的第二老的编程语言,仅次于FORTRAN。经过这么多年的Lisp发展处很多方言版本,但是从20世纪80年代早期,Lisp社区已经合流,朝向使用唯一的方言——Common Lisp.很多优秀的Common Lisp系统都已可用,Common Lisp编译器产生的代码在速度上已经与C和FORTRAN代码不相上下。Lisp-Stat系统都开始采用基于Common Lisp方言或其合理分支的方式。
本书中所有Lisp语言方面的信息都在这里描述,最重要的再第3、4两章。但是Lisp语言的很多其它特性都没有描述或者仅是简略提及。如果您想进一步涉猎Lisp语言,有很多可用的优秀的书籍可以参考。Common Lisp语言的定义由Steele给出[文献56].Common Lisp函数的完成文档包含在[文献31]。对Common Lisp语言的两个很好的介绍是Horn[文献67]和Tater[文献59].(注:此处文献请到英文原著中查看。)
还有一些其他语言也被建议作为统计环境的基础。其中一个受到相当大关注的语言是APL。APL有很多有用的特性,包括处理大矩阵和大数组的功能。但是它没有容易处理高级数据的能力,比如函数和表达式,也没有提供自身容易地支持面向对象编程风格的能力,这在绘图编程里是很重要的。将这些特征放到APL里与把矩阵和数组函数放到Lisp里相比是相当难得。
Lisp-Stat系统可以用在很多不同的水平,从基本的统计计算器与绘图器到为一个平台设计统计GUI。本书的组织就是基础贯穿这些等级水平的级数的(可理解为由浅入深)。
第二章描述了如何把Lisp-Stat当做统计计算器和绘图器。在这本层级水平上很多操作都可以使用Lisp-Stat来完成。你可以输入数据,计算汇总统计,生产静态和动态图形,拟合回归模型等等。做这些统计计算的命令如下:
(mean precipitation)
或者像这样
(standard-deviation precipitation)
来计算数据集precipitation的均值和标准方差。这些表达式正好就是Lisp表达式。但这并不是说在使用Lisp-Stat以前,你一定要学习很多Lisp语法。通过学习很少的基本命令,就像任何其它统计系统需要的基本命令一样,几分钟之内你就可以开始分析数据了。
但是有很多优势是由这样的事实导致的——Lisp-Stat的命令就是Lisp表达式。尽管你不需要知道Lisp就可以使用Lisp-Stat,就像你使用其他系统一样你还是要学一些Lisp基础知识。我们已经学习过如何计算均值和标准差,我们需要前进一小步,使用Lisp表达式形式计算一个标准化的变量:
(/ (- precipitation (mean precipitation)) (standard-deviation precipitation))如果你发现你要经常标准化一个变量,那么需要再前进一小步——把这个过程封装到一个函数里,然后定义成下边的样子:
(defun standardize (x) (/ (- precipitation (mean precipitation)) (standard-deviation precipitation)))从使用Lisp-Stat作为一个计算器,到写你自己的函数来自定义系统是一件非常自然的事儿,这将在第二章的最后一节进行概述。
第二章里描述的工具已经很强大了。但是,与仅仅将一些操作组合到一个新函数里相比,你还可以做得更多。使用Lisp编程语言你可以实现新的算法、设计函数来拟合模型的新类别。为了充分利用这项能力,你需要学习Lisp和Lisp-Stat提供的基本的控制结构和函数。第三章介绍了控制结构,像条件评价结构,也描述了一些Lisp编程里经常遇到的编程风格。第四章展示了一些附加的标准lisp函数,第五章描述了Lisp-Stat包含的统计函数。
使用面向对象编程系统,Lisp-Stat绘图和回归模型也得到了实现。第二章给出了对象使用的简单介绍,第六章展示了Lisp-Stat对象系统和隐藏在面向对象范式之后的思想的更详细的介绍。第七章描述了Lisp-Stat对象系统,是Lisp-Stat可视化系统的基础。除了形成了绘图系统的基础之外,可视化系统提供了从Lisp-Stat到GUI工具(菜单、对话框)访问的通道。绘图系统由建立在可视化操作系统之上的两个附加层组成。第一层在第八章里描述,第二层在第九章里展示,包括对绘图数据和标准交互技术的支持。
Lisp-Stat绘图系统可以以很多不同的方式使用。仅使用第二章介绍的工具,简单动画就能很容易地构造出来,例如,一个由滚动条控制的正态概率图形,该滚动条可以交互地改变能量转换模型中的能量。第七章描述的菜单和对话框对象可以用来设计一些图形接口,这些图形接口是针对功能集或者模型工具集的。第8、9章展示的对象和思想,可以用来以辅助的方式自定义标准图形或者完全地开发新的图形类型。第10章展示了一些例子关于可能性范围的说明。
使用Lisp-Stat的一个好的策略是使用键盘交互式地尝试一些表达式。一旦你能够区分一些表达式或者操作的集合,并自然地把它们放在一起,你就可以定义一个新的函数或者新的对象类型,把它们封装在一起。将来的开发中这个新的函数或者对象就能被用来作为基本的组件。这个策略是很有用的,无论你研究一个新的数据对象、一个新的数值技术还是一个新的绘图灵感。通过一系列的探索和封装的步骤,这样的步步为营的能力是交互式统计环境强大的一个关键点,就像Lisp-Stat。
设计Lisp-Stat的普遍目标是开发一个系统,这个系统可以在很多操作系统上交互式地使用。为了达到之一目的,需要做一些设计上的决定和妥协。
用户界面变量
在设计一个可以工作在各种不同计算机上的绘图系统时,一个重要的问题就是用户界面设计上的不同。例如,Macintosh系统的接口通常把菜单放在菜单栏里,而很多其它接口是当鼠标在窗口内点击时才弹出菜单的。为了处理这个问题,我试图依据一些通用惯例来设计Lisp-Stat的绘图系统,将接口的细节留给特定的实现。例如,Lisp-Stat绘图系统建议每个图形都包含一个菜单以方便控制。所有的实现里再从Lisp-Stat内部区别对待这些菜单。每一个特定的实现负责各自的细节,比如何时将彩带展示给用户。在Macintosh系统里,当统计图形窗口是前端窗口时,菜单可能被置于菜单栏内。而对于其它的系统,当在统计图形窗口内点击了特定的鼠标按钮时,菜单栏才会弹出。
只是用一些通用接口特征的优势是写成的Lisp-Stat代码可以运行在装有各种操作系统的计算机之上,劣势是不可能将特定接口提供的所有特性都发挥出来。幸运的是,大多是的GUI都是很相似的,通过提取它们的共同特征几乎没有接口特性的损失。
操作系统变量
无论何时当Lisp-Stat需要与操作系统进行接口通信时,操作系统之间的差异导致了运行其上的Lisp-Stat系统的变量差异。这种差异发生在Lisp-Stat启动和文件获取过程中。每个版本的Lisp-Stat都应该包含如下信息:如何从操作系统启动Lisp-Stat,文件和路径的命名规范。在一些操作系统上,通过Lisp-Stat内部或连接到Lisp-Stat系统的其它语言代码,去调用其它操作系统的命令是可能的。细节上,会因操作系统的不同而不同。
不同的Lisp系统
理想的Lisp-Stat基系统是Common Lisp系统。不幸的是,Common Lisp系统可能很昂贵。一些Common Lisp系统在与一些可用内存量有限的微机和工作站上工作得不是很好。XLISP提供的Common Lisp子集对于支持一个Lisp-Stat系统是足够胜任的。Common Lisp的最重要的特性中,XLISP没有提供的就是编译器。因为XLISP是免费可用的,我们当然也可以制作一个基于XLISP的免费可用的Lisp-Stat版本。
硬件模型
与用户接口模型类似,用于设计Lisp-Stat的硬件模型也是最大化地基于共同特征的。这个模型假定计算机都有一个位图显示器和一个存取设备。该模型不建议拥有任何针对特殊意图的硬件,比如支持深度感知或双缓冲技术的硬件。Lisp-Stat实现可以利用硬件的双缓冲而不改变Lisp-Stat看待硬件的方式,但是一些改变可能需要用到硬件的深度感知功能。这种修改是否值得还有待观察。
Lisp-Stat是一个不断进化的系统。它的目标是为统计计算提供一个环境,这个环境将充分利用当代计算机硬件的计算速度和图形处理能力,通过以下几种手段可以达到此目的:
使用Lisp-Stat的经验和统计方法论与计算机硬件的新发展,这些都会导致系统的修改和功能增加。随着Lisp-Stat的进化,只要可能,新版本就应该会兼容老版本。