Как мне получить очки, которые соответствуют гистограмме? - PullRequest
11 голосов
/ 08 января 2009

Я работаю над системой моделирования. Скоро у меня будут экспериментальные данные (гистограммы) для реального распределения значений для нескольких входов моделирования.

Когда симуляция запускается, я бы хотел получить случайные значения, которые соответствуют измеренному распределению. Я бы предпочел сделать это без сохранения оригинальных гистограмм. Какие есть хорошие способы

  1. Отображение гистограммы в набор параметров, представляющих распределение?
  2. Генерация значений, основанных на этих параметрах во время выполнения?

РЕДАКТИРОВАТЬ: входные данные являются продолжительностью события для нескольких различных типов событий. Я ожидаю, что разные типы будут иметь разные функции распределения.

Ответы [ 6 ]

19 голосов
/ 08 января 2009

Как минимум два варианта:

  1. Интегрируйте гистограмму и инвертируйте численно.
  2. Отрицание

Числовая интеграция

С Вычисления в современной физике Уильям Р. Гиббс:

Всегда можно численно интегрировать [функцию] и инвертировать [ cdf ] но это часто не очень удовлетворительно, особенно если pdf меняется быстро.

Вы буквально строите таблицу, которая переводит диапазон [0-1) в соответствующие диапазоны в целевом распределении. Затем бросьте свой обычный (качественный) PRNG и переводите со стола. Он громоздок, но понятен, выполним и полностью универсален.

Отрицание:

Нормализуйте целевую гистограмму, затем

  1. Бросьте кости, чтобы случайным образом выбрать позицию (x) вдоль диапазона.
  2. Снова бросьте и выберите эту точку, если новое случайное число меньше нормализованной гистограммы в этом бине. В противном случае перейдите к (1).

Опять же, простой, но понятный и работающий. Распространение может быть медленным с очень малой вероятностью (пики с длинными хвостами).


Используя оба этих метода, вы можете аппроксимировать данные кусочно-полиномиальными подгонками или сплайнами, чтобы получить гладкую кривую, если гистограмма пошаговой функции не нужна, - но оставьте ее на потом, так как может быть преждевременная оптимизация.


В особых случаях могут существовать лучшие методы.

Все это довольно стандартно и должно появиться в любом учебнике по числовому анализу, если мне потребуется больше подробностей.

2 голосов
/ 08 января 2009

Дополнительная информация о проблеме будет полезна. Например, над какими значениями находятся гистограммы? Они категоричны (например, цвета, буквы) или непрерывны (например, высота, время)?

Если гистограммы превышают категориальные данные, я думаю, что может быть сложно параметризовать распределения, если между категориями нет большого количества корреляций.

Если гистограммы превышают непрерывные данные, вы можете попытаться согласовать распределение, используя смеси гауссианов. То есть попробуйте подогнать гистограмму, используя $ \ sum_ {i = 1} ^ n w_i N (m_i, v_i) $, где m_i и v_i - среднее значение и дисперсия. Затем, когда вы хотите сгенерировать данные, вы сначала выбираете a i из 1..n с вероятностью, пропорциональной весам w_i, а затем выбираете x ~ n (m_i, v_i), как если бы вы использовали любой гауссов.

В любом случае, вы можете прочитать больше о моделях смесей .

1 голос
/ 08 января 2009

Таким образом, мне кажется, что для генерации заданного распределения вероятности мне нужна квантильная функция , обратная совокупная функция распределения , как говорит @dmckee.

Возникает вопрос: как лучше всего сгенерировать и сохранить квантильную функцию, описывающую данную непрерывную гистограмму? У меня есть ощущение, что ответ будет во многом зависеть от формы ввода - если он следует какой-либо схеме, должны быть упрощения в наиболее общем случае. Я буду обновлять здесь, как я иду.


Edit:

У меня был разговор на этой неделе, который напомнил мне об этой проблеме. Если я перестану описывать гистограмму как уравнение и просто сохраню таблицу, могу ли я делать выборки за O (1) время? Оказывается, вы можете без потери точности за счет времени строительства O (N lgN).

Создать массив из N элементов. Равномерный случайный выбор в массиве найдет элемент с вероятностью 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) время. Благодаря тщательному отслеживанию вам не нужно сортировать массив, чтобы найти большие и маленькие ячейки. Обновленная реализация здесь

0 голосов
/ 20 октября 2009

Выбрать из гистограммы (оригинал или уменьшенная), Метод псевдонима Уокера это быстро и просто.

0 голосов
/ 08 января 2009

Если вам нужно вытащить большое количество выборок с взвешенным распределением дискретных точек, тогда посмотрите на ответ на аналогичный вопрос .

Однако, если вам нужно аппроксимировать некоторую непрерывную случайную функцию с помощью гистограммы, тогда, вероятно, лучшим вариантом будет числовой интеграционный ответ dmckee. Кроме того, вы можете использовать псевдонимы и сохранить точку слева и выбрать одинаковое число между двумя точками.

0 голосов
/ 08 января 2009

Для нормального распределения может помочь следующее:

http://en.wikipedia.org/wiki/Normal_distribution#Generating_values_for_normal_random_variables

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...