【问题标题】:Using the gaussian probability density function in C++在 C++ 中使用高斯概率密度函数
【发布时间】:2012-06-06 12:02:24
【问题描述】:

首先,这是 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 的新数据到达。我想看看我是否应该将 Xi 与 Y1 相关联,或者我是否应该将 Xi 保留为将称为 Y2 的新数据数据。这是基于新数据 Xi 和现有数据 Y1 之间的距离。如果 Xi 离 Y1 “远”,则 Xi 不会关联到 Y1,否则如果它“不远”,它将关联到 Y1。现在,我想根据 Y 与过去已与 Y 相关联的数据之间的距离的均值和标准差,使用高斯概率对这个“远”或“不远”进行建模。

【问题讨论】:

标签: c++ distribution probability gaussian normal-distribution


【解决方案1】:

自 C++ 11 起,标准头 random 中定义的 std::normal_distribution 可用于生成高斯随机样本。更多信息可以在herein找到。

【讨论】:

    【解决方案2】:

    技术上,

    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(虽然它不是那么通用)。最后一个代码有一些注意事项,即您必须注意不要将其与整数一起使用(有一些变通方法,但这会使例程更加冗长)。

    【讨论】:

    • 但我不明白为什么高斯 pdf 函数返回一些介于 0 和 1 之间的小值,与均匀分布相比?您是否看到我给出的示例:if(pdf_gaussian &lt; uniform_random()) do something else do other thing 或者我应该将 pdf_gaussian 与 normal_random() 而不是 uniform_random() 进行比较?
    【解决方案3】:

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

    例如,请参阅以下问题:How to use boost normal distribution classes?

    作为替代方案,有一种标准方法可以将两个均匀分布的随机数转换为两个正态分布的数字。

    见,例如这个问题:Generate random numbers following a normal distribution in C/C++

    作为对您上次编辑的回应(请注意,问题与已编辑完全不同,因此我对原始问题的回答是无关紧要的)。我认为您最好先自己制定“使用高斯分布建模远或不远”的确切含义。然后用数学术语重新表达这种理解,然后才开始编程。就目前而言,我认为问题未得到充分说明。

    【讨论】:

    • 而不是直接以均值和标准差以及x值作为输入的概率密度函数?
    • 嗯,也许最好直接实现这里描述的方程式 en.wikipedia.org/wiki/Normal_distribution 而不是使用 boost ?
    • 你需要一个正态分布的随机数还是pdf本身?当然,在后一种情况下,输入分布公式并完成
    • 我需要 pdf 函数,那么这是等式的正确 C++ 表示吗? ( 1 / ( s * sqrt(2*M_PI) ) ) * exp( -0.5 * pow( (x-m)/s, 2.0 ) );
    • 那么 (a) 您的标题具有误导性。 (b) 你为什么不把这个单行代码写进去,并将某些参数的结果与你的计算器的结果进行比较。
    【解决方案4】:

    使用 Box-Muller 变换。这将创建具有正态/高斯分布的值。

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

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

    使用数学库编写代码并不是很复杂。

    例如。

    生成 2 个均匀数,用它们得到两个正态分布数。然后返回一个并保存另一个,以便您将其用于“下一个”随机数请求。

    【讨论】:

      猜你喜欢
      • 2014-04-23
      • 1970-01-01
      • 2012-11-21
      • 2019-04-19
      • 1970-01-01
      • 1970-01-01
      • 2016-06-07
      • 2019-12-14
      • 1970-01-01
      相关资源
      最近更新 更多