2016-11-11 1 views
0

Clojure를 사용하여 값의 정규 분포를 생성하는 방법은 무엇입니까? 실제적으로 반드시 정규 분포 일 필요는 없지만 비뚤어 질 수 있습니다.Clojure를 사용하여 종곡 곡선 데이터 생성

예를 들어 대기 중 산소 농도에 대해 생성 된 (의사 랜덤) 숫자를 볼륨별로 출력하는 함수를 만들고 싶습니다. 가능한 가장 낮은 산출량은 19.5 %이고 가능하면 최대 23.5 %이고 모달 값은 20.95 % 여야합니다. 이 함수는 꼬리의 아래 부분이 1.45 %의 범위를 가지며 높은 부분이 2.55 %의 범위 인이 '비뚤어진 정상'분포에 대해 작동해야합니다.

답변

2

확률 밀도 함수를 설명하는 함수 y=f(x)을 플롯 할 수 있다면 원하는 배포판을 얻는 간단한 방법이 있습니다. (- (XM)^2/(2 * S^2))/SQRT (2 * PI * s의^2)

( https://en.wikipedia.org/wiki/Gaussian_function 참조) 가우시안 들어

이 함수 (X) = EXP F이고

여기서 m은 x의 평균이고 s는 x의 표준 편차입니다.

m = 0 및 s = 1 인 "일반"가우시안의 경우, +/- 3 (정확한 양은 독자의 연습 문제로 남음) 밖에 "거의 절대"값이 없습니다. 이 근사값이 주어지면 가우스 분포를 얻는 가장 간단한 방법은 [-3..3] 간격의 x 부동 소수점 값과 [0..1] 간격의 y 값을 생성하는 것입니다. 위와 같이 f (x)를 계산합니다 : exp (...) 등. IFF y < = f (x), 임의의 값으로 x 값을 사용하십시오. 그렇지 않으면 x와 y를 모두 버리고 처음부터 다시 시작하십시오.

이 기술은 일부 (또는 여러) 값을 버리는 반면 매우 간단하고 방탄입니다.

"기울기 가우스"근사법과 비슷한 방법을 사용할 수 있습니다. 설명 된대로 f (x)를 정의하면됩니다. 아주 간단하게는 (19.5,0)에서 (20.95,1)에서 (23.5,0)까지의 직선 근사를 사용할 수도 있습니다. 여기서 f (x)에 대해 삼각형 모양을 만듭니다. 이 경우 간격 [19.5..23.5]에서 x를 그리고 f (x)에 대해 오른쪽 &의 오른쪽 절반에 대한 직선 수식을 계산합니다. 이전과 마찬가지로 [0..1]에 y를 그립니다. 이 구현은 앨런 톰슨의 대답 아이디어 두 가지에서 영감을 https://en.wikipedia.org/wiki/Rejection_sampling

0

:

난 그냥 위키 백과 자세한 내용이 설명 발견 다소의 종형 곡선의 종류보다, '거부 샘플링'삼각형을 사용하여 모양 즉 스케일링.

(defn generator [modal-val low-val high-val] 
    (fn [] 
    (let [gen-val (fn [] 
        (let [diff-range (- high-val low-val) 
          picked-in-range (rand diff-range) 
          perhaps-res (+ low-val picked-in-range) 
          ;; partial distance left or right, that will be negative if to left 
          modal-delta (- perhaps-res modal-val) 
          extremity (if (neg? modal-delta) low-val high-val) 
          ;; full distance left or right, that will be negative if to left 
          total-dist (- extremity modal-val) 
          closeness-to-modal (- 1 (/ modal-delta total-dist)) 
          ] 
         (when (<= (rand) closeness-to-modal) 
         perhaps-res)))] 
     (first (drop-while nil? (repeatedly gen-val)))))) 

다음과 같이 사용할 수 있습니다

((generator 20.95 19.5 23.5)) 
+0

fwiw, Clojure의'rand'는 Java의'Random'에 기초합니다. 따라서 후자가 주어진 용도에 대해 충분히 높은 품질의 난수 생성기가 아니면'rand'도 아닙니다. 그러나 많은 상황에서 충분히 좋습니다. – Mars

2

당신은 (비 기울어) 정규 분포 번호를 생성하기 위해 주문 술사의 sample-normal를 사용할 수 있습니다. 예를 들어,이 평균 2, 표준 편차 5 20 개 정규 분포 값을 생성합니다

(ns foo 
    (:use [incanter.stats])) 

(sample-normal 20 :mean 2 :sd 5) 

당신은 또한 숀 누가 복음의 MersenneTwisterFast으로 자바에서 자바의 Random 또는 더 나은 난수 생성기를 사용할 수 있습니다. 예를 들어 MersenneTwisterFast을 사용하려면 자바 소스 파일을 다운로드하고 예를 들어 Leiningen 프로젝트 트리의 src/java에 있습니다. 그런 다음 행을 :java-source-paths ["src/java"]과 같이 project.clj에 추가하십시오.Clojure의 소스 파일에서 :

(ns foo 
    (:import [ec.util MersenneTwisterFast])) 

(defn make-rng 
    "Make an instance of a MersenneTwisterFast RNG and flush out its initial 
    minimal lack of entropy." 
    [seed] 
    (let [rng (MersenneTwisterFast. seed)] 
    (dotimes [_ 1500] (.nextInt rng)) ; needed because of a quirk of Mersenne Twisters 
    rng)) 

(def my-rng (make-rng 42)) 

;; Now call this as many times as you want to generate standard Normal data: 
(.nextGaussian my-rng) 

은 다운로드하지 않고, 자바의 Random이 비슷합니다 사용 등 SRC/자바, 이동,하지만 난 당신이 1500 .nextInt 자바의 Random를 세척해야합니다 생각하지 않습니다 (임의의 숫자는 메르 센 트위스터의 임의의 숫자와 같지 않을 수도 있지만).

stats.SE에서 설명한 this answer에 따르면 설명 된 표준 편차로 위의 값을 곱한 다음 원하는 평균을 더하여 표준 정규 분포에서 임의의 정규 분포를 얻을 수 있습니다.

Alan Thompson의 대답은 일반 정규 분포에서 잘린 분포를 생성하는 방법을 설명합니다.

This answer (stats.SE)은 정규 분포에서 비뚤어진 정규 분포를 생성하는 것과 관련된 조언을 제공합니다.

+0

Thanks @ChrisMurphy. 네가 옳아. 이제 해결되었습니다. (실제로 사용하는 버전에는 두 가지 요소가 있으며 인수가 없으면 시드 생성 함수가 자동으로 호출됩니다. 여기에서는 명확하게하기 위해'make-rng'를 단순화했습니다.) – Mars

관련 문제