我实际上想做this answer中所述的非常相似的事情。我想创建一个总计给定目标值的随机数列表。如果我不在乎范围,可以使用答案所提示的内容:
>>> print np.random.dirichlet(np.ones(10),size=1)
[[ 0.01779975 0.14165316 0.01029262 0.168136 0.03061161 0.09046587 0.19987289 0.13398581 0.03119906 0.17598322]]
但是,我希望能够控制各个参数的范围和目标。我想提供每个参数的范围。例如,我将传递三个元组的列表,每个元组指定均匀分布的上下边界。 target
关键字参数将描述总和。
get_rnd_numbers([(0.0, 1.0), (0.2, 0.5), (0.3, 0.8)], target=0.9)
例如,输出可能如下所示:
[0.2, 0.2, 0.5]
那怎么实现?
更新:
答案 0 :(得分:0)
from random import uniform
while( True ):
a = uniform(0.0 ,1.0)
b = uniform(0.2 , 0.5)
c = 0.9 - a - b
if(c > 0.3 and c <0.8):
break
print(a,b,c)
先找到两个随机数。从边界中减去以获得第三个“随机数”。检查以确保它满足边界条件。
答案 1 :(得分:0)
好,这是一些想法/代码。
我们将从Dirichlet中采样,因此自动实现了总和目标。
然后对于从Dirichlet采样的每个x i ,我们应用具有不同下边界l i 但具有相同缩放参数s
的线性变换。
v i = l i + s * x i
从求和目标(S i 表示对i
的求和)和事实,Dirichlet采样值总和为1
S i v i =目标
我们可以计算s
:
s =目标-S i l i
让每个v i 的平均值放到间隔的中间。
E [v i ] = l i + s * E [x i ] =(l i + h i )/ 2
E [x i ] =(h i -l i )/ 2 / s
然后介绍基本上与Dirichlets的反方差成正比的旋钮,因此旋钮越大,均值附近的随机采样值越紧。
对于Dirichlet分布alpha参数数组
alpha i = E [x i ] * vscale
其中,vscale是用户定义的方差比例因子。我们将检查采样值是否违反下限或上限条件,如果存在,则拒绝采样。
代码,Python 3.6,Anaconda 5.2
import numpy as np
boundaries = np.array([[0.0, 1.0], [0.2, 0.5], [0.3, 0.8]])
target = 0.9
def get_rnd_numbers(boundaries, target, vscale):
lo = boundaries[:, 0]
hi = boundaries[:, 1]
s = target - np.sum(lo)
alpha_i = ( 0.5 * (hi-lo) / s ) * vscale
print(np.sum(alpha_i))
x_i = np.random.dirichlet(alpha_i, size=1)
v_i = lo + s*x_i
good_lo = not np.any(v_i < lo)
good_hi = not np.any(v_i > hi)
return (good_lo, good_hi, v_i)
vscale = 3.0
gl, gh, v = get_rnd_numbers(boundaries, target, vscale)
print((gl, gh, v, np.sum(v)))
if gl and gh:
print("Good sample, use it")
gl, gh, v = get_rnd_numbers(boundaries, target, vscale)
print((gl, gh, v, np.sum(v)))
if gl and gh:
print("Good sample, use it")
gl, gh, v = get_rnd_numbers(boundaries, target, vscale)
print((gl, gh, v, np.sum(v)))
if gl and gh:
print("Good sample, use it")
您可以使用不同的转换思路,也许将平均条件删除或替换为更明智的方法。我建议您不要忘记旋钮,这样您可以收紧采样范围。