누군가가 를 시뮬레이션하는 방법을 알려줄 수 있습니까? 여기서 은 동전 던지기를 사용하여 (필요한 횟수만큼) ?
나는 거부 샘플링을 사용하려고 생각했지만 그것을 못 박았습니다.
누군가가 를 시뮬레이션하는 방법을 알려줄 수 있습니까? 여기서 은 동전 던지기를 사용하여 (필요한 횟수만큼) ?
나는 거부 샘플링을 사용하려고 생각했지만 그것을 못 박았습니다.
답변:
셀 수없이 많은 솔루션이 있으므로 효율적인 솔루션을 찾으십시오 .
이 아이디어의 기본 개념은 Bernoulli 변수를 구현하는 표준 방법으로 시작합니다. 균일 한 랜덤 변수 를 매개 변수 . 경우 반환 ; 그렇지 않으면 반환하십시오 .
coin을 균일 난수 생성기로 사용할 수 있습니다 . 간격 내에서 균일하게 숫자 를 생성하려면 동전을 뒤집습니다. 헤드 일 때 , 구간 의 첫 번째 부분 에서 균일 한 값 를 재귀 적으로 생성 합니다. 꼬리 일 때 구간 의 마지막 부분 에서 를 재귀 적으로 생성 합니다. 어떤 시점에서 목표 간격이 너무 작아서 실제로 숫자를 어떻게 선택하는지는 중요하지 않습니다. 이것이 재귀가 시작되는 방식입니다. 이 절차는 유도에 의해 쉽게 입증되는 바와 같이 균일 한 변이 (원하는 정밀도까지)를 생성하는 것이 분명합니다.
이 아이디어는 효율적이지 않지만 효율적인 방법으로 이어집니다. 각 단계에서 주어진 간격 에서 숫자를 그릴 것이기 때문에 , 먼저 그것을 그려야하는지 여부를 먼저 확인하지 않겠습니까? 목표 값이이 간격을 벗어난 경우 , 임의 값과 목표 값을 비교 한 결과를 이미 알고 있습니다. 따라서이 알고리즘은 빠르게 종료되는 경향이 있습니다. (이것은 질문에서 요청 된 거부 샘플링 절차 로 해석 될 수 있습니다 .)
이 알고리즘을 더 최적화 할 수 있습니다. 모든 단계에서 실제로 사용할 수 있는 두 개의 코인이 있습니다. 코인의 레이블을 다시 지정하면 우연히 헤드로 만들 수 있습니다 . 따라서 사전 계산으로 재 라벨을 사용하여 레이블을 다시 지정하여 종료에 필요한 예상 플립 횟수를 줄입니다. 이 계산은 비용이 많이 드는 단계 일 수 있습니다.
예를 들어, Bernoulli 변수를 직접 에뮬레이션하기 위해 코인을 사용하는 것은 비효율적 입니다. 평균적으로 거의 10 번의 뒤집기가 필요합니다. 그러나 코인을 사용한다면 단 두 번의 플립으로 확실하게 뒤집을 수 있으며 예상되는 플립 횟수는 입니다.
자세한 내용은 다음과 같습니다.
주어진 반 개방 구간 를 구간으로 분할
이것은 반 개방 간격으로 작동 하는 두 가지 변환 및 를 정의합니다.
용어의 문제로, 만약 실수의 집합 이라면
는 의 하한을 의미합니다 : 모든 대한 . 마찬가지로, 의미 상부 행이다 .
쓰십시오 . (실제로 가 합리적인 것이 아니라 실제 라면 아무런 차이가 없습니다 ; 우리는 만 필요합니다 .)
원하는 Bernoulli 매개 변수를 사용하여 변량 를 생성하는 알고리즘은 다음과 같습니다 .
집합 과 .
반면 {토스 경화가 생성하는 . 집합 증가 .}
만약 다음 집합 . 그렇지 않으면 설정하십시오 .
예를 R
들어, 함수로서 alorithm 의 구현이 있습니다 draw
. 인수는 목표 값 와 간격 이며 처음에는 입니다. 구현 하는 보조 기능을 사용합니다 . 반드시 필요한 것은 아니지만 동전 던지기 수를 추적합니다. 랜덤 변수, 던지기 횟수 및 마지막으로 검사 한 간격을 반환합니다.s
s <- function(x, ab, p) {
d <- diff(ab) * p
if (x == 1) c(ab[1], ab[1] + d) else c(ab[1] + d, ab[2])
}
draw <- function(target, p) {
between <- function(z, ab) prod(z - ab) <= 0
ab <- c(0,1)
n <- 0
while(between(target, ab)) {
n <- n+1; ab <- s(runif(1) < p, ab, p)
}
return(c(target > ab[2], n, ab))
}
정확도 사용 및 테스트의 예로 및 . 하자 그리 평균 (및 표준 오류)에 대한 알고리즘, 보고서를 사용하여 값을, 그리고 사용 넘겼의 평균 수를 나타냅니다.
target <- 0.01
p <- 0.9
set.seed(17)
sim <- replicate(1e4, draw(target, p))
(m <- mean(sim[1, ])) # The mean
(m - target) / (sd(sim[1, ]) / sqrt(ncol(sim))) # A Z-score to compare to `target`
mean(sim[2, ]) # Average number of flips
이 시뮬레이션 에서, 플립의 는 헤드였다. 목표 보다 낮지 만 의 Z- 점수는 하지 않습니다.이 편차는 우연의 원인 일 수 있습니다. 평균 플립 횟수는 10보다 조금 작습니다. 만약 코인을 사용했다면 , 평균은 였지만 여전히 목표와 크게 다르지 않았지만 평균 플립 만이 필요했을 것입니다.
여기 해결책이 있습니다 (지저분한 해결책이지만 내 첫 번째 찌르기입니다). 실제로 무시할 수 있으며 WLOG는 합니다. 왜? 2 개의 바이어스 코인 플립으로부터 바이어스되지 않은 코인 플립을 생성 하는 영리한 알고리즘 이 있습니다 . 따라서 라고 가정 할 수 있습니다 .
을 생성하기 위해 두 가지 솔루션을 생각할 수 있습니다 (첫 번째는 내 것이 아니라 두 번째는 일반화입니다).
편견이없는 동전을 번 뒤집 습니다. 경우 헤드가 존재하지 않는, 다시 시작. 헤드 가 경우 첫 번째 코인이 헤드인지 아닌지를 반환합니다 ( ).
이것은 값으로 확장 될 수 있습니다 . 쓰기 바이너리 형식이다. 예를 들어
우리는 동전 뒤집기를 사용하여 새로운 이진수를 만들 것입니다. 시작 하고 머리 (1) 또는 꼬리 (0)가 나타나는지 여부에 따라 숫자를 추가하십시오. 각각의 플립에서, 새로운 이진수와 의 이진 표현을 같은 숫자까지 비교하십시오 . 결국 두 개가 분기되고 가 이진수보다 크면 반환됩니다 .
파이썬에서 :
def simulate(p):
binary_p = float_to_binary(p)
binary_string = '0.'
index = 3
while True:
binary_string += '0' if random.random() < 0.5 else '1'
if binary_string != binary_p[:index]:
return binary_string < binary_p[:index]
index += 1
몇 가지 증거 :
np.mean([simulate(0.4) for i in range(10000)])
약 0.4입니다 (그러나 빠르지는 않습니다)
나는 간단한 해결책을 보았지만 의심 할 여지없이 여러 가지 방법이 있습니다. 이 방법은 두 단계로 나눌 수 있습니다.
불공평 한 동전 던지기 절차 (특정 동전과 동전이 확률 헤드를 생성하는 방법의 조합)가 주어지면 동일한 확률로 두 사건에서 생성됩니다 . 이 두 가지 가능한 이벤트 및 호출 할 수 있습니다 . [이에 대한 간단한 접근법이 있습니다. 와 를 짝으로하여 두 개의 똑같이 비슷한 결과를 생성해야합니다. 다른 모든 결과는 새로운 쌍을 생성합니다. 다시 시도하십시오.]
이제 시뮬레이션 된 공정한 동전을 사용하여 두 가지 흡수 상태로 무작위 보행을 생성합니다. 원점에서 흡수 상태의 거리를 선택하여 (위 및 아래) 하나의 흡수 상태를 원하는 정수 비율로 설정하여 흡수 확률을 설정할 수 있습니다. 당신의 위 흡수 장벽을 배치하면 특히, 과의 낮은 일 (원점에서 프로세스를 시작), 흡수 될 때까지 랜덤 워크 (random walk)를 실행, 위 장벽에서 흡수 확률은 입니다.
(여기서 계산해야 할 계산이 있지만 재귀 관계로 작업하여 확률을 상당히 쉽게 얻을 수 있습니다 ... 또는 무한 시리즈를 합산하여 다른 방법을 사용할 수 있습니다.)
[self-study]
태그 를 추가 하고 위키를 읽으십시오 . 질문 끝에 도움을 청할 필요는 없습니다. 여기에 글을 올리는 모든 사람이 도움을 원한다는 것을 알고 있습니다.