Использование гауссовой функции плотности вероятности в C ++

Во-первых, это правильное представление гауссовской функции PDF в C ++?

float pdf_gaussian = ( 1 / ( s * sqrt(2*M_PI) ) ) * exp( -0.5 * pow( (x-m)/s, 2.0 ) );

Во-вторых, имеет ли смысл делать что-то подобное?

if(pdf_gaussian < uniform_random())
   do something
else
   do other thing

РЕДАКТИРОВАТЬ: Пример того, чего именно вы пытаетесь достичь:

Скажем, у меня есть данные под названием Y1. Затем приходят новые данные под названием Си. Я хочу увидеть, следует ли связать Xi с Y1 или сохранить Xi в качестве новых данных, которые будут называться Y2. Это основано на расстоянии между новыми данными Xi и существующими данными Y1. Если Xi «далеко» от Y1, то Xi не будет связан с Y1, в противном случае, если он «недалеко», он будет связан с Y1. Теперь я хочу смоделировать это «далеко» или «недалеко», используя гауссовскую вероятность, основанную на среднем значении и стандартном отклонении расстояний между Y и данными, которые уже были связаны с Y в прошлом.


person shn    schedule 01.06.2012    source источник
comment
Не то, что я знаю из. Может, в учебнике по математике?   -  person Burkhard    schedule 01.06.2012
comment
Что ж, может быть лучше реализовать уравнение напрямую, как описано здесь en.wikipedia.org/wiki/Normal_distribution вместо использования наддува?   -  person shn    schedule 01.06.2012
comment
Возможный дубликат: stackoverflow.com/questions/2325472/   -  person ev-br    schedule 01.06.2012


Ответы (4)


да. boost::random имеет гауссовское распределение.

См., Например, этот вопрос: Как использовать классы нормального распределения boost?

В качестве альтернативы существует стандартный способ преобразования двух равномерно распределенных случайных чисел в два нормально распределенных числа.

См., Например, этот вопрос: Генерация случайных чисел в соответствии с нормальным распределением в C / C ++

В ответ на ваше последнее изменение (обратите внимание, что вопрос полностью отличается от редактируемого, поэтому мой ответ на исходный вопрос не имеет значения). Я думаю, вам лучше сначала сформулировать для себя, что именно вы имеете в виду, говоря «далеко или недалеко от модели с использованием гауссовского распределения». Затем переформулируйте это понимание в математических терминах и только после этого приступайте к программированию. В его нынешнем виде, я думаю, проблема недооценена.

person ev-br    schedule 01.06.2012
comment
но не функция плотности вероятности, которая принимает непосредственно в качестве входных данных среднее значение, стандартное отклонение и значение x? - person shn; 01.06.2012
comment
Что ж, может быть лучше реализовать уравнение напрямую, как описано здесь en.wikipedia.org/wiki/Normal_distribution вместо использования boost? - person shn; 01.06.2012
comment
вам нужно нормально распределенное случайное число или сам pdf? В последнем случае, конечно, введите формулу распределения и покончите с ней. - person ev-br; 01.06.2012
comment
Мне нужна функция pdf, так это правильное представление уравнения на C ++? (1 / (s * sqrt (2 * M_PI))) * exp (-0,5 * pow ((x-m) / s, 2,0)); - person shn; 01.06.2012
comment
тогда (а) ваше название вводит в заблуждение. (б) почему бы вам не закодировать этот однострочник и не сравнить результат для некоторых параметров с результатом вашего калькулятора. - person ev-br; 01.06.2012
comment
Есть ли смысл, если мы сделаем что-то вроде: float pdf = ( 1 / ( s * sqrt(2*M_PI) ) ) * exp( -0.5 * pow( (x-m)/s, 2.0 ) ); if(pdf < uniform_random()) {do something} else {do other thing}? - person shn; 01.06.2012
comment
чего именно вы пытаетесь достичь? - person ev-br; 01.06.2012
comment
ну скажем, у меня есть данные под названием Y1. Затем приходят новые данные под названием Си. Я хочу увидеть, следует ли связать Xi с Y1 или сохранить Xi в качестве новых данных, которые будут называться Y2. Это основано на расстоянии между новыми данными Xi и существующими данными Y1. Если Xi далеко от Y1, то Xi не будет связан с Y1, в противном случае, если он находится недалеко, он будет связан с Y1. Теперь я хочу смоделировать это далеко или недалеко, используя гауссовскую вероятность, основанную на среднем значении и стандартном отклонении расстояний между Y и данными, которые уже были связаны с Y в прошлом. - person shn; 01.06.2012

Технически,

float pdf_gaussian = ( 1 / ( s * sqrt(2*M_PI) ) ) * exp( -0.5 * pow( (x-m)/s, 2.0 ) );

не является неправильным, но может быть улучшен.

Во-первых, 1 / sqrt(2 Pi) можно вычислить заранее, и использование pow с целыми числами не является хорошей идеей: вместо простого x * x можно использовать exp(2 * log x) или процедуру, специализированную для экспонентов с плавающей запятой.

Пример лучшего кода:

float normal_pdf(float x, float m, float s)
{
    static const float inv_sqrt_2pi = 0.3989422804014327;
    float a = (x - m) / s;

    return inv_sqrt_2pi / s * std::exp(-0.5f * a * a);
}

Вы можете сделать это шаблоном вместо использования float:

template <typename T>
T normal_pdf(T x, T m, T s)
{
    static const T inv_sqrt_2pi = 0.3989422804014327;
    T a = (x - m) / s;

    return inv_sqrt_2pi / s * std::exp(-T(0.5) * a * a);
}

это позволяет вам также использовать normal_pdf с double аргументами (хотя это не намного более универсально). В отношении последнего кода есть предостережения, а именно: вы должны остерегаться использовать его с целыми числами (есть обходные пути, но это делает процедуру более многословной).

person Alexandre C.    schedule 01.06.2012
comment
но я не понимаю, почему функция гауссовского pdf возвращает небольшие значения от 0 до 1 по сравнению с равномерным распределением? вы видели пример, который я привел: if(pdf_gaussian < uniform_random()) do something else do other thing Или мне следует сравнить pdf_gaussian с normal_random () вместо uniform_random ()? - person shn; 01.06.2012

Используйте преобразование Бокса-Мюллера. Это создает значения с нормальным / гауссовым распределением.

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

http://en.wikipedia.org/wiki/Box_Muller_transform

Кодировать с использованием математических библиотек не так уж сложно.

eg.

Сгенерируйте 2 одинаковых числа, используйте их, чтобы получить два нормально распределенных числа. Затем верните один и сохраните другой, чтобы он у вас был для вашего «следующего» запроса случайного числа.

person Totero    schedule 01.06.2012

Начиная с C ++ 11, std::normal_distribution, определенный в стандартном заголовке random, может использоваться для генерации гауссовских случайных выборок. Дополнительную информацию можно найти здесь.

person Andrew Tomazos    schedule 01.06.2012