python按指定概率抽样_python – 没有替换概率的抽样

我对这个问题有两种解释.一个我更喜欢(“永恒”)和一个我认为技术上有效但劣等(“天真”)

永恒:

给定概率x,y,z,该方法计算x’,y’,z’,使得如果我们独立地绘制两次并丢弃所有相等的对,则0,1,2的频率是x,y,z.

这为两次试验提供了合适的总频率,并且在第一次和第二次试验相同的意义上具有简单和永恒的额外好处.

为此我们必须拥有

(x'y' + x'z') / [2 (x'y' + x'z' + y'z')] = x

(x'y' + y'z') / [2 (x'y' + x'z' + y'z')] = y (1)

(y'z' + x'z') / [2 (x'y' + x'z' + y'z')] = z

如果我们添加其中两个并减去我们得到的第三个

x'y' / (x'y' + x'z' + y'z') = x + y - z = 1 - 2 z

x'z' / (x'y' + x'z' + y'z') = x - y + z = 1 - 2 y (2)

y'z' / (x'y' + x'z' + y'z') = -x + y + z = 1 - 2 x

乘以其中的2个除以第三个

x'^2 / (x'y' + x'z' + y'z') = (1 - 2 z) (1 - 2 y) / (1 - 2 x)

y'^2 / (x'y' + x'z' + y'z') = (1 - 2 z) (1 - 2 x) / (1 - 2 y) (3)

z'^2 / (x'y' + x'z' + y'z') = (1 - 2 x) (1 - 2 y) / (1 - 2 z)

因此达到一个恒定的因素

x' ~ sqrt[(1 - 2 z) (1 - 2 y) / (1 - 2 x)]

y' ~ sqrt[(1 - 2 z) (1 - 2 x) / (1 - 2 y)] (4)

z' ~ sqrt[(1 - 2 x) (1 - 2 y) / (1 - 2 z)]

既然我们知道x’,y’,z’必须总和为1,这就足以解决了.

但是:我们实际上不需要完全解决x’,y’,z’.由于我们只对不相等的对感兴趣,所以我们需要的是条件概率x’y’/(x’y’x’z’y’z’),x’z’/(x’y’x’z’ y’z’)和y’z’/(x’y’x’z’y’z’).我们可以使用等式(2)计算这些.

然后,我们将它们中的每一个减半,以获得有序对的概率,并从具有这些概率的六个法律对中抽取.

幼稚:

这是基于(在我看来是任意的)假设在第一次抽签后用概率x’,y’,z’,第二次必须有条件概率0,y’/(y’z’),z’/( y’z’)如果第一个是0 x’/(x’z’),0,z’/(x’z’),如果第一个是1,概率x’/(x’y’),y’/( x’y’),0)如果第一个是2.

这样做的缺点是,据我所知,没有简单的,封闭形式的解决方案,第二次和第一次抽奖是完全不同的.

优点是可以直接使用np.random.choice;然而,这是如此之慢,以至于在下面的实现中我提供了避免此功能的解决方法.

在一些代数之后,人们发现:

1/x' - x' = c (1 - 2x)

1/y' - y' = c (1 - 2y)

1/z' - z' = c (1 - 2z)

其中c = 1 / x’1 / y’1 / z’ – 1.这我只能用数字解决.

实施和结果:

这是实施.

import numpy as np

from scipy import optimize

def f_pairs(n, p):

p = np.asanyarray(p)

p /= p.sum()

assert np.all(p <= 0.5)

pp = 1 - 2*p

# the following two lines show how to compute x', y', z'

# pp = np.sqrt(pp.prod()) / pp

# pp /= pp.sum()

# now pp contains x', y', z'

i, j = np.triu_indices(3, 1)

i, j = i[::-1], j[::-1]

pairs = np.c_[np.r_[i, j], np.r_[j, i]]

pp6 = np.r_[pp/2, pp/2]

return pairs[np.random.choice(6, size=(n,), replace=True, p=pp6)]

def f_opt(n, p):

p = np.asanyarray(p)

p /= p.sum()

pp = 1 - 2*p

def target(l):

lp2 = l*pp/2

return (np.sqrt(1 + lp2**2) - lp2).sum() - 1

l = optimize.root(target, 8).x

lp2 = l*pp/2

pp = np.sqrt(1 + lp2**2) - lp2

fst = np.random.choice(3, size=(n,), replace=True, p=pp)

snd = (

(np.random.random((n,)) < (1 / (1 + (pp[(fst+1)%3] / pp[(fst-1)%3]))))

+ fst + 1) % 3

return np.c_[fst, snd]

def f_naive(n, p):

p = np.asanyarray(p)

p /= p.sum()

pp = 1 - 2*p

def target(l):

lp2 = l*pp/2

return (np.sqrt(1 + lp2**2) - lp2).sum() - 1

l = optimize.root(target, 8).x

lp2 = l*pp/2

pp = np.sqrt(1 + lp2**2) - lp2

return np.array([np.random.choice(3, (2,), replace=False, p=pp)

for _ in range(n)])

def check_sol(p, sol):

N = len(sol)

print("Frequencies [value: observed, desired]")

c1 = np.bincount(sol[:, 0], minlength=3) / N

print(f"1st column: 0: {c1[0]:8.6f} {p[0]:8.6f} 1: {c1[1]:8.6f} {p[1]:8.6f} 2: {c1[2]:8.6f} {p[2]:8.6f}")

c2 = np.bincount(sol[:, 1], minlength=3) / N

print(f"2nd column: 0: {c2[0]:8.6f} {p[0]:8.6f} 1: {c2[1]:8.6f} {p[1]:8.6f} 2: {c2[2]:8.6f} {p[2]:8.6f}")

c = c1 + c2

print(f"1st or 2nd: 0: {c[0]:8.6f} {2*p[0]:8.6f} 1: {c[1]:8.6f} {2*p[1]:8.6f} 2: {c[2]:8.6f} {2*p[2]:8.6f}")

print()

print("2nd column conditioned on 1st column [value 1st: val / prob 2nd]")

for i in range(3):

idx = np.flatnonzero(sol[:, 0]==i)

c = np.bincount(sol[idx, 1], minlength=3) / len(idx)

print(f"{i}: 0 / {c[0]:8.6f} 1 / {c[1]:8.6f} 2 / {c[2]:8.6f}")

print()

# demo

p = 0.4, 0.35, 0.25

n = 1000000

print("Method: Naive")

check_sol(p, f_naive(n//10, p))

print("Method: naive, optimized")

check_sol(p, f_opt(n, p))

print("Method: Timeless")

check_sol(p, f_pairs(n, p))

样本输出:

Method: Naive

Frequencies [value: observed, desired]

1st column: 0: 0.449330 0.400000 1: 0.334180 0.350000 2: 0.216490 0.250000

2nd column: 0: 0.349050 0.400000 1: 0.366640 0.350000 2: 0.284310 0.250000

1st or 2nd: 0: 0.798380 0.800000 1: 0.700820 0.700000 2: 0.500800 0.500000

2nd column conditioned on 1st column [value 1st: val / prob 2nd]

0: 0 / 0.000000 1 / 0.608128 2 / 0.391872

1: 0 / 0.676133 1 / 0.000000 2 / 0.323867

2: 0 / 0.568617 1 / 0.431383 2 / 0.000000

Method: naive, optimized

Frequencies [value: observed, desired]

1st column: 0: 0.450606 0.400000 1: 0.334881 0.350000 2: 0.214513 0.250000

2nd column: 0: 0.349624 0.400000 1: 0.365469 0.350000 2: 0.284907 0.250000

1st or 2nd: 0: 0.800230 0.800000 1: 0.700350 0.700000 2: 0.499420 0.500000

2nd column conditioned on 1st column [value 1st: val / prob 2nd]

0: 0 / 0.000000 1 / 0.608132 2 / 0.391868

1: 0 / 0.676515 1 / 0.000000 2 / 0.323485

2: 0 / 0.573727 1 / 0.426273 2 / 0.000000

Method: Timeless

Frequencies [value: observed, desired]

1st column: 0: 0.400756 0.400000 1: 0.349099 0.350000 2: 0.250145 0.250000

2nd column: 0: 0.399128 0.400000 1: 0.351298 0.350000 2: 0.249574 0.250000

1st or 2nd: 0: 0.799884 0.800000 1: 0.700397 0.700000 2: 0.499719 0.500000

2nd column conditioned on 1st column [value 1st: val / prob 2nd]

0: 0 / 0.000000 1 / 0.625747 2 / 0.374253

1: 0 / 0.714723 1 / 0.000000 2 / 0.285277

2: 0 / 0.598129 1 / 0.401871 2 / 0.000000

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
提供的源码资源涵盖了安卓应用、小程序、Python应用和Java应用等多个领域,每个领域都包含了丰富的实例和项目。这些源码都是基于各自平台的最新技术和标准编写,确保了在对应环境下能够无缝运行。同时,源码中配备了详细的注释和文档,帮助用户快速理解代码结构和实现逻辑。 适用人群: 这些源码资源特别适合大学生群体。无论你是计算机相关专业的学生,还是对其他领域编程感兴趣的学生,这些资源都能为你提供宝贵的学习和实践机会。通过学习和运行这些源码,你可以掌握各平台开发的基础知识,提升编程能力和项目实战经验。 使用场景及目标: 在学习阶段,你可以利用这些源码资源进行课程实践、课外项目或毕业设计。通过分析和运行源码,你将深入了解各平台开发的技术细节和最佳实践,逐步培养起自己的项目开发和问题解决能力。此外,在求职或创业过程中,具备跨平台开发能力的大学生将更具竞争力。 其他说明: 为了确保源码资源的可运行性和易用性,特别注意了以下几点:首先,每份源码都提供了详细的运行环境和依赖说明,确保用户能够轻松搭建起开发环境;其次,源码中的注释和文档都非常完善,方便用户快速上手和理解代码;最后,我会定期更新这些源码资源,以适应各平台技术的最新发展和市场需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值