세 가지 문제가 있습니다.
먼저 재귀를위한 초기 사례가 필요합니다. 다음은 무한 재귀를 유도합니다 (i
의 값은 계속 감소하지만 결코 멈추지 않습니다).
f <- function(i) g(i-1)
g <- function(i) g(i-1) + f(i)
f(5)
다음과 같습니다.
f <- function(i) g(i-1)
g <- function(i) if(i <= 0) 0 else g(i-1) + f(i)
f(5)
두 번째 문제점은 이러한 값 중 일부가 지수 적 횟수로 다시 계산된다는 것입니다.
f(500) # Too long
더 추상화 관점에서 에지 함수 호출에 대응 i
, 의 모든 값에 대한 꼭지점과 f(i)
g(i)
이 그래프를 고려한다. 재귀를 사용하면이 그래프를 마치 나무처럼 탐색 할 수 있습니다. 그러나이 경우에는 트리가 아니므로 동일한 기능을 (동일한 노드를 탐색하는) 매우 많은 횟수로 평가하게됩니다. 다음 코드는이 그래프를 그립니다.
library(igraph)
n <- 5
g <- graph.empty()
g <- g + vertices(paste0("f(", 1:n, ")"))
g <- g + vertices(paste0("g(", 0:n, ")"))
for(i in 1:n) {
g <- g + edge(paste0("f(", i ,")"), paste0("g(", i-1, ")"))
g <- g + edge(paste0("g(", i ,")"), paste0("f(", i, ")"))
g <- g + edge(paste0("g(", i ,")"), paste0("g(", i-1, ")"))
}
plot(g)
한 가지 해결 방법은 당신이 이미 그들을 다시 계산 피하기 위해 계산 한 값을 저장하는 것입니다 이 memoization라고합니다. 이 기능을 memoise 때
library(memoise)
f <- function(i) G(i-1)
g <- function(i) if(i <= 0) 1 else G(i-1) + F(i)
F <- memoize(f)
G <- memoize(g)
f(500)
은 재귀 호출의 수는 선형, 하게하지만 여전히 너무 클 수 있습니다.초기 오류 메시지에 의해 제안 당신이 한계를 증가시킬 수있다 :이 충분하지 않은 경우
options(expressions = 5e5)
, 당신은 i
의 점점 더 큰 값을 사용하여 테이블을 미리 채울 수 있습니다. 귀하의 예제와 :
options(expressions = 5e5)
loss(1000,10) # Does not work: Error: protect(): protection stack overflow
loss(500,10) # Automatically stores the values of loss(i,100) for i=1:500
loss(1000,10) # Works
셋째, 기능이 불필요하게 호출 스택의 크기를 증가 시킨다는 호출이있을 수 있습니다. 예를 들어, 오류 후 traceback()
을 입력하면 함수 인수 내에서 weight(i,k)
및 loss(i,k)
이 사용되므로 많은 중간 함수 이 호출 스택에 있음을 알 수 있습니다. 함수 인수 밖에서 이러한 호출을 이동하면 호출 스택이 작아지고 작동하는 것처럼 보입니다.
library(memoise)
gradient <- function(x,y,tau){
if (x-y > 0) { - tau }
else { (1-tau) }
}
aj <- c(-3,-4,-2,-3,-5,-6,-4,-5,-1,rep(-1,15))
f <- function(x,vec){sum(x^vec)-1}
root <- uniroot(f, interval=c(0,200), vec=aj)$root
memloss<-function(i,k){
cat("loss(", i, ",", k, ")\n", sep="")
if (i==1) {
c(rep(0,24))
} else if (i <= 0 | k < -5) {
0
} else {
w <- weight(i-1,k) # Changed
gradient(dailyreturn[i-1],w%*%A[i-1,],0.0025)*A[i-1,]
}
}
memweight <- function(i,k){
cat("weight(", i, ",", k, ")\n", sep="")
if (i==1) {
c(rep(root,24)^aj)
} else if (i <= 0 | k < -5) {
0
} else {
w <- weight(i-1,k) # Changed
l <- loss(i,k) # Changed
(exp(- (2^(k)/(sqrt(1415))) * l))/(w %*% exp(- 2^(k)/(sqrt(1415)) * l)) * w
}
}
loss <- memoize(memloss)
weight <- memoize(memweight)
A <- matrix(1, 1414, 24)
dailyreturn <- rep(1,2080)
options(expressions = 1e5)
loss(1400,10)
안녕하세요, 당신이 말한 것을 적용했지만 여전히 얻을 수 있습니다. 오류 : 중첩 된 평가 : 무한 재귀/옵션 (표현식 =)? – user1627466
[재현 가능한 예] (http://stackoverflow.com/questions/5963269/how-to-make-a-great-r-reproducible-example)를 제공해주십시오. –
예를 들어 주셔서 감사합니다. 나는 나의 대답을 업데이트했다. –