[英]np.random.choice not producing expected histogram
我正在尋找生成 1 和 0 之間的random normally distributed
數字,但隨着mean
接近 1 或 0,右側或左側分別變得“壓扁”。
修改正態分布並在 geogebra 中使用滑塊后,我得出以下結論:
接下來我需要在python
中創建一個方法,它會生成隨機樣本,這些樣本將根據這個 PDF 進行分配。
最初我認為做到這一點的唯一方法是嘗試推導一個新的方程來生成隨機數,如Box-Muller
證明中所示(我通過跟隨本教程獲得)。
但是,我認為使用numpy
庫的np.random.choice()
方法可能有更簡單的方法來執行此操作。
畢竟,我應該能夠以非常小的步長對 PDF 進行積分,並獲得所述步長的各種概率(當然是近似值)。
因此,我編寫了以下腳本:
# Standard libs
import math
# Third party libs
import numpy as np
from alive_progress import alive_bar
from matplotlib import pyplot as plt
class RandomNumberGenerator:
def __init__(self):
pass
def clamped_normal_distribution(self, mu: float,
stddev: float, x: float):
""" Computes a value from the clamped normal distribution """
divideByZeroAvoider = 1e-5
if x < 0 or x > 1:
return 0
elif x >= 0 and x <= mu:
return math.exp(-0.5*( (x - mu) / (stddev) )**2 \
* (1/(x**2 + divideByZeroAvoider)))
elif x <= 1 and x > mu:
return math.exp(-0.5*( (x - mu) / (stddev) )**2 \
* (1/((1-x)**2 + divideByZeroAvoider)))
else:
print("This shouldn't happen!: {}".format(x))
return 0
if __name__ == '__main__':
rng = RandomNumberGenerator()
mu = 0.7
stddev = 1
stepSize = 1e-3
x = np.linspace(stepSize,1, int(1/stepSize) - 1)
# Determine the total area under the curve
samples = []
print("Generating samples...")
with alive_bar(len(x.tolist())) as bar:
for i in x:
samples.append(rng.clamped_normal_distribution(
mu, stddev, i))
bar()
area = np.trapz(samples, dx=stepSize)
print("Area = {}".format(area))
# Determine the probability of x falling in a specific interval
probabilities = []
print("Generating probabilties...")
with alive_bar(len(x.tolist())) as bar:
for i in x:
lead = rng.clamped_normal_distribution(mu,
stddev, i)
lag = rng.clamped_normal_distribution(mu,
stddev, i - stepSize)
probability = np.trapz(
np.array([lag, lead]),
dx=stepSize)
# Divide by the area because this isn't a standard normal
probabilities.append(probability / area)
bar()
# Should be approximately 1
print("Probability: {}".format(sum(probabilities)))
plt.plot(x, probabilities)
plt.show()
y = []
print("Performing distribution test...")
testSize = int(10e3)
with alive_bar(testSize) as bar:
for _ in range(testSize):
randSamp = np.random.choice(samples, p=probabilities)
y.append(randSamp)
bar()
plt.hist(y,300)
plt.show()
線性間隔樣本的第一個 plot 概率看起來很有希望,給出了下圖:
但是,如果我們使用這些樣本作為具有給定概率的選擇,我們將得到以下直方圖:
我不知道為什么這不能正常工作。
我嘗試了其他(較小的)示例,例如numpy 網站上列出的示例,它們根據給定的概率數組生成直方圖。
如果可能的話,我真的很感激一些建議/直覺:)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.