히스토그램과 일치하는 포인트를 어떻게 생성합니까?
-
05-07-2019 - |
문제
시뮬레이션 시스템을 작업 중입니다. 곧 여러 시뮬레이션 입력에 대한 값의 실제 분포에 대한 실험 데이터 (히스토그램)를 가질 것입니다.
시뮬레이션이 실행되면 측정 된 분포와 일치하는 임의의 값을 생성하고 싶습니다. 원래 히스토그램을 저장하지 않고이 작업을 선호합니다. 좋은 방법은 무엇입니까?
- 히스토그램을 분포를 나타내는 매개 변수 세트에 매핑 하는가?
- 런타임에서 해당 매개 변수를 기반으로하는 값을 생성합니까?
편집 : 입력 데이터는 여러 유형의 이벤트에 대한 이벤트 기간입니다. 다른 유형마다 분포 기능이 다를 것으로 예상됩니다.
해결책
최소한 두 가지 옵션 :
- 히스토그램을 통합하고 수치 적으로 반전시킵니다.
- 배제
숫자 통합
에서 현대 물리학의 계산 William R. Gibbs :
하나는 항상 [함수]를 숫자로 통합하고 [CDF] 그러나 이것은 종종 특히 만족스럽지 않습니다. PDF 빠르게 변화하고 있습니다.
문자 그대로 범위를 번역하는 테이블을 작성합니다. [0-1)
대상 분포에서 적절한 범위로. 그런 다음 평소 (고품질) PRNG를 던지고 테이블로 번역하십시오. 그것은 번거롭지 만 명확하고 실행 가능하며 완전히 일반적입니다.
배제:
그러면 대상 히스토그램을 정규화하십시오
- 주사위를 던져 위치를 선택하십시오 (
x
) 범위를 따라 무작위로. - 다시 던지고 새로운 임의의 숫자 가이 빈의 정규화 된 히스토그램보다 낮 으면이 점을 선택하십시오. 그렇지 않으면 goto (1).
다시 말하지만, 단순한 마음이 있지만 명확하고 일합니다. 매우 낮은 확률 (긴 꼬리가있는 피크)로 분포가 느리게 진행될 수 있습니다.
이 두 가지 방법 모두로, 당신 ~할 수 있다 스텝-기능 히스토그램이 필요하지 않은 경우, 부드러운 곡선을 생성하기 위해 부분 다항식 또는 스플라인으로 데이터를 근사화하십시오.
특별한 경우에는 더 나은 방법이 존재할 수 있습니다.
이 모든 것은 매우 표준이며 자세한 내용이 필요한 경우 숫자 분석 교과서에 나타나야합니다.
다른 팁
문제에 대한 자세한 정보가 유용합니다. 예를 들어, 히스토그램은 어떤 종류의 값을 초과합니까? 그것들은 범주 형 (예 : 색상, 문자) 또는 연속 (예 : 높이, 시간)입니까?
히스토그램이 범주 형 데이터를 초과하는 경우 범주간에 많은 상관 관계가없는 한 분포를 매개 변수화하기가 어려울 수 있습니다.
히스토그램이 연속적 인 데이터 인 경우 가우시안의 혼합물을 사용하여 분포에 맞도록 시도 할 수 있습니다. 즉, $ sum_ {i = 1}^n w_i n (m_i, v_i) $를 사용하여 히스토그램을 맞추십시오. 그런 다음 데이터를 생성하려면 먼저 가중치 w_i에 비례하는 확률로 1에서 1에서 i를 샘플링 한 다음 모든 가우스에서와 같이 x ~ n (m_i, v_i)을 샘플링합니다.
어느 쪽이든, 당신은 혼합 모델.
그래서 주어진 probablity 분포를 생성하기 위해 내가 원하는 것은 양자 기능, 그것은 반대입니다누적 분포 함수, @dmckee가 말한 것처럼.
문제는 다음과 같습니다. 주어진 연속 히스토그램을 설명하는 Quantile 함수를 생성하고 저장하는 가장 좋은 방법은 무엇입니까? 나는 대답이 입력의 모양에 크게 의존 할 것이라고 생각합니다. 어떤 종류의 패턴을 따르는 경우 가장 일반적인 경우에 비해 단순화해야합니다. 내가 갈 때 여기서 업데이트하겠습니다.
편집하다:
이번 주 에이 문제를 생각 나게하는 대화를 나누었습니다. 히스토그램을 방정식으로 묘사하고 테이블을 저장하는 경우 O (1) 시간으로 선택할 수 있습니까? 정밀도 손실없이 O (n lgn) 시공 시간의 비용으로 가능하다는 것이 밝혀졌습니다.
N 항목 배열을 만듭니다. 배열로의 균일 랜덤 선택은 probablilty 1/n의 항목을 찾을 수 있습니다. 각 항목에 대해이 항목을 실제로 선택 해야하는 히트의 일부 와이 항목의 색인을 저장하십시오.
가중 무작위 샘플링, C 구현 :
//data structure
typedef struct wrs_data {
double share;
int pair;
int idx;
} wrs_t;
//sort helper
int wrs_sharecmp(const void* a, const void* b) {
double delta = ((wrs_t*)a)->share - ((wrs_t*)b)->share;
return (delta<0) ? -1 : (delta>0);
}
//Initialize the data structure
wrs_t* wrs_create(int* weights, size_t N) {
wrs_t* data = malloc(sizeof(wrs_t));
double sum = 0;
int i;
for (i=0;i<N;i++) { sum+=weights[i]; }
for (i=0;i<N;i++) {
//what percent of the ideal distribution is in this bucket?
data[i].share = weights[i]/(sum/N);
data[i].pair = N;
data[i].idx = i;
}
//sort ascending by size
qsort(data,N, sizeof(wrs_t),wrs_sharecmp);
int j=N-1; //the biggest bucket
for (i=0;i<j;i++) {
int check = i;
double excess = 1.0 - data[check].share;
while (excess>0 && i<j) {
//If this bucket has less samples than a flat distribution,
//it will be hit more frequently than it should be.
//So send excess hits to a bucket which has too many samples.
data[check].pair=j;
// Account for the fact that the paired bucket will be hit more often,
data[j].share -= excess;
excess = 1.0 - data[j].share;
// If paired bucket now has excess hits, send to new largest bucket at j-1
if (excess >= 0) { check=j--;}
}
}
return data;
}
int wrs_pick(wrs_t* collection, size_t N)
//O(1) weighted random sampling (after preparing the collection).
//Randomly select a bucket, and a percentage.
//If the percentage is greater than that bucket's share of hits,
// use it's paired bucket.
{
int idx = rand_in_range(0,N);
double pct = rand_percent();
if (pct > collection[idx].share) { idx = collection[idx].pair; }
return collection[idx].idx;
}
편집 2 : 약간의 연구 후에, 나는 O (n) 시간으로 건설을 할 수 있음을 알았습니다. 신중한 추적을 사용하면 크고 작은 쓰레기통을 찾기 위해 배열을 정렬 할 필요가 없습니다. 여기에서 업데이트 된 구현
이산 지점의 가중 분포로 많은 수의 샘플을 뽑아야한다면 비슷한 질문에 대한 답.
그러나 히스토그램을 사용하여 연속 랜덤 함수를 근사해야한다면 가장 좋은 방법은 아마도 DMCKEE의 숫자 통합 답변 일 것입니다. 또는 별명을 사용하고 왼쪽에 지점을 저장하고 두 지점 사이에서 균일 한 번호를 선택할 수 있습니다.
히스토그램 (원본 또는 축소) 중에서 선택하려면워커의 별칭 방법빠르고 간단합니다.
정규 분포의 경우 다음이 도움이 될 수 있습니다.
http://en.wikipedia.org/wiki/normal_distribution#generating_values_for_normal_random_variables