使用并行编程在 R 中编程 50000 个回归
Programming 50000 regressions in R using parallel programming
我有以下作业问题,我已经完成但似乎需要很长时间才能完成:
假设Y、X1、···、X1000均为均值为0、标准差为1的正态随机变量,且相互独立。生成 Y、X1、···、X1000 的 30 个样本。现在重复以下 50000 次:从 X1 中随机选取十个变量,. . ., X1000, 运行 Y 对这十个变量的线性回归并记录 R2。计算 50000 个 R2 的最大值。
这是我的代码,它适用于 8000 次回归(在我的 macbook pro 的每个核心上 1000 次回归),但似乎无法在每个核心上完成 6250 次回归(总共 50000 次回归)。这是我的代码:
library(snow)
cl <- makeCluster(8, type = "SOCK")
invisible(clusterEvalQ(cl, reg_cluster <- function(rep, samples, n) {
X <- list()
R <- rep(0, rep)
for (k in 1:rep) {
Y <- rnorm(samples)
for (j in 1:n) {
X[[j]] <- rnorm(samples)
}
X_1 <- sample(X, 10, replace = FALSE)
X_1_unlist <- unlist(X_1)
X.1 <- matrix(X_1_unlist[1:30], ncol = 1)
X.2 <- matrix(X_1_unlist[31:60], ncol = 1)
X.3 <- matrix(X_1_unlist[61:90], ncol = 1)
X.4 <- matrix(X_1_unlist[91:120], ncol = 1)
X.5 <- matrix(X_1_unlist[121:150], ncol = 1)
X.6 <- matrix(X_1_unlist[151:180], ncol = 1)
X.7 <- matrix(X_1_unlist[181:210], ncol = 1)
X.8 <- matrix(X_1_unlist[211:240], ncol = 1)
X.9 <- matrix(X_1_unlist[241:270], ncol = 1)
X.10 <- matrix(X_1_unlist[271:300], ncol = 1)
X_data <- cbind(X.1, X.2, X.3, X.4, X.5, X.6, X.7, X.8, X.9, X.10)
X_data <- as.data.frame (X_data)
names(X_data) <- c("X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "X10")
attach(X_data)
reg <- lm(Y ~ X1 + X2 + X3 + X4 + X5 + X6 + X7 + X8 + X9 + X10)
R[k] <- summary(reg)$r.squared
}
return(max(R))
}))
results <- clusterEvalQ(cl, reg_cluster(1000, 30, 1000))
results <-clusterEvalQ(cl, reg_cluster(6250, 30, 1000))
stopCluster(cl)
max_results <- c(results[[1]], results[[2]], results[[3]], results[[4]],
results[[5]], results[[6]], results[[7]], results[[8]])
max(max_results)
这里还有一点需要注意。每次我 运行 一个新的回归,Y 和所有的 X 都会重新生成。没有随机变量从一个回归转移到下一个。
所以我的问题是,我怎样才能使这个 运行 更快?
另外,谁能告诉我为什么它在 12 分钟后完成了 8000 次回归,但在 2.5 小时后仍然没有完成 50000 次回归?
编辑:以下程序已被教授确认:
1) 为Y, X1, ..., X1000 中的每一个生成30 个随机标准正态变量。 Y 总共有 30 个随机正态变量,所有 X 总共有 30 x 1,000 = 30,000 个随机正态变量(每个 30 个)
2) 随机 select X 的 1000 个选择中的十个(例如 X726、X325、X722、X410、X46、X635、X822、X518、X773、X187)
3) 运行 使用 R 中的 lm 函数对 Y ~ 10 X 进行线性回归。Y 将有 30 个观测值,而每个 X 也将有 30 个观测值。本质上,我们会尝试拟合 Y = B0 + B1 * X1 + B2 * X2 + ... + B10 * X10,其中每个 X 代表第 2 部分中随机 selected 之一。
4) 将R2值记录在向量中
5) 重复步骤 1-4 50,000 次
6) 找出记录的 50,000 个中的最大 R2
这是一个似乎可以解决您的问题的替代代码。
ns <- 30
rvals <- replicate(50000, {
y <- rnorm(ns)
xvals <- replicate(1000, rnorm(ns))
selecteds <- xvals[,sample(1:1000, 10)]
df <- data.frame(y = ys, selecteds)
summary(lm(paste("y ~", paste0("X", 1:10, collapse = "+")), data = df))$r.squared
})
我对集群不是很有经验,但以下是您的代码可能太慢的几个原因:
- 您嵌套了 foor 循环来创建
X
,我使用了 replicate
,这可能比使用列表快一些。
- 您生成的是一个空列表,
X
,这非常糟糕。 (勾选The R inferno - Circle 2)
- 您取消列出了几个列表元素只是为了使它们成为 1 列矩阵,然后将它们全部绑定并最后命名列。尽管这些步骤似乎是必要的,但我认为一次一个地执行这些步骤可能很慢。例如,colnames 会自动设置为 X1:X10.
- 没有必要使用
attach
并且可能会减慢速度。
- 如果您 open/close 集群太多,会消耗大量处理,并且会比非并行更慢。不过好像不是这样。
最后一点,请确保我和你做的一样,因为这个问题对我来说仍然有点令人困惑。
我有以下作业问题,我已经完成但似乎需要很长时间才能完成:
假设Y、X1、···、X1000均为均值为0、标准差为1的正态随机变量,且相互独立。生成 Y、X1、···、X1000 的 30 个样本。现在重复以下 50000 次:从 X1 中随机选取十个变量,. . ., X1000, 运行 Y 对这十个变量的线性回归并记录 R2。计算 50000 个 R2 的最大值。
这是我的代码,它适用于 8000 次回归(在我的 macbook pro 的每个核心上 1000 次回归),但似乎无法在每个核心上完成 6250 次回归(总共 50000 次回归)。这是我的代码:
library(snow)
cl <- makeCluster(8, type = "SOCK")
invisible(clusterEvalQ(cl, reg_cluster <- function(rep, samples, n) {
X <- list()
R <- rep(0, rep)
for (k in 1:rep) {
Y <- rnorm(samples)
for (j in 1:n) {
X[[j]] <- rnorm(samples)
}
X_1 <- sample(X, 10, replace = FALSE)
X_1_unlist <- unlist(X_1)
X.1 <- matrix(X_1_unlist[1:30], ncol = 1)
X.2 <- matrix(X_1_unlist[31:60], ncol = 1)
X.3 <- matrix(X_1_unlist[61:90], ncol = 1)
X.4 <- matrix(X_1_unlist[91:120], ncol = 1)
X.5 <- matrix(X_1_unlist[121:150], ncol = 1)
X.6 <- matrix(X_1_unlist[151:180], ncol = 1)
X.7 <- matrix(X_1_unlist[181:210], ncol = 1)
X.8 <- matrix(X_1_unlist[211:240], ncol = 1)
X.9 <- matrix(X_1_unlist[241:270], ncol = 1)
X.10 <- matrix(X_1_unlist[271:300], ncol = 1)
X_data <- cbind(X.1, X.2, X.3, X.4, X.5, X.6, X.7, X.8, X.9, X.10)
X_data <- as.data.frame (X_data)
names(X_data) <- c("X1", "X2", "X3", "X4", "X5", "X6", "X7", "X8", "X9", "X10")
attach(X_data)
reg <- lm(Y ~ X1 + X2 + X3 + X4 + X5 + X6 + X7 + X8 + X9 + X10)
R[k] <- summary(reg)$r.squared
}
return(max(R))
}))
results <- clusterEvalQ(cl, reg_cluster(1000, 30, 1000))
results <-clusterEvalQ(cl, reg_cluster(6250, 30, 1000))
stopCluster(cl)
max_results <- c(results[[1]], results[[2]], results[[3]], results[[4]],
results[[5]], results[[6]], results[[7]], results[[8]])
max(max_results)
这里还有一点需要注意。每次我 运行 一个新的回归,Y 和所有的 X 都会重新生成。没有随机变量从一个回归转移到下一个。
所以我的问题是,我怎样才能使这个 运行 更快?
另外,谁能告诉我为什么它在 12 分钟后完成了 8000 次回归,但在 2.5 小时后仍然没有完成 50000 次回归?
编辑:以下程序已被教授确认:
1) 为Y, X1, ..., X1000 中的每一个生成30 个随机标准正态变量。 Y 总共有 30 个随机正态变量,所有 X 总共有 30 x 1,000 = 30,000 个随机正态变量(每个 30 个)
2) 随机 select X 的 1000 个选择中的十个(例如 X726、X325、X722、X410、X46、X635、X822、X518、X773、X187)
3) 运行 使用 R 中的 lm 函数对 Y ~ 10 X 进行线性回归。Y 将有 30 个观测值,而每个 X 也将有 30 个观测值。本质上,我们会尝试拟合 Y = B0 + B1 * X1 + B2 * X2 + ... + B10 * X10,其中每个 X 代表第 2 部分中随机 selected 之一。
4) 将R2值记录在向量中
5) 重复步骤 1-4 50,000 次
6) 找出记录的 50,000 个中的最大 R2
这是一个似乎可以解决您的问题的替代代码。
ns <- 30
rvals <- replicate(50000, {
y <- rnorm(ns)
xvals <- replicate(1000, rnorm(ns))
selecteds <- xvals[,sample(1:1000, 10)]
df <- data.frame(y = ys, selecteds)
summary(lm(paste("y ~", paste0("X", 1:10, collapse = "+")), data = df))$r.squared
})
我对集群不是很有经验,但以下是您的代码可能太慢的几个原因:
- 您嵌套了 foor 循环来创建
X
,我使用了replicate
,这可能比使用列表快一些。 - 您生成的是一个空列表,
X
,这非常糟糕。 (勾选The R inferno - Circle 2) - 您取消列出了几个列表元素只是为了使它们成为 1 列矩阵,然后将它们全部绑定并最后命名列。尽管这些步骤似乎是必要的,但我认为一次一个地执行这些步骤可能很慢。例如,colnames 会自动设置为 X1:X10.
- 没有必要使用
attach
并且可能会减慢速度。 - 如果您 open/close 集群太多,会消耗大量处理,并且会比非并行更慢。不过好像不是这样。
最后一点,请确保我和你做的一样,因为这个问题对我来说仍然有点令人困惑。