답변:
확률 밀도 함수에 대한 중철 근사화 (질량 함수에 대해서도 동일하게 작동하지만 밀도 측면에서만 여기서 이야기 할 것임)는 놀랍도록 잘 작동하는 근사치이며, 중앙 한계 정리의 개선으로 볼 수 있습니다. 따라서 중앙 제한 정리가있는 설정에서만 작동하지만 더 강력한 가정이 필요합니다.
모멘트 생성 기능이 존재하고 두 배의 차별화가 가능하다는 가정부터 시작합니다. 이것은 특히 모든 순간이 존재 함을 의미합니다. 하자 모멘트 생성 함수 (MGF)과 랜덤 변수 일
이제 우리는 이것을보다 유용한 형태로 만들기 위해 약간의 작업을해야합니다.
에서 우리 GET
와 관련하여 이것을 구별 하면
(가정에 따라), 따라서 와 의 관계 는 모노톤이므로 는 잘 정의되어 있습니다. 대한 근사가 필요합니다 . 이를 위해 우리는
를 결정할 때 지금 놓친 것은
그리고 새들 포인트 방정식 x_t의 암시 적 미분으로 찾을 수 있습니다 .
결과는 (최대 우리의 근사치)은
모두를 함께두기 우리 밀도의 최종 saddlepoint 근사치가 등의
saddlepoint 근사 빈도에 따라 평균의 밀도에 근사치로 언급되는 IID 관찰 . 평균의 누적 생성 함수는 간단히 이므로 평균의 안장 근사값은
첫 번째 예를 살펴 보겠습니다. 표준 정규 밀도 에 근접하면 어떻게됩니까?
mgf는 따라서
이므로 새들 포인트 방정식은 x_t이고 새들 포인트 근사는
경우 근사는 정확합니다.
변환 도메인의 부트 스트랩은 평균의 부트 스트랩 분포에 대한 중철 점 근사를 사용하여 분석적으로 부트 스트랩을 수행 할 수 있습니다!
우리가 iid를 어떤 밀도 에서 분배 가정 합니다 (시뮬레이션 된 예에서는 단위 지수 분포를 사용합니다). 샘플에서 우리는 경험적 모멘트 생성 함수
을 계산 한 다음 경험적 cgf 입니다. 우리는 평균 에 대한 경험적 mgf와 평균 대한 경험적 cgf가 필요합니다.
안장 근사치를 구성하는 데 사용되는 . 다음은 일부 R 코드 (R 버전 3.2.3)입니다.
set.seed(1234)
x <- rexp(10)
require(Deriv) ### From CRAN
drule[["sexpmean"]] <- alist(t=sexpmean1(t)) # adding diff rules to
# Deriv
drule[["sexpmean1"]] <- alist(t=sexpmean2(t))
###
make_ecgf_mean <- function(x) {
n <- length(x)
sexpmean <- function(t) mean(exp(t*x))
sexpmean1 <- function(t) mean(x*exp(t*x))
sexpmean2 <- function(t) mean(x*x*exp(t*x))
emgf <- function(t) sexpmean(t)
ecgf <- function(t) n * log( emgf(t/n) )
ecgf1 <- Deriv(ecgf)
ecgf2 <- Deriv(ecgf1)
return( list(ecgf=Vectorize(ecgf),
ecgf1=Vectorize(ecgf1),
ecgf2 =Vectorize(ecgf2) ) )
}
### Now we need a function solving the saddlepoint equation and constructing
### the approximation:
###
make_spa <- function(cumgenfun_list) {
K <- cumgenfun_list[[1]]
K1 <- cumgenfun_list[[2]]
K2 <- cumgenfun_list[[3]]
# local function for solving the speq:
solve_speq <- function(x) {
# Returns saddle point!
uniroot(function(s) K1(s)-x,lower=-100,
upper = 100,
extendInt = "yes")$root
}
# Function finding fhat for one specific x:
fhat0 <- function(x) {
# Solve saddlepoint equation:
s <- solve_speq(x)
# Calculating saddlepoint density value:
(1/sqrt(2*pi*K2(s)))*exp(K(s)-s*x)
}
# Returning a vectorized version:
return(Vectorize(fhat0))
} #end make_fhat
(나는 이것을 다른 cgfs에 대해 쉽게 수정할 수있는 일반 코드로 작성하려고 시도했지만 코드는 여전히 강건하지 않습니다 ...)
그런 다음 단위 지수 분포에서 10 개의 독립적 인 관측치 샘플에이를 사용합니다. 우리는 일반적인 비모수 부트 스트래핑 "손으로"를 수행하고, 결과에 대한 부트 스트랩 히스토그램을 플로팅하고 안 장점 근사값을 오버 플롯합니다.
> ECGF <- make_ecgf_mean(x)
> fhat <- make_spa(ECGF)
> fhat
function (x)
{
args <- lapply(as.list(match.call())[-1L], eval, parent.frame())
names <- if (is.null(names(args)))
character(length(args))
else names(args)
dovec <- names %in% vectorize.args
do.call("mapply", c(FUN = FUN, args[dovec], MoreArgs = list(args[!dovec]),
SIMPLIFY = SIMPLIFY, USE.NAMES = USE.NAMES))
}
<environment: 0x4e5a598>
> boots <- replicate(10000, mean(sample(x, length(x), replace=TRUE)), simplify=TRUE)
> boots <- replicate(10000, mean(sample(x, length(x), replace=TRUE)), simplify=TRUE)
> hist(boots, prob=TRUE)
> plot(fhat, from=0.001, to=2, col="red", add=TRUE)
결과 플롯 제공 :
근사치가 다소 좋은 것 같습니다!
새들 포인트 근사와 크기 조정을 통합하여 더 나은 근사를 얻을 수 있습니다.
> integrate(fhat, lower=0.1, upper=2)
1.026476 with absolute error < 9.7e-07
이제이 근사에 기반한 누적 분포 함수를 수치 적분으로 찾을 수 있지만 직접 새들 포인트 근사를 만들 수도 있습니다. 그러나 그것은 다른 게시물에 대한 것입니다.
마지막으로, 일부 의견은 위의 개발에서 제외되었습니다. 에서 우리는 근사값은 본질적으로 세 번째 임기를 무시했다. 왜 그렇게 할 수 있습니까? 하나의 관찰은 정규 밀도 함수의 경우, 왼쪽 항이 아무 것도 기여하지 않으므로 근사값이 정확하다는 것입니다. 따라서, 안 장점 근사는 중앙 한계 정리의 개선이므로, 우리는 정상에 다소 가깝기 때문에 이것이 잘 작동합니다. 특정 예를 볼 수도 있습니다. 포아송 분포에 대한 안 장점 근사를보고, 왼쪽의 세 번째 항을 보면,이 경우에는 트리 감마 함수가됩니다.
마지막으로 왜 이름이? 복잡한 분석 기법을 사용하는 대체 파생물에서 유래 한 이름입니다. 나중에 우리는 그것을 볼 수 있지만 다른 게시물에서 볼 수 있습니다!
여기서 kjetil의 대답을 확장하고 Cumulant Generating Function (CGF)을 알 수 없지만 데이터 , 추정 할 수있는 상황에 중점을 둡니다 . 가장 간단한 CGF 추정치는 아마도 Davison and Hinkley (1988) 의 추정치 일 것입니다. kjetil의 부트 스트랩 예에서 사용 된 하나입니다. 이 추정기는 새들 포인트 밀도를 평가하려는 지점 인 가 의 볼록 껍질 내에있는 경우에만 결과 새들 포인트 방정식 해결할 수 있다는 단점이 있습니다. .
((1992) 및 Fasiolo et al. (2016) 은 안장 방정식을 모든 대해 풀 수있는 방식으로 설계된 두 개의 대체 CGF 추정기를 제안함으로써이 문제를 해결했습니다 . Fasiolo 등의 해결책. 확장 된 Empirical Saddlepoint Approximation ESA (2016)는 esaddle R 패키지로 구현되었으며 여기에 몇 가지 예가 나와 있습니다.
간단한 일 변량 예제로 ESA를 사용하여 밀도 를 근사화하십시오 .
library("devtools")
install_github("mfasiolo/esaddle")
library("esaddle")
########## Simulating data
x <- rgamma(1000, 2, 1)
# Fixing tuning parameter of ESA
decay <- 0.05
# Evaluating ESA at several point
xSeq <- seq(-2, 8, length.out = 200)
tmp <- dsaddle(y = xSeq, X = x, decay = decay, log = TRUE)
# Plotting true density, ESA and normal approximation
plot(xSeq, exp(tmp$llk), type = 'l', ylab = "Density", xlab = "x")
lines(xSeq, dgamma(xSeq, 2, 1), col = 3)
lines(xSeq, dnorm(xSeq, mean(x), sd(x)), col = 2)
suppressWarnings( rug(x) )
legend("topright", c("ESA", "Truth", "Gaussian"), col = c(1, 3, 2), lty = 1)
이것은 맞습니다
깔개를 보면 데이터 범위 밖의 ESA 밀도를 평가 한 것이 분명합니다. 더 어려운 예는 다음과 같이 변형 된 이변 량 가우시안입니다.
# Function that evaluates the true density
dwarp <- function(x, alpha) {
d <- length(alpha) + 1
lik <- dnorm(x[ , 1], log = TRUE)
tmp <- x[ , 1]^2
for(ii in 2:d)
lik <- lik + dnorm(x[ , ii] - alpha[ii-1]*tmp, log = TRUE)
lik
}
# Function that simulates from true distribution
rwarp <- function(n = 1, alpha) {
d <- length(alpha) + 1
z <- matrix(rnorm(n*d), n, d)
tmp <- z[ , 1]^2
for(ii in 2:d) z[ , ii] <- z[ , ii] + alpha[ii-1]*tmp
z
}
set.seed(64141)
# Creating 2d grid
m <- 50
expansion <- 1
x1 <- seq(-2, 3, length=m)* expansion;
x2 <- seq(-3, 3, length=m) * expansion
x <- expand.grid(x1, x2)
# Evaluating true density on grid
alpha <- 1
dw <- dwarp(x, alpha = alpha)
# Simulate random variables
X <- rwarp(1000, alpha = alpha)
# Evaluating ESA density
dwa <- dsaddle(as.matrix(x), X, decay = 0.1, log = FALSE)$llk
# Plotting true density
par(mfrow = c(1, 2))
plot(X, pch=".", col=1, ylim = c(min(x2), max(x2)), xlim = c(min(x1), max(x1)),
main = "True density", xlab = expression(X[1]), ylab = expression(X[2]))
contour(x1, x2, matrix(dw, m, m), levels = quantile(as.vector(dw), seq(0.8, 0.995, length.out = 10)), col=2, add=T)
# Plotting ESA density
plot(X, pch=".",col=2, ylim = c(min(x2), max(x2)), xlim = c(min(x1), max(x1)),
main = "ESA density", xlab = expression(X[1]), ylab = expression(X[2]))
contour(x1, x2, matrix(dwa, m, m), levels = quantile(as.vector(dwa), seq(0.8, 0.995, length.out = 10)), col=2, add=T)
착용감이 꽤 좋습니다.
Kjetil의 위대한 답변 덕분에 나는 작은 예를 생각해 냈습니다.
분포를 고려하십시오 . 와 그 파생어는 여기 에서 찾을 수 있으며 아래 코드의 기능으로 재현됩니다.
x <- seq(0.01,20,by=.1)
m <- 5
K <- function(t,m) -1/2*m*log(1-2*t)
K1 <- function(t,m) m/(1-2*t)
K2 <- function(t,m) 2*m/(1-2*t)^2
saddlepointapproximation <- function(x) {
t <- .5-m/(2*x)
exp( K(t,m)-t*x )*sqrt( 1/(2*pi*K2(t,m)) )
}
plot( x, saddlepointapproximation(x), type="l", col="salmon", lwd=2)
lines(x, dchisq(x,df=m), col="lightgreen", lwd=2)
이것은 생산
이것은 분명히 밀도의 정 성적 특성을 얻는 근사치를 생성하지만 Kjetil의 의견에서 확인 된 것처럼 모든 곳의 정확한 밀도보다 높기 때문에 적절한 밀도가 아닙니다. 다음과 같이 근사값의 크기를 조정하면 다음과 같이 거의 무시할 수없는 근사 오차가 나타납니다.
scalingconstant <- integrate(saddlepointapproximation, x[1], x[length(x)])$value
approximationerror_unscaled <- dchisq(x,df=m) - saddlepointapproximation(x)
approximationerror_scaled <- dchisq(x,df=m) - saddlepointapproximation(x) /
scalingconstant
plot( x, approximationerror_unscaled, type="l", col="salmon", lwd=2)
lines(x, approximationerror_scaled, col="blue", lwd=2)
approximationerror_unscaled/approximationerror_scaled
25.90798 주위를 맴돌다