我遇到嵌套循环问题,这是代码:
T=2
dt=0.001
K=floor(T/dt)
t= seq(0,T,dt)
BM<- matrix(0,2000,1000)
for (i in 1:1000){
for (k in 1:K-1){
BM[k+1,i]=BM[k,i]+sqrt(dt)*rnorm(1)
}
}
错误信息是:
Error in BM[k + 1, i] = BM[k, i] + sqrt(dt) * rnorm(1) :
replacement has length zero
循环有什么问题? 它的目标是模拟布朗运动的1000个样本路径。
答案 0 :(得分:3)
这是一个完全向量化的方法,它可以提供相同的结果,并且比使用for
循环更快
B <- mat.or.vec(K,1000) # pre-allocate
set.seed(1)
B[-1, ] <- matrix(rnorm((K-1)*100),K-1,1000) * sqrt(dt)
B <- apply(B, 2, cumsum)
矢量化函数可以加速您的代码,如下面的基准测试结果所示:
test elapsed relative
1 vectorized() 2.070 1.000
2 for.loop() 181.768 87.811
矢量化方法比两个嵌套for
- 循环快约88倍。基准代码如下所示。
for.loop <- function(){ # this is your approach
BM<- matrix(0,2000,1000)
set.seed(1)
for (i in 1:1000){
for (k in 1:(K-1)){
BM[k+1, i]=BM[k,i]+sqrt(dt)*rnorm(1)
}
}
return(BM)
}
vectorized <- function(){ # this is my approach
B <- mat.or.vec(K,1000) # pre-allocate
set.seed(1)
B[-1, ] <- matrix(rnorm((K-1)*100),K-1,1000) * sqrt(dt)
B <- apply(B, 2, cumsum)
}
library("rbenchmark")
benchmark(vectorized(),
for.loop(),
replications=10,
columns=c('test', 'elapsed', 'relative'),
order = "relative")
比较前5行和5列以检查结果:
> vectorized()[1:5, 1:5]
[,1] [,2] [,3] [,4] [,5]
[1,] 0.00000000 0.000000000 0.000000000 0.000000000 0.000000000
[2,] -0.01981021 -0.009865464 -0.008371525 0.015834886 0.001562361
[3,] -0.01400290 -0.037887974 -0.037253019 0.010349073 -0.024924006
[4,] -0.04042779 -0.098675011 -0.073133176 0.018483702 -0.066867547
[5,] 0.01001941 -0.047455576 -0.048955758 -0.001085329 -0.123356698
> for.loop()[1:5, 1:5]
[,1] [,2] [,3] [,4] [,5]
[1,] 0.00000000 0.000000000 0.000000000 0.000000000 0.000000000
[2,] -0.01981021 -0.009865464 -0.008371525 0.015834886 0.001562361
[3,] -0.01400290 -0.037887974 -0.037253019 0.010349073 -0.024924006
[4,] -0.04042779 -0.098675011 -0.073133176 0.018483702 -0.066867547
[5,] 0.01001941 -0.047455576 -0.048955758 -0.001085329 -0.123356698
答案 1 :(得分:2)
这是问题所在:
for (k in 1:K-1){
你的优先权已经结束。这将有效:
for (k in 1:(K-1)){
等价(对于K > 0
):
for (k in seq(K-1)){
矢量化更好:
for (k in seq(K-1)) {
BM[k+1,] <- BM[k,]+sqrt(dt)*rnorm(2000)
}