R中的Bigglm:源代码的限制和改进(例如,调用Fortran)

时间:2012-01-03 13:00:41

标签: r bigdata glm

我最近一直在使用R在100 mb csv文件(900万行乘5列)上运行广义线性模型(GLM)。这个文件的内容包括5个名为depvar,var1,var2,var3,var4的列,它们都是随机分布的,这样列包含0,1或2的数字。基本上我使用了biglm包来运行GLM此数据文件和R在大约2分钟内处理完毕。这是在使用R版本2.10(我目前正在更新到2.14),4个内核和8 GB RAM的Linux机器上。基本上我想在30到60秒左右更快地运行代码。一种解决方案是添加更多内核和RAM,但这只是一个临时解决方案,因为我意识到数据集只会变得更大。理想情况下,我想找到一种方法来使bigglm的代码更快。我在数据集上运行了一些R分析代码。添加以下代码(在我想运行的代码之前检查它的速度):

Rprof('method1.out')

然后在输入此命令后,我编写了我的bigglm代码,如下所示:

x<-read.csv('file location of 100mb file')
form<-depvar~var1+var2+var3+var4
a<-bigglm(form, data=x, chunksize=800000, sandwich=FALSE, family=binomial())
summary(a)
AIC(a)
deviance(a)

运行这些代码大约需要2到3分钟后,我输入以下代码来查看我的分析代码:

Rprofsummary('method1.out')

然后我得到的是bigglm过程的细分以及哪些单独的线路花了很长时间。看完之后,我惊讶地发现有一个需要很长时间(约20秒)的fortran代码调用。此代码可以在Bigglm的基本文件中找到:

http://cran.r-project.org/web/packages/biglm/index.html

在bigglm 0.8.tar.gz文件中

基本上我问社区的是,这段代码可以更快吗?例如,通过更改代码来调用Fortran代码来进行QR分解。此外还有其他功能,如as.character和model.matrix也需要很长时间。我没有在这里附加分析文件,因为我相信它可以很容易地重现,因为我提供的信息,但基本上我暗示大数据的大问题和处理这个大数据GLM。这是R社区共享的问题,我认为任何反馈或帮助都会对此问题表示感谢。您可以使用不同的数据集轻松复制此示例,并查看bigglm代码中的内容,并查看它们是否与我找到的内容相同。如果是这样,请有人帮我弄清楚如何让bigglm运行得更快。在Ben请求它之后,我已经上传了我的分析代码片段以及我的csv文件的前10行:

 CSV File:

 var1,var2,var3,var4,depvar
   1,0,2,2,1
   0,0,1,2,0
   1,1,0,0,1
   0,1,1,2,0
   1,0,0,3,0
   0,0,2,2,0
   1,1,0,0,1
   0,1,2,2,0
   0,0,2,2,1

此CSV输出是从我的文本编辑器UltraEdit中复制的,可以看到var1取值0或1,var2取值0和1,var3取值0,1,2,var4取值0 1,2,3和depvar取值为1或0.这个csv可以在excel中使用RAND函数复制到大约100万行然后可以复制和粘贴多次以获得大量的行像ultraedit这样的文本编辑器。基本上将RAND()键入一列100万列,然后在RAND()列旁边的列中进行舍入(列)以得到1和0。同样的想法适用于0,1,2,3。

分析文件很长,所以我附加了占用大部分时间的行:

 summaryRprof('method1.out')



$by.self
                        self.time self.pct total.time total.pct
"model.matrix.default"      25.40     20.5      26.76      21.6
".Call"                     20.24     16.3      20.24      16.3
"as.character"              17.22     13.9      17.22      13.9
"[.data.frame"              14.80     11.9      22.12      17.8
"update.bigqr"               5.72      4.6      14.38      11.6
"-"                          4.36      3.5       4.36       3.5
"anyDuplicated.default"      4.18      3.4       4.18       3.4
"|"                          3.98      3.2       3.98       3.2
"*"                          3.44      2.8       3.44       2.8
"/"                          3.18      2.6       3.18       2.6
"unclass"                    2.28      1.8       2.28       1.8
"sum"                        2.26      1.8       2.26       1.8
"attr"                       2.12      1.7       2.12       1.7
"na.omit"                    2.02      1.6      20.00      16.1
"%*%"                        1.74      1.4       1.74       1.4
"^"                          1.56      1.3       1.56       1.3
"bigglm.function"            1.42      1.1     122.52      98.8
"+"                          1.30      1.0       1.30       1.0
"is.na"                      1.28      1.0       1.28       1.0
"model.frame.default"        1.20      1.0      22.68      18.3
">"                          0.84      0.7       0.84       0.7
"strsplit"                   0.62      0.5       0.62       0.5

$by.total
                        total.time total.pct self.time self.pct
"standardGeneric"           122.54      98.8      0.00      0.0
"bigglm.function"           122.52      98.8      1.42      1.1
"bigglm"                    122.52      98.8      0.00      0.0
"bigglm.data.frame"         122.52      98.8      0.00      0.0
"model.matrix.default"       26.76      21.6     25.40     20.5
"model.matrix"               26.76      21.6      0.00      0.0
"model.frame.default"        22.68      18.3      1.20      1.0
"model.frame"                22.68      18.3      0.00      0.0
"["                          22.14      17.9      0.02      0.0
"[.data.frame"               22.12      17.8     14.80     11.9
".Call"                      20.24      16.3     20.24     16.3
"na.omit"                    20.00      16.1      2.02      1.6
"na.omit.data.frame"         17.98      14.5      0.02      0.0
"model.response"             17.44      14.1      0.10      0.1
"as.character"               17.22      13.9     17.22     13.9
"names<-"                    17.22      13.9      0.00      0.0
"<Anonymous>"                15.10      12.2      0.00      0.0
"update.bigqr"               14.38      11.6      5.72      4.6
"update"                     14.38      11.6      0.00      0.0
"data"                       10.26       8.3      0.00      0.0
"-"                           4.36       3.5      4.36      3.5
"anyDuplicated.default"       4.18       3.4      4.18      3.4
"anyDuplicated"               4.18       3.4      0.00      0.0
"|"                           3.98       3.2      3.98      3.2
"*"                           3.44       2.8      3.44      2.8
"/"                           3.18       2.6      3.18      2.6
"lapply"                      3.04       2.5      0.04      0.0
"sapply"                      2.44       2.0      0.00      0.0
"as.list.data.frame"          2.30       1.9      0.02      0.0
"as.list"                     2.30       1.9      0.00      0.0
"unclass"                     2.28       1.8      2.28      1.8
"sum"                         2.26       1.8      2.26      1.8
"attr"                        2.12       1.7      2.12      1.7
"etafun"                      1.88       1.5      0.14      0.1
"%*%"                         1.74       1.4      1.74      1.4
"^"                           1.56       1.3      1.56      1.3
"summaryRprof"                1.48       1.2      0.02      0.0
"+"                           1.30       1.0      1.30      1.0
"is.na"                       1.28       1.0      1.28      1.0
">"                           0.84       0.7      0.84      0.7
"FUN"                         0.70       0.6      0.36      0.3
"strsplit"                    0.62       0.5      0.62      0.5

我主要对调用Fortran的.Call函数感到惊讶。也许我不明白。似乎所有计算都在使用此功能后完成。我认为这就像一个提取Fortran代码的链接函数。此外,如果Fortran正在完成所有工作并且所有迭代加权最小二乘/ QR为什么剩下的代码需要这么长时间。

1 个答案:

答案 0 :(得分:4)

我的理解是,biglm将数据分成块并按顺序运行它们。

  • 因此,您可以通过优化块的大小来加快速度,使其与内存允许的大小一样大。
  • 这也只是使用你的一个核心。这不是多线程代码。你需要做一些魔术才能让它发挥作用。