概率回归的EM算法实现

9月30日,二千零一十四
通过

(本文首次发表于 Rcpp画廊,并对 188bet appR博主

新用户Rcpp
功能系列通常对
可实现的性能提升,但很难找到方法
他们自己的计算问题。许多最令人印象深刻的性能提升
用看似先进的统计方法证明,先进的
c++相关结构,或者两者兼而有之。即使用户能够理解
各种已演示的功能单独运行,示例也可以实现
许多人同时看起来很容易接近。

本文的重点是提供一个示例应用程序
性能良好(多亏了RCPP系列),但减少了统计数据和
一些用户的编程开销。此外,而不是简单地展示
最终产品,开发过程被明确地记录下来
叙述。

激励示例:Probit回归

作为一个例子,我们将考虑评估标准探针的参数
回归模型由

在哪里和是长度矢量和“截距”项的存在被吸收到如果需要的话。

分析员只能使用经过审查的版本,即
其中下标表示第三次观察。

是很常见的,假设审查产生
如果


否则。当我们假定

问题是所有人都喜欢的Probit回归模型。

为了使这个混凝土,考虑使用数据集的投票人投票模型
由Zelig R包提供。

图书馆“变色龙”数据“投票”
产量
种族年龄教育收入VOTE1白色60 14 3.3458 12白色51 10 1.8561 03白色24 12 0.6304 04白色38 8 3.4183 15白色25 12 2.7852 16白色67 12 2.3866 1
昏暗的产量
〔1〕2000 5

我们的目标是估计与变量相关的参数
收入教育,和年龄。因为这没什么特别的金宝搏网址
数据集,标准方法非常有效。

FIT0<全球语言监测机构投票~收入+教育+年龄数据=产量家庭=二项式链接= “probit”
            FIT0
呼叫:GLM(公式=投票~收入+教育+年龄,家族=二项式(link=“probit”),数据=道岔)系数:(截距)收入教育年龄-1.6824 0.0994 0.1067 0.0169自由度:1999年总计(即零);残差:2270残差:2030 AIC: 2040

使用FIT0作为我们的基准,问题是我们如何恢复这些估计
采用基于RCPP的方法。一个答案是在C++中实现EM算法
可以被处理成r级函数的代码片段;我们就这么做
做的。(可以把这看作是一个Probit回归的类比
线性回归实例-但功能更少。

EM算法:直觉

对于不熟悉电磁算法的人,考虑
维基百科的文章
和A密集的斯沃斯莫尔课堂讲稿

这种方法背后的直觉开始于注意到如果自然母亲
揭示了价值观,我们只需要一个线性回归问题
并专注于

其中,假定矩阵符号的含义。

因为大自然母亲不是那么仁慈,我们必须归罪这个
值。对于一个给定的猜测,由于我们的分布
假设金宝搏网址我们知道

在哪里。

通过重复这两个步骤,我们最终可以恢复
参数估计:

  1. 转嫁/增强价值观
  2. 估计考虑到数据的增加

我们的实现

演示Probit回归模型的EM算法的实现
使用rcppr提供的功能,我们将考虑一系列步骤。

这些都是:

  1. 尝试1:主结构
  2. 尝试2:错误增强的电磁波
  3. 尝试3:EM,正确增大
  4. 尝试4:em,同时正确增加

这些步骤是之所以选择,是因为每个都会产生有用的输出(从
参数估计的角度)但是因为它们反映了a的里程碑
有利于新用户的开发过程:在
时间。

开始,我们准备了r级数据,以最终实现基于c++的版本
功能。

我的< 矩阵产量$投票mX< cBN产量$收入产量$教育产量$年龄

尝试1:主结构

第一个里程碑是模拟一个函数em1导出到
创建同名的R级函数。这里的主要特点是
已将函数定义为
–接受与可能的输入相对应的参数
–为要计算的值创建容器,
–概述em迭代的代码主循环,和
–返回列表中感兴趣的各种值

新加入RCPP流程的用户将受益于退货列表中的对象
开始。它们允许您快速将新的和不同的值返回到r级别
进行检查。

包括:
          
/ /[[Rcpp:取决于(RcppArmadillo)]]

使用 命名空间 Rcpp 

//[[rcpp::export()]]
列表 em1 康斯特 自回归滑动平均:: Y
          康斯特 自回归滑动平均:: X
          康斯特 int 马克西特 = 10
           {
    / /输入
    康斯特 int N = Y恩罗 
    康斯特 int K = X恩科尔斯 

    / /容器
    自回归滑动平均:: βK  
    β填满  //将betas初始化为1
    自回归滑动平均:: 埃斯塔尔N  
    埃斯塔尔填满 

    / /算法
    对于 int  =    < 马克西特  ++ { //em迭代
        //下一步:实现算法
    }

    /返回
    列表 受潮湿腐烂 
    受潮湿腐烂[“n”] = N 
    受潮湿腐烂[“K”] = K 
    受潮湿腐烂[“测试版”] = β 
    受潮湿腐烂[“eystar”] = 埃斯塔尔 
    返回受潮湿腐烂 
}

我们知道这段代码不会产生任何估计。的确,那就是
通过设计。都不β也不埃斯塔尔返回的元素列表
在初始化为0后进行更新。

然而,我们可以看到,很多行政工作都是为了工作
实现完成。

fit1<em1Y=我的X=mX马克西特= 20.
            fit1$β
[,1][1,] 0[2,] 0[3,] 0[4,] 0
fit1$埃斯塔尔
[1][1][2]0 0 0[3][4][5][6]0

验证了输入数据结构和输出数据结构
按预期“工作”,我们开始更新值。

尝试2:错误增强的电磁波

更新不同的值取决于或
。而不是担心不被观察到的事物金宝搏网址
倾向性,我们将使用1和-1的虚拟值作为占位符。相反,这个
重点是建立必要的代码条件结构,以及
循环执行每个观察的更新步骤。

此外,在每个插补步骤结束时e在里面相对长度单位我们更新了
用最小二乘法估计在里面相对长度单位

包括:
          
/ /[[Rcpp:取决于(RcppArmadillo)]]

使用 命名空间 Rcpp 

//[[rcpp::export()]]
列表 EM2 康斯特 自回归滑动平均:: Y
          康斯特 自回归滑动平均:: X
          康斯特 int 马克西特 = 10
           {
    / /输入
    康斯特 int N = Y恩罗 
    康斯特 int K = X恩科尔斯 

    / /容器
    自回归滑动平均:: βK  
    β填满  //将betas初始化为0
    自回归滑动平均:: 埃斯塔尔N  
    埃斯塔尔填满 

    / /算法
    对于 int  =    < 马克西特  ++ {
        自回归滑动平均:: μ = X * β 
        / /增加步骤
        对于 int n =   n < N  n++ {
            如果 Yn  = =  { //y=1
                //下一步:修复增强
                埃斯塔尔n  =  
            }
            如果 Yn  = =  { //y=0
                //下一步:修复增强
                埃斯塔尔n  = - - - - - - 
            }
        }
        / /最大化一步
        β = Xt() * X() * Xt() * 埃斯塔尔 
    }

    /返回
    列表 受潮湿腐烂 
    受潮湿腐烂[“n”] = N 
    受潮湿腐烂[“K”] = K 
    受潮湿腐烂[“测试版”] = β 
    受潮湿腐烂[“eystar”] = 埃斯塔尔 
    返回受潮湿腐烂 
}

此代码,就像在第一次尝试中,在语法上很好。但是,正如我们所知,这个
更新步骤非常错误。然而,我们可以看到更新的发生是
我们期望,我们看到非零回报β元素与埃斯塔尔
元素。

fit2<EM2Y=我的X=mX马克西特= 20.
            fit2$β
-0.816273[1][1][2][3]0.046065 0.059481 0.009085[4]
fit2$埃斯塔尔
[1][1]1[2][3][4]1[5]1[6]1

尝试3:EM,正确增大

随着代码的最终逻辑结构的构建,现在我们将纠正
数据扩充。具体地说,我们把1和-1的赋值替换成
不可观测值的期望值。而不是弄脏我们的
功能(EM3-())通过进一步的计算,我们示例调用C++级别
功能F-()g-()哪些在我们定义之前就已经包含了
EM3-()

但是,因为这些只是EM3-(),他们
未标记为要导出(通过//[[rcpp::export()]])到R级。

事实上,这是一个正确的实现(尽管还有空间)
改进)。

包括:
          
/ /[[Rcpp:取决于(RcppArmadillo)]]

使用 命名空间 Rcpp 

 f  μ {
     瓦尔 = ((R::达范德- - - - - -μ   )) /
                   - - - - - - R::帕尼莫- - - - - -μ    ))
                   
    返回瓦尔 
}

 G  μ {
     瓦尔 = ((R::达范德- - - - - -μ   )) /
                  R::帕尼莫- - - - - -μ    ))
                   
    返回瓦尔 
}

//[[rcpp::export()]]
列表 em3 康斯特 自回归滑动平均:: Y
          康斯特 自回归滑动平均:: X
          康斯特 int 马克西特 = 10
           {
    / /输入
    康斯特 int N = Y恩罗 
    康斯特 int K = X恩科尔斯 

    / /容器
    自回归滑动平均:: βK  
    β填满  //将betas初始化为0
    自回归滑动平均:: 埃斯塔尔N  
    埃斯塔尔填满 

    / /算法
    对于 int  =    < 马克西特  ++ {
        自回归滑动平均:: μ = X * β 
        / /增加步骤
        //下一步:并行扩充步骤
        对于 int n =   n < N  n++ {
            如果 Yn  = =  { //y=1
                埃斯塔尔n  = μn  + fμn )) 
            }
            如果 Yn  = =  { //y=0
                埃斯塔尔n  = μn  - - - - - - Gμn )) 
            }
        }
        / /最大化一步
        β = Xt() * X() * Xt() * 埃斯塔尔 
    }

    /返回
    列表 受潮湿腐烂 
    受潮湿腐烂[“n”] = N 
    受潮湿腐烂[“K”] = K 
    受潮湿腐烂[“测试版”] = β 
    受潮湿腐烂[“eystar”] = 埃斯塔尔 
    返回受潮湿腐烂 
}
FIT3<em3Y=我的X=mX马克西特= 一百
            
FIT3$埃斯塔尔
[1][1,]1.3910[2,]0.6599[3,]0.7743[4,]0.8563[5,]0.9160[6,]1.2677

第二,注意,此输出与参数估计值
对象FIT0)从我们的R级呼叫到GLM-()功能。

FIT3$β
-1.68241[1][1][2][3]0.09936 0.10667 0.01692[4]
FIT0
呼叫:GLM(公式=投票~收入+教育+年龄,家族=二项式(link=“probit”),数据=道岔)系数:(截距)收入教育年龄-1.6824 0.0994 0.1067 0.0169自由度:1999年总计(即零);残差:2270残差:2030 AIC: 2040

尝试4:em,同时正确增加

具有完整的as函数实现EM3-(),我们知道转到第二个
订单关注:性能。计算函数所需的时间可以是
从用户坐在一个有空闲内核的计算机的角度来看。

虽然这些数据的小规模并不需要并行化,这个e
STEP是并行化的自然候选者。在这里,平行化
依赖于OpenMP。见在这里对于其他组合示例
RCPP和OpenMP或在这里换一种方法。

Sys.setenv“PKG_CXXFLAGS” = “-fopenmp”
Sys.setenv“PKG_LIBS” = “-fopenmp”

除了一些额外的编译器标志之外,对新实现的更改
在里面EM4()是最小的。他们是:

  • 包括附加标题
  • 标志着对于与A并行的循环# pragma
包括:
          
包括:
          

/ /[[Rcpp:取决于(RcppArmadillo)]]

使用 命名空间 Rcpp 

 f  μ {
     瓦尔 = ((R::达范德- - - - - -μ   )) /
                   - - - - - - R::帕尼莫- - - - - -μ    ))
                   
    返回瓦尔 
}

 G  μ {
     瓦尔 = ((R::达范德- - - - - -μ   )) /
                  R::帕尼莫- - - - - -μ    ))
                   
    返回瓦尔 
}

//[[rcpp::export()]]
列表 em4 康斯特 自回归滑动平均:: Y
          康斯特 自回归滑动平均:: X
          康斯特 int 马克西特 = 10
          康斯特 int 萨里法斯 = 
           {
    / /输入
    康斯特 int N = Y恩罗 
    康斯特 int K = X恩科尔斯 
    OMP_设置_num_线程萨里法斯 

    / /容器
    自回归滑动平均:: βK  
    β填满  //将betas初始化为0
    自回归滑动平均:: 埃斯塔尔N  
    埃斯塔尔填满 

    / /算法
    对于 int  =    < 马克西特  ++ {
        自回归滑动平均:: μ = X * β 
        / /增加步骤
#pragma omp parallel用于
        对于 int n =   n < N  n++ {
            如果 Yn  = =  { //y=1
                埃斯塔尔n  = μn  + fμn )) 
            }
            如果 Yn  = =  { //y=0
                埃斯塔尔n  = μn  - - - - - - Gμn )) 
            }
        }
        / /最大化一步
        β = Xt() * X() * Xt() * 埃斯塔尔 
    }

    /返回
    列表 受潮湿腐烂 
    受潮湿腐烂[“n”] = N 
    受潮湿腐烂[“K”] = K 
    受潮湿腐烂[“测试版”] = β 
    受潮湿腐烂[“eystar”] = 埃斯塔尔 
    返回受潮湿腐烂 
}

这种更改不应该(也不会)导致对计算的任何更改
正在完成。然而,如果我们的算法包含随机数生成,伟大的
需要注意确保我们的结果是可重复的。

fit4<em4Y=我的X=mX马克西特= 一百
            

完全相同的fit4$βFIT3$β
[1 ]真

最后,我们可以确认我们的并行化是“成功的”。再一次,
因为实际上不需要并行处理这段代码,业绩增长是
谦虚的但是,它确实跑得更快是显而易见的。

图书馆“微基准”微基准SEQ= em3Y=我的X=mX马克西特= 一百
                          
                      标准= em4Y=我的X=mX马克西特= 一百萨里法斯= 4
                          
                      = 20.
               
单位:毫秒expr min lq平均中位数uq max neval cld seq 32.94 33.01 33.04 33.03 33.07 33.25 20 b par 11.16 11.20 11.35 11.26 11.29 13.16 20 a

包扎

这篇长篇的画廊文章的目的既不是为了展示新的
功能性和前沿计算的可行性
算法。相反,它是明确地遍历一个开发过程
与新用户在使用非常常见的
统计问题,概率单位回归。

留下你的评论作者,请关注他们博客上的链接和评论: Rcpp画廊

188bet appR博客提供了 每日电子邮件更新金宝搏网址 R新闻和 教程关于以下主题: 数据科学大数据, r作业,可视化(可视化) GGPROTT2箱线图地图动画)程序设计(程序) 演播室斯威夫特乳胶SQL日食吉特哈多普网页抓取)统计 回归主成分分析时间序列交易还有更多…



如果你走这么远,为什么不 订阅更新 从这个网站吗?选择你的味道: 电子邮件推特1188bet app,或 脸谱网

注释已关闭。

搜索R-blo188bet appggers


赞助商

千万不要错过更新!
订阅R-bloggers188bet app接收
电子邮件与最新的R职位。
(您将不再看到此消息。)

单击此处关闭(此弹出窗口将不再出现)