在python中动态构建随机变量函数

在python中动态构建随机变量函数,python,random,scipy,Python,Random,Scipy,我使用scipy.stats得到一些随机变量,如下所示: import scipy.stats as st x1 = st.uniform() x2 = st.uniform() 现在,我想在前面的随机变量的基础上再做一个随机变量,并对新的随机变量进行一些计算,如var。假设我希望新的随机变量类似于max(2,x1)+x2。我如何动态地定义它?我的旧答案如下: (当引用SO文档的答案被编辑以删除这些引用时,我被提示再次查看此问题。无论如何,我认为这是一个更好的答案。) 首先,据我所知,对于两个

我使用
scipy.stats
得到一些随机变量,如下所示:

import scipy.stats as st
x1 = st.uniform()
x2 = st.uniform()

现在,我想在前面的随机变量的基础上再做一个随机变量,并对新的随机变量进行一些计算,如
var
。假设我希望新的随机变量类似于
max(2,x1)+x2
。我如何动态地定义它?

我的旧答案如下:

(当引用SO文档的答案被编辑以删除这些引用时,我被提示再次查看此问题。无论如何,我认为这是一个更好的答案。)

首先,据我所知,对于两个或多个变量的非线性函数的方差,没有一种通用的方法可以得到一个很好的闭式表达式。也许大多数凡人都会采用某种蒙特卡罗方法来近似计算这样的量

下面的一些代码生成了一个针对这种特定情况的绘图。它适用于许多其他类型

从单位均匀随机变量生成两个伪随机样本,然后计算伪随机变量
Y
,作为这些样本元素的函数

>>> import scipy.stats as stats
>>> import matplotlib.pyplot as plt
>>> import numpy as np
>>> X1 = stats.uniform.rvs(0,1, 5000)
>>> X2 = stats.uniform.rvs(0,1, 5000)
>>> Y = [max(2,x1)+x2 for (x1,x2) in zip(X1,X2)]
现在,为了确定这个函数的密度函数,绘制它的直方图

>>> plt.hist(Y)
(array([ 501.,  526.,  490.,  481.,  513.,  488.,  525.,  490.,  521.,  465.]), array([ 2.00012599,  2.10007992,  2.20003386,  2.2999878 ,  2.39994173,
        2.49989567,  2.59984961,  2.69980354,  2.79975748,  2.89971141,
        2.99966535]), <a list of 10 Patch objects>)
>>> plt.show()
但这些都不是真的必要,是吗?

作为U(0,1)随机变量,X1从不超过1。因此,max(X1,2)必须是2。那么2+X2必须是U(2,3)。该随机变量与X2具有相同的标度;只有它的位置改变了。因此其方差必须相同,且U(0,1)的方差为0.0833333

编辑“下一天”:

刚刚得知sympy现在支持随机变量,我很想在这个问题上尝试一下

>>> from sympy.stats import Uniform, Variance
>>> from sympy import symbols, Integral
>>> X1 = Uniform('X1', 0, 1)
>>> X2 = Uniform('X2', 0, 1)
唉,作为其他答案的作者,它似乎无法处理涉及
max
的表达式

>>> Variance(max(2, X1) + X2)
Traceback (most recent call last):
  File "<interactive input>", line 1, in <module>
  File "C:\Python34\lib\site-packages\sympy-1.0.1.dev0-py3.4.egg\sympy\core\relational.py", line 195, in __nonzero__
    raise TypeError("cannot determine truth value of Relational")
TypeError: cannot determine truth value of Relational
“旧答案”从这里开始:

我想不是直接的。但是,这种方法可能对您有用

首先假设您知道感兴趣的随机变量函数的pdf或cdf。然后可以在scipy.stats中使用rv_continuous来计算该函数的方差和其他矩

显然,“乐趣”从这里开始。通常,您会尝试定义cdf。对于随机变量的任何给定值,这是一个表达式(如您给出的表达式)不大于给定值的概率。因此,确定cdf简化为求解两个变量中的(无限)不等式集合。当然,通常有一种强大的模式,可以大大降低执行此任务的复杂性和难度。

在OpenTURNS中,使用该模式可以进行更多种类的操作

在您的例子中,x1和x2代表独立分布

import openturns as ot
x1 = ot.Uniform() 
x2 = ot.Uniform()
因此,边缘为x1和x2的组合分布为:

dist = ot.ComposedDistribution([x1, x2], ot.IndependentCopula(2))
dist.setDescription(["x1", "x2"])  # labels 

# note the use of "IndependentCopula of dimension 2" as second argument 
如果您想要一个尺寸为5的样品

sample = dist.getSample(5)
print(sample)
>>>     [ x1        x2        ]
0 : [ -0.752141 -0.897212 ]
1 : [  0.850966  0.857914 ]
2 : [ -0.340213 -0.344882 ]
3 : [ -0.166526  0.458643 ]
4 : [  0.378453 -0.908958 ]
如前所述,可以将基于(x1,x2)的模型定义为符号函数。在您的示例中:y=max(2,x1)+x2

您可以应用于
模型(示例)

但是你的模型可以是多维的。例如:

model = ot.SymbolicFunction(["x1", "x2"], ["x1^2+x2", "x2^2+x1"])
应用于样本将得到一个二维样本

>>>    [ y0         y1      ]
0   -0.331496   0.05284813
1   1.582057    1.586982
2   -0.2291374  -0.2212693
3   0.4863741   0.04382738
4   -0.7657314  1.204657
这在创建更高级的模型时非常有趣。在最后一种情况下,绘制大小为10000的输出
out=model(dist.getSample(10000))

import matplotlib.pyplot as plt
plt.scatter(out.getMarginal(0),out.getMarginal(1), s=0.5)

只是想澄清一下:你想模拟画一个随机变量max(2,x1)+x2的样本,然后计算这个样本的方差吗?我认为创建随机变量函数没有那么容易。你的例子可以用解析法计算,但我怀疑任何一个包都不能提供一个通用的解决方案。你可以创建两个随机数组,然后根据模拟得出结论。@Bill我不明白你所说的样本方差是什么意思。但我的意思是,例如,对于
x1
,我可以说
x1.var()
来获得方差。我希望新的随机变量有类似的东西。我通过定义cdf尝试了它,但我得到了以下错误:
对象没有属性'\u parse\u args\u stats'
连续的
rv\u的子类需要定义
\u cdf
,而不是
cdf
@MehdiJafarniaJahromi:我不知道。我们能看看你的密码吗?@比尔,我纠正了我的错误。我应该调用super
\uuuu init\uuuu
函数使代码正常工作。
    [ y0      ]
0 : [ 1.10279 ]
1 : [ 2.85791 ]
2 : [ 1.65512 ]
3 : [ 2.45864 ]
4 : [ 1.09104 ]
model = ot.SymbolicFunction(["x1", "x2"], ["x1^2+x2", "x2^2+x1"])
>>>    [ y0         y1      ]
0   -0.331496   0.05284813
1   1.582057    1.586982
2   -0.2291374  -0.2212693
3   0.4863741   0.04382738
4   -0.7657314  1.204657
import matplotlib.pyplot as plt
plt.scatter(out.getMarginal(0),out.getMarginal(1), s=0.5)