gpt4 book ai didi

r - 如何矢量化这个循环?将两个矩阵相乘,存储信息,多次执行此操作而不循环

转载 作者:行者123 更新时间:2023-12-01 18:57:00 26 4
gpt4 key购买 nike

假设(本例中的数字很小)我有一个数组

3 x 14 x 5

调用此

set.seed(1)
dfarray=array(rnorm(5*3*14,0,1),dim=c(3,14,5))

我有一个与此相对应的矩阵,是

39 (which is 13*3) x 14

调用这个矩阵:

dfmat = matrix(rnorm(13*3*14,0,1),39,14)
dfmat = cbind(dfmat,rep(1:3,13))
dfmat = dfmat[order(dfmat [,15]),]
colnames(dfmat)[15]='unit'

我想做的是运行这个循环:

 costs = c(0.45, 2.11, 1.05, 1.44, 0.88, 2.30, 1.96, 1.76, 2.06, 1.54, 1.69,1.75,0)
p = c(1,2,3,1,4,3,2,1,4,1,3,4,0)
profit=numeric(0)
for(i in 1:3){
j=13
beta = dfarray[i,,]
Xt = dfmat [which(dfmat [,'unit']==i),1:14] #this takes a set of 13, Xt is 13x14

Xbeta = exp( Xt %*% beta )
iota = c(rep(1, j))
denom = iota%*%Xbeta
Prob = (Xbeta/ (iota%*%denom))
Eprob = rowSums(Prob)/5 #the 5 coming from the last dim of array
profit = c(profit,sum((p-costs)*Eprob))

}


sum(profit)

我想不出一种方法来通过调用来矢量化循环所绕过的部分

beta = dfarray[i,,]
Xt = dfmat [which(dfmat [,'unit']==i),] #this takes a set of 13, Xt is 13x14

最佳答案

为了清楚地表达我在评论栏中的言论,假设我们有 dfmat作为矩阵列表。使用一系列矩阵几乎总是比使用一个大的命名矩阵更容易。此外,如果您想完全矢量化此处给出的解决方案,您可能需要使用 bdiag 获得 block 对角矩阵来自Matrix作用于列表的包。

set.seed(1)
dfarray=array(rnorm(5*3*14,0,1),dim=c(3,14,5))
# dfmats as a list of matrices
dfmats <- lapply(1:3, function(i)matrix(rnorm(13*14), nrow=13))

乘以iotacolSumsrowSums ,因此我们可以简化操作,如f .

f <- function(Xbeta) rowSums(Xbeta / matrix(colSums(Xbeta), nrow=nrow(Xbeta), ncol=ncol(Xbeta), byrow=T)) / ncol(Xbeta)
#profits is written as a function for benchmarking
#cost and p are ignored as they can be easily added back in.
profits <- function(){
Xbetas <- lapply(seq_len(dim(dfarray)[1]), function(i) exp(dfmats[[i]] %*% dfarray[i,,]))
Eprobs <- lapply(Xbetas, f)
unlist(Eprobs)
}

以及你的方法

profits1 <- function(){
profit=numeric(0)
for(i in 1:dim(dfarray)[1]){
j=13
beta = dfarray[i,,]
Xt = dfmat [which(dfmat [,'unit']==i),1:14] #this takes a set of 13, Xt is 13x14

Xbeta = exp( Xt %*% beta )
iota = c(rep(1, j))
denom = iota%*%Xbeta
deno <- colSums(Xbeta)
s <- iota%*%denom
Prob = (Xbeta/ s)
Eprob = rowSums(Prob)/dim(dfarray)[3] #the 100 coming from the last dim of array
profit = c(profit,Eprob)

}
return(profit)
}
dfmat <- do.call(rbind, dfmats)
dfmat <- cbind(dfmat,rep(1:3, each=13))
colnames(dfmat)[15]='unit'

检查它们是否给出相同的结果

all.equal(profits(), profits1())
[1] TRUE

基准

我在通过http://www.louisaslett.com/RStudio_AMI/访问的AWS EC2免费实例上运行了这个.

dfarray=array(rnorm(100*10000*14,0,1),dim=c(10000,14,100))
dfmats <- lapply(1:10000, function(i)matrix(rnorm(13*14), nrow=13))

从您的初始构造中,您可以转换 dfmat列表 dfmatsdfmats <- lapply(1:3, function(i)dfmat[which(dfmat [,'unit']==i),1:14])但这是一次成本非常高昂的转变。创建dfmat来自dfmats成本相当低。

dfmat <- do.call(rbind, dfmats)
dfmat <- cbind(dfmat,rep(1:10000, each=13))
colnames(dfmat)[15]='unit'

请注意,使用 list 可以显着提高速度,以及可怕的名称查找成本的危险。

system.time(a1 <- profits1())
# user system elapsed
#250.885 4.442 255.394
system.time(a <- profits())
# user system elapsed
# 2.717 0.429 3.167
all.equal(a, a1)
#[1] TRUE

PS:我注意到您提出了几个可能与此问题相关的问题,并且已全部回答。如果您分享如何成功地利用它们,我会很高兴。

关于r - 如何矢量化这个循环?将两个矩阵相乘,存储信息,多次执行此操作而不循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28950443/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com