在C++中使用高斯概率密度函数

10

首先,这是高斯函数在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。我想要看看是否应将Xi与Y1相关联,或者是否应该将Xi作为一个新数据来命名为Y2。这基于新数据Xi与现有数据Y1之间的距离。如果Xi与Y1相距“远”,则Xi将不与Y1相关联;否则,如果它距离“不远”,它将与Y1相关联。现在,我想使用高斯概率模型来建模“远”或“不远”,并基于过去已经与Y相关联的数据的距离的均值和标准差。


我不知道。也许在数学书里可以找到? - Burkhard
也许直接实现这里描述的等式比使用boost库更好?http://en.wikipedia.org/wiki/Normal_distribution - shn
可能是重复问题:https://dev59.com/1XE95IYBdhLWcg3wadGq - ev-br
4个回答

12

从技术角度来看,

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

这段代码并没有错误,但是可以进行改进。

首先,1 / sqrt(2 Pi) 可以预先计算,并且使用 pow 函数来处理整数不是一个好的选择:它可能会使用 exp(2 * log x) 或专门针对浮点指数的例程,而不是简单地使用 x * 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);
}

这样可以使您能够在double参数上使用normal_pdf(尽管它不是那么通用)。但是,最后一段代码存在一些注意事项,即您必须小心不要将其与整数一起使用(虽然有解决方法,但这会使程序更加冗长)。

但是我不明白为什么高斯概率密度函数返回的一些小值在0和1之间,与均匀分布相比较?你看到我给出的关于这个例子了吗: if(pdf_gaussian < uniform_random()) do something else do other thing或者我应该将pdf_gaussian与normal_random()进行比较,而不是uniform_random()? - shn

2

是的,boost::random 有高斯分布。

例如,可以参考这个问题:如何使用boost正态分布类?

作为另一种选择,有一种标准方法将两个均匀分布的随机数转换为两个正态分布的随机数。

例如,可以参考这个问题:在C/C++中生成遵循正态分布的随机数

针对您最后的编辑(请注意,问题已完全改变,因此我的答案对原始问题无效),我认为您最好先明确“使用高斯分布进行建模”到底意味着什么。然后用数学术语重新表述这种理解,然后再开始编程。就目前而言,我认为该问题未明确说明。


但是不是概率密度函数,它直接以均值、标准差和值x作为输入? - shn
也许直接按照这里所描述的正态分布方程实现会比使用boost更好? - shn
你需要一个正态分布的随机数还是概率密度函数本身?如果是后者,当然可以输入分布的公式并完成它。 - ev-br
我需要pdf函数,那么这个C++方程式的表示是否正确?(1 / (s * sqrt(2*M_PI) ) ) * exp( -0.5 * pow( (x-m)/s, 2.0 ) ); - shn
如果我们这样做,是否有意义: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} - shn
显示剩余3条评论

2

-1
自C++ 11以来,可以使用标准头文件random中定义的std::normal_distribution生成高斯随机样本。更多信息可以在此处找到。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接