如何在 R 中进行并行化 k-means?
How to do parallelization k-means in R?
我有一个非常大的数据集 (5000*100),我想使用 kmeans
函数来查找聚类。但是,我不知道如何使用clusterApply
函数。
set.seed(88)
mydata=rnorm(5000*100)
mydata=matrix(data=mydata,nrow = 5000,ncol = 100)
parallel.a=function(i) {
kmeans(mydata,3,nstart = i,iter.max = 1000)
}
library(parallel)
cl.cores <- detectCores()-1
cl <- makeCluster(cl.cores)
clusterSetRNGStream(cl,iseed=1234)
fit.km = clusterApply(cl,x,fun=parallel.a(500))
stopCluster(cl)
clusterApply
需要 'x' 值,我不知道如何设置。另外,clusterApply
、parSapply
和parLapply
有什么区别?非常感谢。
这是一种使用 clusterApply
通过并行化 nstart
参数(假设它大于一个)来执行并行 kmeans 的方法:
library(parallel)
nw <- detectCores()
cl <- makeCluster(nw)
clusterSetRNGStream(cl, iseed=1234)
set.seed(88)
mydata <- matrix(rnorm(5000 * 100), nrow=5000, ncol=100)
# Parallelize over the "nstart" argument
nstart <- 100
# Create vector of length "nw" where sum(nstartv) == nstart
nstartv <- rep(ceiling(nstart / nw), nw)
results <- clusterApply(cl, nstartv,
function(n, x) kmeans(x, 3, nstart=n, iter.max=1000),
mydata)
# Pick the best result
i <- sapply(results, function(result) result$tot.withinss)
result <- results[[which.min(i)]]
print(result$tot.withinss)
人们通常将 mydata
输出给工人,但此示例将其作为附加参数传递给 clusterApply
。这是有道理的(因为任务的数量等于工人的数量),效率稍微高一点(因为它有效地将导出与计算结合起来),并且避免在集群工人上创建全局变量(这有点多整齐的)。 (当然,如果您计划使用该数据集对工作人员执行更多计算,则导出更有意义。)
请注意,您可以根据需要使用 detectCores()-1
个工作人员,但在我的机器上进行的基准测试表明,使用 detectCores()
个工作人员时它的执行速度要快得多。我建议您在您的机器上对其进行基准测试,看看哪个更适合您。
至于不同并行函数之间的区别,clusterApply
是lapply
的并行版本,它在单独的任务中处理x
的每个值。 parLapply
是 lapply
的并行版本,它将 x
拆分为每个集群 worker 只发送一个任务(这样效率更高)。 parSapply
调用 parLapply
但简化结果的方式与 sapply
简化调用 lapply
.
的结果相同
clusterApply
对于并行 kmeans 有意义,因为您手动拆分 nstart
这样它只向每个集群工作人员发送一个任务,从而使 parLapply
变得不必要。
我有一个非常大的数据集 (5000*100),我想使用 kmeans
函数来查找聚类。但是,我不知道如何使用clusterApply
函数。
set.seed(88)
mydata=rnorm(5000*100)
mydata=matrix(data=mydata,nrow = 5000,ncol = 100)
parallel.a=function(i) {
kmeans(mydata,3,nstart = i,iter.max = 1000)
}
library(parallel)
cl.cores <- detectCores()-1
cl <- makeCluster(cl.cores)
clusterSetRNGStream(cl,iseed=1234)
fit.km = clusterApply(cl,x,fun=parallel.a(500))
stopCluster(cl)
clusterApply
需要 'x' 值,我不知道如何设置。另外,clusterApply
、parSapply
和parLapply
有什么区别?非常感谢。
这是一种使用 clusterApply
通过并行化 nstart
参数(假设它大于一个)来执行并行 kmeans 的方法:
library(parallel)
nw <- detectCores()
cl <- makeCluster(nw)
clusterSetRNGStream(cl, iseed=1234)
set.seed(88)
mydata <- matrix(rnorm(5000 * 100), nrow=5000, ncol=100)
# Parallelize over the "nstart" argument
nstart <- 100
# Create vector of length "nw" where sum(nstartv) == nstart
nstartv <- rep(ceiling(nstart / nw), nw)
results <- clusterApply(cl, nstartv,
function(n, x) kmeans(x, 3, nstart=n, iter.max=1000),
mydata)
# Pick the best result
i <- sapply(results, function(result) result$tot.withinss)
result <- results[[which.min(i)]]
print(result$tot.withinss)
人们通常将 mydata
输出给工人,但此示例将其作为附加参数传递给 clusterApply
。这是有道理的(因为任务的数量等于工人的数量),效率稍微高一点(因为它有效地将导出与计算结合起来),并且避免在集群工人上创建全局变量(这有点多整齐的)。 (当然,如果您计划使用该数据集对工作人员执行更多计算,则导出更有意义。)
请注意,您可以根据需要使用 detectCores()-1
个工作人员,但在我的机器上进行的基准测试表明,使用 detectCores()
个工作人员时它的执行速度要快得多。我建议您在您的机器上对其进行基准测试,看看哪个更适合您。
至于不同并行函数之间的区别,clusterApply
是lapply
的并行版本,它在单独的任务中处理x
的每个值。 parLapply
是 lapply
的并行版本,它将 x
拆分为每个集群 worker 只发送一个任务(这样效率更高)。 parSapply
调用 parLapply
但简化结果的方式与 sapply
简化调用 lapply
.
clusterApply
对于并行 kmeans 有意义,因为您手动拆分 nstart
这样它只向每个集群工作人员发送一个任务,从而使 parLapply
变得不必要。