分布范围从 0 到 1,并且在它们之间有峰值?

机器算法验证 分布 正态分布
2022-01-25 13:43:08

是否有一个发行版,或者我可以从另一个发行版中创建一个如下图所示的发行版(为糟糕的图纸道歉)?

分配 其中我给出了一个数字(示例中为 0.2、0.5 和 0.9)来表示峰值的位置以及使函数更宽或更窄的标准偏差(sigma)。

PS:当给定数字为 0.5 时,分布是正态分布。

4个回答

一种可能的选择是beta 分布,但根据均值和精度重新参数化,即“对于固定的方差越小”(参见 Ferrari和 Cribari-Neto,2004 年)。概率密度函数是通过将 beta 分布的标准参数替换为μϕμϕyα=ϕμβ=ϕ(1μ)

f(y)=1B(ϕμ,ϕ(1μ))yϕμ1(1y)ϕ(1μ)1

其中E(Y)=μVar(Y)=μ(1μ)1+ϕ

或者,您可以计算适当参数,这些参数将导致具有预定义均值和方差的 beta 分布。但是,请注意,对于 beta 分布有效的可能方差值存在限制。就我个人而言,使用精度的参数化更直观(想想二项式分布比例,样本大小和成功概率)。αβx/ϕ Xϕμ

Kumaraswamy 分布是另一种有界连续分布,但像上面那样重新参数化会更困难。

正如其他人所注意到的,它不是正态分布,因为正态分布具有支持,所以充其量你可以使用截断的正态作为近似值。(,)

Ferrari, S. 和 Cribari-Neto, F. (2004)。用于建模率和比例的 Beta 回归。应用统计杂志,31(7),799-815。

我转换以创建这种变量。从一个随机变量 x 开始,它在整条实线上都有支持(如正常),然后将其转换为一个新的随机变量Presto,你有一个随机变量分布在单位间隔上。由于这种特定的变换正在增加,您可以通过移动 x 的均值/中值/众数来移动 y 的均值/中值/众数。想让更加分散(比如说,就四分位间距而言)?只是让更加分散。y=exp(x)1+exp(x)yx

没有什么特别之处任何累积分布函数都可以生成在单位间隔上定义的新随机变量。exp(x)1+exp(x)

因此,通过将其插入任何 cdf ( ) 进行转换的任何随机变量都可以满足您的需求——使 rv 分布在单位间隔上,您可以通过调整未转换随机变量的参数来方便地调整其属性以直观的方式。只要是严格单调的,转换后的变量就会在很多方面看起来像未转换的变量。例如,您希望是单位区间上的单峰随机变量。只要严格增加并且是单峰的,你就明白了。增加 的中值/均值/众数会增加的中值/均值/众数。增加四分位距y=F(x)F()yF()xxyx(通过向下移动第 25 个百分位和第 75 个百分位)增加的四分位数范围。严格的单调性是一件好事。y

计算的均值和 sd 的公式可能不容易找到,但这就是蒙特卡洛模拟的用途。要获得像您绘制的那样相对漂亮的分布,您希望是连续随机变量(连续随机变量的 cdf),并在实线上得到支持。yxF()

如果有人对我在 Python 中用于生成接近给定数字的随机值作为参数的解决方案感兴趣。我的解决方案分为四个阶段。每个阶段生成的数字更接近给定数字的机会更大。

我知道解决方案不如使用一个发行版那么漂亮,但这是我能够解决我的问题的方式:

number_factory.py:

import random
import numpy as np

class NumberFactory:
    def __init__(self):
        self.functions = [self.__linear, self.__exponential_point_four, self.__exponential_point_three, self.__exponential_point_twenty_five]  
        self.stage = 0

    def next_stage(self):
        self.stage += 1

    def get_mutated_number(self, number):
         # True if the generated number will be higher than the given number
         # False if the generated number will be lower than the given number
        add = bool(np.random.choice([0,1], p=[number, 1-number]))

        # Generate a number between 0 and 1 that will be used
        # to multiply the new number by which the number parameter will be substracted or added
        # The bigger the stage number (0-3) the more change that the mutated number is close to the number parameter
        multiply_number_seed = random.uniform(0, 1)
        multiply_number = self.functions[self.stage](multiply_number_seed)

        if (add):
            return number+((1-number)*multiply_number)
        else:
            return number-(number*multiply_number)

    def __linear(self, x):
        return -x+1

    def __exponential_point_four(self, x):
        return 0.4*x**2 - 1.4*x + 1

    def __exponential_point_three(self, x):
        return 0.8*x**2 - 1.8*x + 1

    def __exponential_point_twenty_five(self, x):
        return x**2 - 2*x + 1

    def get_stage(self):
        return self.stage

主要.py:

import matplotlib.pyplot as plt
import numpy as np

factory = NumberFactory()
numbers = []

factory.next_stage()
factory.next_stage()
factory.next_stage()

for _ in range(100000):
    numbers.append(factory.get_mutated_number(0.3))

bins = 100

plt.hist(numbers, bins, normed=True)
plt.plot(1, np.ones_like(bins))
plt.show()

执行此代码时的结果如下图所示: 图形

您可能想看看“约翰逊曲线”。请参阅 NL Johnson:由平移方法生成的频率曲线系统。1949 年 Biometrika 第 36 卷第 149-176 页。R 支持将它们拟合到任意曲线。特别是他的 SB(有界)曲线可能很有用。

我使用它们已有 40 年了,但它们当时对我非常有用,我认为它们会对你有用。