作用及R语言实现

2024-05-23

作用及R语言实现(精选4篇)

作用及R语言实现 篇1

近年来,随着人们对统计数据的关注度越来越强,对统计数据的质量要求也越来越高。提升统计数据质量,其中之一要关注统计数据中的异常值。所谓异常值,是指样本中的个别观测值,其数值明显偏离它所属样本的其余观测值,分析其产生的原因,从而能更好的利用统计数据和保证统计数据质量。目前很多文章从统计理论和统计模型角度探讨识别统计数据异常值,从统计图形的角度探讨识别统计数据异常值的文章少见;在统计软件方面,常用的统计软件有SPSS、SAS、STAT、R、S-PLUS等,R软件是一个自由、免费、开源的软件,是一个具有强大统计分析功能和优秀统计制图功能的统计软件,已成为国内外众多统计学者喜爱的数据分析工具。笔者基于R语言基础,结合具体实例,说明箱须图在识别统计数据中有异常值的作用。

一、箱须图

箱须图(Box-whisker Plot)也称箱线图(Boxplot),在箱线图中,上(Q3)下(Q1)四分位数分别确定出中间箱体的顶部和底部。箱体中间的粗线是中位数(me)所在的位置。由箱体向上下伸出的垂直部分称为”触须”,表示数据的散步范围,最远点为1.5倍四分位数间距。超出此范围的点称为异常值点,异常值点用”o”号表示。是利用数据中的五个统计量:最小值、第一四分位数、中位数、第三四分位数与最大值来描述数据的一种方法,它也可以粗略地看出数据是否具有有对称性,分布的分散程度等信息,特别的能直观明了地识别数据批中的异常值;一批数据中的异常值值得关注,忽视异常值的存在是十分危险的,不加剔除地把异常值包括进数据的计算分析过程中,对结果会带来不良影响;重视异常值的出现,分析其产生的原因,常常成为发现问题进而改进决策的契机。箱线图为我们提供了识别异常值的一个标准:异常值被定义为小于Q1-1.5IQR或大于Q3+1.5IQR的值。虽然这种标准有点任意性,但它来源于经验判断,经验表明它在处理需要特别注意的数据方面表现不错。这与识别异常值的经典方法有些不同。众所周知,基于正态分布的3σ法则或z分数方法是以假定数据服从正态分布为前提的,但实际数据往往并不严格服从正态分布。它们判断异常值的标准是以计算数据批的均值和标准差为基础的,而均值和标准差的耐抗性极小,异常值本身会对它们产生较大影响,这样产生的异常值个数不会多于总数0.7%。显然,应用这种方法于非正态分布数据中判断异常值,其有效性是有限的。箱线图的绘制依靠实际数据,不需要事先假定数据服从特定的分布形式,没有对数据作任何限制性要求,它只是真实直观地表现数据形状的本来面貌;另一方面,箱线图判断异常值的标准以四分位数和四分位距为基础,四分位数具有一定的耐抗性,多达25%的数据可以变得任意远而不会很大地扰动四分位数,所以异常值不能对这个标准施加影响,箱线图识别异常值的结果比较客观。由此可见,箱线图在识别异常值方面有一定的优越性。

二、基于R语言的箱须图程序

在R软件中,用boxplot()函数作箱线图

其中x是由数据构成的数值型向量,或者是列表,或者是数据框;range是”触须”的范围(默认值为1.5),若规定range=0则”触须”包含所有的值;notch是逻辑变量,当notch=TRUE(默认值为FALSE)时,画出的箱线图带有切口;outline是逻辑变量,当outline=FALSE(默认值是TRUE)时,不标明异常值点;col是颜色变量,赋给不同的值,将绘出不同颜色的箱线图;horizontal是逻辑变量,当horizontal=TRUE(默认值为FALSE)时,将把箱线图绘成水平状;add是逻辑变量,当add=TRUE时,在原图上画图,否则替换上一张图。

三、应用举例

统计数据如下表,请识别出统计数据的异常值。

元/人

数据来源:《2009年山东统计年鉴》

程序如下

分析图形如下:

结合统计数据表,从上面的箱须图可以看出,异常值点是潍坊市城镇居民居住消费支出人均1327.72元、济南市城镇居民交通通讯消费支出人均634.83元、威海市城镇居民医疗保健消费支出人均444.31元,其中最显著的异常值点是潍坊市城镇居民居住消费支出人均1327.72元。

参考文献

[1]庄作钦.Boxplot——描述统计的一个简便工具[J].统计教育,2003(1)

[2]汤银才.R语言与统计分析[M].北京:高等教育出版社,2008

[3]薛毅,陈立萍.统计建模与R软件[M].北京:清华大学出版社,2009数据来源:《2009年山东统计年鉴》

推荐系统简介及其R语言实现 篇2

关键词:推荐,R语言

1 推荐系统出现的背景

互联网的出现和普及为用户带来了大量的信息, 满足了用户在信息时代对信息的需求, 但随着网络的迅速发展而带来的网上信息量的大幅增长, 也使得用户在面对大量信息时无法从中获得对自己真正有用的那部分信息, 传统的搜索算法只能呈现给所有用户一样的排序结果, 无法针对不同用户的兴趣爱好提供相应的信息反馈服务。信息的爆炸使得信息的利用率反而降低, 这就是所谓的信息过载问题。

解决信息过载问题一个非常有潜力的办法是推荐系统, 它是根据用户的信息需求、兴趣等, 将用户感兴趣的信息、产品等推荐给用户的个性化信息推荐系统。和搜索引擎相比, 个性化推荐系统通过建立用户与信息产品之间的二元关系, 利用已有的选择过程或相似性关系挖掘每个用户潜在感兴趣的对象, 进而进行个性化推荐, 从而引导用户发现自己的信息需求。推荐问题从根本上说是代替用户评估它从未看过的产品, 这些产品包括书、电影、CD、网页、甚至可以是饭店、音乐、绘画等等。一个好的推荐系统不仅能为用户提供个性化的服务, 还能通过提供良好的服务, 与用户之间建立密切关系, 增加用户的粘性。

推荐系统有三个重要的模块:用户模块、推荐对象模块、推荐算法模块。通用的推荐系统模型流程如图1所示。推荐系统把用户模型中的兴趣需求信息和推荐对象模型中的特征信息匹配, 同时使用相应的推荐算法进行计算筛选, 找到用户可能感兴趣的推荐对象, 然后推荐给用户。

2 推荐系统的分类

根据推荐系统中推荐算法的不同, 推荐系统主要分为以下三种。

2.1 基于内容的推荐

基于内容的推荐 (Content-based Recommendation) 是信息过滤技术的延续与发展, 它是在项目的内容信息上作出推荐, 而不需要用户对项目的评价意见, 更多地需要用机器学习的方法从关于内容特征描述的事例中得到用户的兴趣资料。在基于内容的推荐系统中, 项目或对象 (item) 是通过相关特征的属性来定义, 系统基于评价对象的特征, 学习用户的兴趣, 考察用户资料与待预测项目 (item) 的相匹配程度。用户的资料模型取决于所用学习方法, 常用的有决策树、神经网络和基于向量的表示方法等。基于内容的用户资料是需要有用户的历史数据, 用户资料模型可能随着用户的偏好改变而发生变化。

基于内容推荐方法的优点是:

1) 不需要其它用户的数据, 没有“冷启动”问题和稀疏问题;

2) 能为具有特殊兴趣爱好的用户进行推荐;

3) 能推荐新的或不是很流行的项目, 没有新项目问题;

4) 通过列出推荐项目的内容特征, 可以解释为什么推荐那些项目;

5) 已有比较好的技术, 如关于分类学习方面的技术已相当成熟;

6) 对用户兴趣可以很好的建模, 并通过对物品属性维度的增加, 获得更好的推荐精度。

缺点是:

1) 要求内容物品能容易抽取成有意义的特征, 要求特征内容有良好的结构性, 并且用户的口味必须能够用内容特征形式来表达;

2) 物品的属性有限, 很难有效的得到更多数据;

3) 物品相似度的衡量标准只考虑到了物品本身, 有一定的片面性;

4) 如果两个不同的产品恰好用相同的特征词表示, 这两个产品就无法区分。

2.2 协同过滤推荐

协同过滤推荐 (Collaborative Filtering Recommendation) 技术是推荐系统中应用最早和最为成功的技术之一, 是第一代被提出并得到广泛应用的推荐系统。如Amazon的书籍推荐, Jester的笑话推荐等等。它一般采用最近邻技术, 利用用户的历史喜好信息计算用户或物品 (item) 之间的距离, 然后利用目标用户的最近邻居用户对物品评价的加权评价值来预测目标用户对特定物品的喜好程度, 系统从而根据这一喜好程度来对目标用户进行推荐。协同过滤最大优点是对推荐对象没有特殊的要求, 能处理非结构化的复杂对象, 如音乐、电影等。

协同过滤是基于这样的假设:为一用户找到他真正感兴趣的内容的好方法是首先找到与此用户有相似兴趣的其他用户, 然后将他们感兴趣的内容推荐给此用户。其基本思想非常易于理解, 在日常生活中, 我们往往会利用好朋友的推荐来进行一些选择。协同过滤正是把这一思想运用到互联网推荐系统中来, 基于其他用户对某一内容的评价来向目标用户进行推荐。

基于协同过滤的推荐系统可以说是从用户的角度来进行相应推荐的, 而且是自动的, 即用户获得的推荐是系统从购买模式或浏览行为等隐式获得的, 不需要用户主动提供自己感兴趣的推荐信息, 如填写一些调查表格等。

和基于内容的过滤方法相比, 协同过滤具有如下的优点:

1) 它不需要对物品或者用户进行严格的建模, 而且不要求物品的描述是机器可理解的, 所以这种方法也是领域无关的, 能够过滤难以进行机器自动内容分析的信息, 如艺术品, 音乐等;

2) 共享其他人的经验, 避免了内容分析的不完全和不精确, 并且能够基于一些复杂的、难以表述的概念 (如信息质量、个人品味) 进行过滤;

3) 有推荐新信息的能力。可以发现内容上完全不相似的信息, 用户对推荐信息的内容事先是预料不到的。这也是协同过滤和基于内容的过滤一个较大的差别, 基于内容的过滤推荐很多都是用户本来就熟悉的内容, 而协同过滤可以发现用户潜在的但自己尚未发现的兴趣偏好;

4) 能够有效的使用其他相似用户的反馈信息。较少用户的反馈量, 加快个性化学习的速度;

5) 这种方法计算出来的推荐是开放的, 可以共用他人的经验, 很好的支持用户发现潜在的兴趣偏好。

协同过滤的缺点是:

1) 方法的核心是基于历史数据, 所以对新物品和新用户都有“冷启动”的问题;

2) 推荐的效果依赖于用户历史偏好数据的多少和准确性;

3) 在大部分的实现中, 用户历史偏好是用稀疏矩阵进行存储的, 而稀疏矩阵上的计算有些明显的问题, 包括可能少部分人的错误偏好会对推荐的准确度有很大的影响等等;

4) 对于一些特殊品味的用户不能给予很好的推荐;

5) 由于以历史数据为基础, 抓取和建模用户的偏好后, 很难修改或者根据用户的使用演变, 从而导致这个方法不够灵活。

协同过滤系统的关键在于相似度的计算, 根据相似度计算对象的不同, 又分为基于用户的协同过滤系统和基于内容的协同过滤系统。在计算相似度时, 大部分都是基于用户对内容的评分矩阵, 最常用的相似度计算方法是Pearson相关性和夹角余弦。

2.3 组合推荐

由于各种推荐方法都有优缺点, 所以在实际中, 组合推荐 (Hybrid Recommendation) 经常被采用。研究和应用最多的是内容推荐和协同过滤推荐的组合。最简单的做法就是分别用基于内容的推荐方法和协同过滤推荐方法去产生一个推荐预测结果, 然后用某方法组合其结果。

因为基于用户的协同过滤系统和基于内容的协同过滤系统的不同之处在于相似度计算的对象不同, 体现在数学表达式上则是评分矩阵行列的转置, 基于内容的推荐方法与基于内容的协同过滤系统区别主要在于前者的评分矩阵式人工标注, 后者是基于用户行为的记录。因此, 以下将以基于内容的协同过滤系统为例进行介绍。

3 基于内容的协同过滤系统的R语言实现

3.1 用K近邻的方法自行编写R代码

假设用户—内容的评分矩阵为rating_matrix, 矩阵的行对应于各个用户对各个内容item的评分值。为减少用户反馈难度, 考虑最简单的情况, 一般取值为二进制评分, 用户喜欢为1, 一般对应用户选用了该内容item;不喜欢为0, 一般对应用户没有选用该内容item。矩阵的列对应于各个内容item在各个用户处获得的评分。以一个电影推荐系统的评分矩阵为例, 则其第一列是用户ID, 第一行是各个电影item的ID, 第i行j列的分x, 则代表第i个用户对第j部电影的评分为x, 如果第i个用户选取看了第j部电影, 则对应的评分rating.matrix[i, j]=1, 否则为0。

首先将用户ID和内容ID分别存入row.names和row.names向量:

采用R语言自行编写推荐系统代码, 优点是可以根据具体应用灵活调整推荐算法及参数, 缺点是代码相对更复杂。

3.2 采用R语言中的推荐工具包Recommender

r<-Recommender (data, method, parameter)

生成推荐模型r, 其中data为评分矩阵, method为推荐算法, 包括随机模型 (random items) , 流行模型 (popular items) , 基于用户的协同过滤 (user-based CF) 和基于内容的协同过滤 (item-based CF) 。

采用R语言中的推荐工具包Recommender的优点是代码简洁, 缺点是算法调整不灵活。

4 结束语

个性化推荐是解决信息过载、提高用户使用满意度的有效手段, 本文对推荐系统及其主要分类进行了简介, 并对R语言环境下的代码实现进行了分析介绍。随着电信运营向互联网的转型逐渐深入, 推荐系统在诸如IPTV、运营商电商网站等方面将会得到更大的发展。

参考文献

[1]Dietmar Jannach.Recommendation Systems.蒋凡等译.推荐系统[M].北京:人民邮电出版社, 2013.

[2]李明.R语言与网站分析[M].北京:机械工业出版社, 2014.

[3]Drew Conway, John Myles White.陈开江, 刘逸哲等译.机器学习:实用案例解析[M].北京:机械工业出版社, 2014.

[4]recommenderlab:A Framework for Developing and Testing Recommendation Algorithms.http://cran.r-project.org/

作用及R语言实现 篇3

1 国内外研究进展

1. 1 流处理技术

流处理( stream processing) 是一个比较宽泛的概念。在大数据领域,流处理指的是对在线数据进行实时分析的技术。流处理的概念是相对于批处理而提出的。批处理和流处理主要具有以下不同: 在数据上,批处理分析的是离线数据,单次作业的数据集规模基本不变; 而流处理分析的是在线数据,时刻有新的数据提交给处理程序。在实时性上,批处理作业一次可能需要几个小时或者更长时间来完成;而流处理程序对新数据从接收到完成处理再到做出响应必须控制在分钟级或者秒级以内。

目前比较有代表性的分布式流处理系统包括MapReduce Online[1]、Spark Streaming[2]、Storm[3]、S4[4]等。MapReduce Online基于Hadoop实现,可以复用Hadoop的现有软件栈,但是由于Hadoop计算时延较大,所以MapReduce Online性能不高。Spark Streaming将在1. 2 节介绍。Storm由Twitter公司开发,性能卓越,支持事务型计算,因而得到了广泛应用,却存在部署困难,学习成本较高的问题。S4 采用去中心的架构设计,可以实现高吞吐率和低延迟,但是由于在传递保证等方面的不足,限制了它的使用场景。

1. 2 Spark Streaming

Spark[5]是加州大学伯克利分校AMPLab实验室开发的一个大数据计算框架,支持MapReduce计算范式[1]。Spark借鉴函数式编程的思想,提出了弹性分布式数据数据集( resilient distributed datasets,RDD) ,充分利用内存计算技术,具有极高的计算性能。Spark是目前最活跃的大数据开源项目之一,围绕Spark已经形成了一个完整而活跃的生态系统[7]。

Spark Streaming是在Spark基础上( Spark的核心计算框架称为Spark Core) 开发的流处理框架。它的设计思想是把流处理过程分成一个个时间片,每个时间片接收到的数据( RDD) 组合成DStream对象,DStream对象最终交由Spark Core来计算。Spark Streaming的这种设计思路可以充分复用Spark Core系统的代码,使得Spark Streaming的实现比较轻量,可维护性更强。当然这种设计也使得Spark Streaming的延时只能精确到秒级,略逊于Storm等系统,但是对于大多数的应用场景来说,这样的延时性是够用的。

Spark使用Scala语言编写。Scala编程语言融合了函数式编程和指令式编程两种编程范式,在语言层面引入了基于ACTOR模型的并发框架、高阶函数、惰性计算等高级特性。这些特性使得Spark的开发者受益,但是对于Spark的使用者而言却增加了不小的学习成本。为了提高Spark的易用性,Spark开发了它的Python语言绑定Py Spark[8]和R语言前端SparkR[7]。

1. 3 R语言

R语言[9]是主要应用于统计分析的编程语言。R语言最早由统计学家开发,它的语法规则和惯用编程方式天然地契合了统计和数据分析领域用户的使用习惯。R语言自带了常用的统计分析函数和程序包,并通过CRAN汇聚了超过6000 款第三方程序包,这使得大多数的统计和数据分析问题都能找到相应的R语言程序包。R语言成为了统计和数据分析领域最主流的编程语言之一。

然而R语言本身也存在一些问题。R语言程序处理数据的规模不能超过进程所在的计算机系统的内存容量,这限制了R语言能够处理的数据规模。R语言解释器是单线程模型,这使得R语言的并行计算能力偏弱。为了提高R语言的大数据处理能力,出现过若干解决办法。snow等CRAN程序包尝试改善R语言本身的并行计算能力[10],但因为R语言设计的缺陷而具有很大的局限性。 RHadoop[11]让R语言程序运行在Hadoop集群上,以此来提高程序的运行性能。这种让R语言和分布式计算框架或系统结合的做法虽然实现比较复杂,但是可以取得较大性能提升,因此本文采用的就是这一种做法。

2 系统设计与实现

2. 1 系统总体设计

本文实现的分布式流处理系统采用分层设计模式( 图1) ,自底向上分别是Spark层、中间层和用户代码层。

Spark位于系统的最底层,通过Spark Streaming为系统提供了可靠而高效的分布式流处理能力,从而让设计和实现工作聚焦在R语言的支持上。Spark基于Master-slave的并发模型实现。在此模型之下,集群中的主机分为一个主节点和若干个从节点。主节点,或称驱动节点,负责集群的任务调度、资源分配和系统监控等工作; 从节点,或称计算节点,负责处理主节点下发的具体计算任务并把处理结果返回给主节点。

中间层( 图1 Layer 2) 实现系统对于R语言的支持,即让R语言编写的流处理程序能够运行在Spark分布式计算集群上。为了实现这一功能,本文提出了R/Java的跨语言双向交互机制( 见2. 2节) ,通过对Spark Streaming的流处理相关API进行封装,提供了对应API的R语言版本。这一层是本文的工作重点。

用户代码层是用户编写面向具体问题的R语言流处理程序。在这一层,用户以和普通的R语言函数相同的方式使用中间层提供的R语言函数,就可以编写出可以运行在Spark集群上的分布式流处理程序。用户程序只需思考针对具体问题的数据处理过程,而无需关心与分布式计算有关的繁琐细节。

2. 2 R / Java跨语言交互模型

Spark主要使用Scala语言开发。和Java编写的程序一样,Scala编写的程序运行在Java虚拟机上,可以和Java语言程序直接交互( 由于这层特性,在下文中将不再专门区分Scala和Java,统称Java) 。R语言是通过R语言解释器运行的脚本语言,通常情况下不能直接运行在Java虚拟机上。为了使R语言程序能够运行在Spark上,则需要实现一个R/Java的跨语言交互模型,让R语言代码和Java语言代码能够自由地相互调用。

一种编程语言的代码调用另一种编程语言的代码称为互操作。一般情况下,R和Java没有直接互操作的能力。但是,Java语言支持通过JNI与C / C + + 代码进行交互,R语言可以使用. Call和. External函数和C / C + + 代码进行交互。由此可以考虑以C /C ++ 语言为媒介实现Java语言和R语言的间接的互操作( 图2) 。然而这种做法需要编写大量的C /C ++ 代码,导致编程复杂度上升,可移植性变差,可维护性下降。r Java[12]采用图2 的设计实现了R语言和Java语言的交互,它通过封装C /C + +代码并提供R语言API的方式降低了编程难度,但是存在版本陈旧、接口设计较差等可用性的问题。因此本文中没有采用基于互操作的实现方式。

经过研究Py4J[13]、SparkR等程序的实现原理,本文提出了如图3 所示的R/Java跨语言双向交互模型,但是包含了“R对Java方法调用”( 见2. 2. 1节) 及“Java对R函数调用”( 见2. 2. 2 节) 两个方面,比SparkR中的跨语言交互模型更加完整。

该模型由三个单元构成,分别是R-side、J-side和R-Worker。R-side单元面向用户编写的R语言程序,把R语言代码转化为对Spark系统的API访问。J-side单元与Spark系统相对接,调用Spark Streaming的Java API以使用分布式流处理功能。R-side单元和J-side单元工作在Spark集群的主节点上,而R-worker单元则工作在Spark集群的从节点上,它的作用是辅助执行从节点上的计算任务。三个单元相互配合完成R语言和Java语言代码的交互,沟通了用户代码层和Spark层( 图1) ,从而使得用户编写的R语言程序能够工作在运行于Java平台的Spark集群上。

图4 是一段不严格的R语言代码,以#号开始的行是注释,每行第一列的数字是行号。下面将以这一段示例代码详细介绍R/Java跨语言交互模型的工作原理。

2. 2. 1 R对Java方法调用

用户代码访问Spark Streaming的API,从而具备在Spark集群上运行分布式流处理程序的能力。用户代码使用R语言编写,而Spark Streaming API是Java语言的,用户代码运行在Spark集群上就会有R对Java方法调用的过程。比如在图4 中,第3行代码创建了一个类型为Class T的Java对象x,在第4 行代码调用了x的方法method A得到计算结果r1。

本文提出的R/Java跨语言交互模型采用“双进程+ SOCKET”的方式来实现R对Java的方法调用。这种方式的基本原理是,用户代码运行时所在的R解释器进程创建Java虚拟机进程,R进程向Java进程发起执行相关方法调用的请求,Java在执行完方法调用后把结果返回给R进程,二者之间通过基于SOCKET的跨进程通信进行交互。两个进程分别对应图3 中的R-side和Java-side。具体过程如下。

( 1) 初始化。这一步在用户代码实际开始执行之前自动完成,且一般只进行一次。执行用户代码的R解释器进程创建一个Java虚拟机进程。Java进程创建一个服务器端套接字( J-Server) ,监听配置文件指定的端口。

( 2) R进程发送请求。R进程创建客户端套接字( J-Client) ,连接到J-Server,向Java进程发送请求类型、关联参数等序列化之后的数据。请求类型包括创建对象( 如图4 第3 行) 、调用对象方法( 如图4第4 行) 、调用静态方法( 即调用Java类的static方法) 等。关联参数,对于创建对象的请求包括类名( “Class T”) 、构造器形参( “arg1”) 等,对于方法调用的请求包括对象标识( “x”) 、方法名( “method A”) 和方法形参( “param1”) 等。J-Client开始等待J-Server返回结果。

( 3) Java进程接收和处理请求。J-Server接收到J-Client发来的请求,反序列化请求数据,解析出请求类型、关联参数等数据。

对于创建对象的请求,J-Server依据类名、构造器形参通过反射确定合适的构造器,执行该构造器,结果记为X; 对于调用方法的请求,J-Server依据对象标识、方法名和方法形参,从Java对象池( J-Pool)中找到对象标识实际引用的对象,并确定合适的方法,执行该方法,结果记为X。

J-Server返回处理结果取决于结果X的类型。如果X是void、null、简单类型( 如布尔值、数值、字符串等) 或简单类型的简单复合结构( 如数组、链表等) ,将按照预制的规则序列化之后返回给J-Client。如果X不是上述类型( 即X是一个一般性的Java对象) ,则把这个对象存放在J-Pool中,返回序列化之后的对象唯一标识给J-Client。

( 4) R进程接收处理结果。J-Client收到J-Server返回的数据,反序列化和解析,从而得到R调用Java方法的执行结果。

在上述过程中,Java对象池( J-Pool) 存放了Java进程运行的部分对象。这些对象往往需要和R进程进行交互,但是又难以表示为R进程的一个运行时对象,无法在R进程中直接使用。通过把对象实际保存在Java进程的对象池中,而提供一个可以被R进程访问的对象标识,使得R进程可以通过这个标识符与实际的Java对象交互。这样可以比较好的解决兼容性的问题。

2. 2. 2 Java对R函数调用

和Java语言不同,在R语言中,函数和数值、向量、列表等普通变量一样都是对象,可以和后者一样作为函数的形式参数传递。在2. 2. 1 节中,如果R调用Java方法的形参是函数,则会在转化为闭包、序列化之后传递给Java进程。图4 第5 行定义了一个R语言函数,函数名是foo。第6 行代码调用了Java对象“x”的方法“method B”,函数foo作为该方法的形参传递。从2. 2. 1 节可知,“method B”会在Java进程执行,作为方法形参的foo会被使用。这时就出现了Java对R的函数调用。

Java对R函数调用,根据R函数用途不同,可分为两种类型。

第一类,数据型函数。这类R函数用于数据处理,它们被传入map等Spark Streaming的API中,用于对数据进行转换。在Spark Streaming任务执行过程中,这类函数被R进程以闭包的函数提交给Java进程,Java进程把闭包作为流处理流程的一部分提交给Spark集群; Spark集群中的主节点接收到了这个闭包,在为从节点分配任务的同时把闭包传递给了从节点。在从节点上,主任务进程( Java虚拟机进程) 创建新的R进程,把闭包和需要处理的数据传递给R进程( R-Worker) ; R-Worker解析闭包,执行数据处理函数,最后把处理结果返回给Java进程。Java进程和R进程之间通过标准输入流和标准输出流进行数据传递。

第二类,功能型函数。图4 中的函数foo,可能是调用中间层( 图2) 的其他R语言函数。这类函数因为上下文依赖等原因,必须在主节点的R-side上运行,所以不能采用调用数据型函数的解决方法。这类函数出现在系统中间层的内部,对一般用户不可见,所以称之为功能性函数。Java调用功能型函数的基本原理和R调用Java方法的原理相同,但过程相反,同时也复用了R-SIDE和J-SIDE( 图3) 。具体过程如下。

( 1) 初始化。R进程创建服务器套接字( RServer) ,监听指定端口。

( 2) Java进程发出请求。因为Java调用R函数发生在R调用Java方法之后,所以当出现Java调用R函数的时候,Java进程已经存在。Java进程创建客户端套接字( R-Client) ,连接到R-Server上,把功能型函数的闭包等数据序列化之后传递给R-Server。

( 3) R进程接收和处理请求。R-Server接收到来自R-Client的请求以后,反序列化请求数据,从闭包中解析出需要执行的函数,得到执行结果。和2. 2. 1 节中的第( 3) 步不同,执行结果不会出现复杂的R语言对象,因而,可以直接把执行结果序列化之后返回给R-Client。

( 4) Java进程接收处理结果。R-Client收到RServer返回的数据,反序列化和解析,从而得到Java调用R函数的执行结果。

在实现过程中,功能型函数的闭包在R进程( R-Side) 创建也最终在R进程执行,传递给Java进程( J-Side) 也只是因为函数执行的时机由Java进程决定。为此可以在R-side创建一个R进程的运行时对象池( R-Pool) ,把功能型函数的闭包对象寄存在R-Pool中,并为每一个闭包对象分配一个唯一性的标识。这样,功能函数的闭包对象无需传递给Java进程,在第( 3) 只需要通过闭包的对象标识从RPool中找到合适的闭包对象即可。这样可以为减少进程间通信的开销,优化系统性能。

2. 2. 3 套接字创建和销毁

在2. 2. 1 节中服务器套接字J-Server在用户代码执行之前系统初始化时创建,其后一直保持坚挺状态,直到程序退出。客户端套接字J-Client在遇到R调用Java代码的时创建,当得到J-Server返回的结果以后立即销毁。这时因为R解释器是单线程实现,J-Client不停用则程序会阻塞在该处。

在2. 2. 2 节中,R-Server不能像J-Server一样在系统初始化是创建并开始监听,否者会阻塞该处代码之后程序的运行。R语言不支持多线程,让Java调用功能型R函数实现变得困难。经过对Spark Streaming代码的研究,本文在实现时利用了一个技巧。

Spark Streaming代码在定义流处理的具体过程之后,调用Streaming Context的start方法才会真正开始处理数据。而在start以后,这个工作线程就处于闲置等待状态了,直到程序异常退出或者用户关闭进程。对于单线程的R语言进程来说,这种做法实在是浪费资源。为此,本文在实现的时候复用了start之后的线程。在start之后再启用R-Server,让这个线程同时成为了R-Server的监听线程。因为start之后一段时间整个系统会等待Spark自身初始化,所以在此之前不会有R-Client对R-Server的请求发生,这保证了线程复用方法的正确性。

2. 3 闭包和代码优化

闭包是大多数函数式编程语言支持的一种技术,也被很多命令式编程语言支持,是“第一等级函数( first-class function) ”技术的基础。在有些编程语言里面,闭包也被成为lambda表达式。从技术上看,闭包是函数和函数上下文( 环境) 的所组成的特殊的数据结构,函数上下文可能包含外部环境变量的引用。闭包技术体现了函数式编程语言中“代码即数据”的思想,把表示数据处理操作的函数命令打包成为一种和普通变量一样使用的数据类型。

闭包的应用使得函数的执行脱离当前进程而转移到其他进程,使得函数执行的时机变得更加灵活,同时也对代码优化有积极作用。比如对于一些连续数据处理可以进行合并然后再经过闭包传递执行,这样做可以减少模块间通信所产生的额外消耗,从而提升性能。下面我们通过一个例子来说明。

图5 是闭包和代码优化过程的示意图。图5( a) 是R语言的一个代码片段,这段代码中,数据i经过func1、func2、func3 三个函数的变换得到最终结果z。在系统中,每个函数实际执行结果是返回一个对象,三个函数执行结果是三个依次嵌套的对象: 如图5( b) 所示,图中每个矩形表示一个对象,矩形的包含关系,也象征了对象的聚合关系。对象聚合的目的是获得如图5( c) 所示的闭包,在图5( c)中func1、func2、func3 三个函数聚合在一个函数c中构成一个闭包,这个闭包包含了对最初的数据i的从func1 到func3 的转换过程,而只有当闭包被执行,转换过程才会发生,这样可以实现类似延迟加载的作用; 闭包c可以序列化后传递给其他进程,这也是2. 2 节中跨语言交互的基础,也可以减少跨语言交互的频次,起到了代码优化的作用。对用户而言,图5 所示的过程是透明的。

3 应用示例

词频统计( word count) 是数据分析中常见任务,是文本向量生成、热点话题发现等多类分析任务的基础。图6 是用R语言编写的网络文本的词频统计应用的代码,应用了flat Map等Spark API的R语言接口,也有function( l) { strsplit( l," ") [[1]]}等用户自定义的R语言函数。图7 展示了该程序运行效果。仅仅使用几行R语言代码就可以开始一个分布式流处理词频统计任务,简单快速,对大多数熟悉R语言的统计分析人员和数据科学家而言非常方便。

4 结束语

作用及R语言实现 篇4

关键词:广义相关系数,非线性相关,抽样分布,假设检验,R语言

变量间的相关性度量是进行系统结构与功能分析的基础。但以往的研究如简单相关、典范相关[1]和广义相关[2]等,均是建立在线性相关[3]的基础上,或者是造成了原有变异信息的损失[4],或者是计算复杂[5],它们反映了两个(组)变量之间的线性相关程度,但不能反映两个(组)变量之间的非线性相关程度[6]。本文就自己定义的计算简单、无信息损失的非线性广义相关系数的抽样分布及假设检验问题,使用R语言编写了该非线性广义相关系数抽样分布及假设检验的函数包,便于应用工作者使用,并且丰富了多元统计学的知识和R语言中的函数包。

1 一种非线性广义相关系数的定义

定义:假设变量X的四阶中心矩为(μ4)i[8],四阶混合矩为(μ4)ij,(i,j=1,2,…,m;且i≠j),变量Y的四阶中心矩为(ν4)i,四阶混合矩为(ν4)ij,(i,j=1,2,…,p;i≠j);变量X、Y的四阶混合矩为(μν)4 ij,(i=1,2,…,m;j=1,2,…,p),并假设

为变量X、Y的广义相关系数。

式(1)中:

(μ4)ij=E(Xi-μxi)2(Xj-μxj)2,i,j=1,2,…,m;(ν4)ij=E(Yi-μyi)2(Yj-μyj)2,i,j=1,2,…,p;(μν4)ij=E(Xi-μxi)2(Yj-μyj)2,i=1,2,…,m;

因为变量的四阶中心矩与其四阶混合矩组成矩阵中的每个元素,与相关阵的每个元素平方后所得的矩阵中每个元素相差3倍。故定义中的式(1)与下式是等价的,即:当

显然,当m=p=1时,X、Y的相关系数是其简单相关系数,即:r2XY=ρ2。

2 非线性广义相关系数的假设检验

2.1 定义中非线性相关性广义相关系数的抽样分

布及假设检验问题

建立Y(2)关于X(2)的一元线性回归模型,记为:Yi(2)=β0+βXi(2)+εi,且εi~N(0,σ2)。应用最小二乘估计可得β0=珔Y(2)-b珔X(2),其中珔X(2)、珔Y(2)分别是X(2)、Y(2)的均值;

由一元线性回归方程的统计检验可得:

再由t分布和F分布的关系可得:

以上分析表明,定义中的广义相关系数即是X(2)与Y(2)之间的简单相关系数,所以定义中广义相关系数r=0的检验即可应用t检验或者F检验进行。

2.2 假设检验步骤

为了方便应用,现将检验步骤列举如下:

第1步:由定义中的公式计算出广义相关系数值r;

第2步:将r代入式(3)或(4)中,算出相应的F值和t值;

第3步:给定置信水平α,查表得Fα(1,n-2)或者tα(n-2):若|F|<Fα(1,n-2)或者|t|<tα(n-2),则接受原假设,即广义相关系数r与0无显著性差异;否则原假设不成立,即广义相关系数r与0有显著性差异。

3 非线性广义相关系数的抽样分布、假设检验及其R语言实现[10]

将变量X和Y之间的非线性广义相关系数的抽样分布及假设检验问题是用R语言[11]编写的函数程序包generalized.correlation如下:

在R程序中,输入变量X和Y的原始数据值,再运行generalized.correlation(X,Y),,就可直接得到变量X和Y的非线性广义相关系数值,并能检验出该非线性广义相关系数与0之间是否有显著性差异。

4 结论

本文就计算简单、无信息损失的非线性广义相关系数的计算,及其抽样分布与假设检验问题,使用R语言编写了其函数包,便于应用工作者使用,并且丰富了多元统计学的知识和扩充了R语言中的函数包。

参考文献

[1]张尧庭.广义相关系数及其应用.应用数学学报,1978;(4):33—39

[2]胡永宏.一种广义相关系数.统计与信息论坛,1997;(1):20—23

[3]张尧庭.关于度量变量之间的相关程度.上海财经大学学报,1999;(2):60—63

[4]Nelsen N B.An Introduction to copulas,lectures notes in statistics.New York:Spring Verlag,1998:139

[5]Kullback S.Information theory and statistics.[s.n.]:John Wiley&Sons Inc,1959

[6]刘垂玗.作物数量性状的遗传相关信息及其可加性.安徽农业科学,1981;(S1):52—57

[7]袁志发,周静芋.多元统计分析.北京:科学出版社,2002:172—180,241—256

[8]陈希孺.概率论与数理统计.安徽:科学出版社,2002:126—140

[9]董晓萌,曹彬婕,罗凤娟,等.一种度量生物性状非线性相关性的广义相关系数.西北农林科技大学学报:自然科学版,2008;(5):191—195

[10]汤银才.R语言与统计分析.北京:高等教育出版社,2008:27—67

上一篇:环境生态学与经济学下一篇:幼儿期养成教育论文