我尝试使用theano的scan
函数多次评估多元正常CDF,但我得到了一个ValueError。
以下是我试图进行矢量化的原始函数示例:
from scipy.stats.mvn import mvnun # library that calculates MVN CDF
low = [-1.96, 0 ] # lower bounds of integration
upp = [0 , 1.96] # upper bounds of integration
mean = [0 , 0 ] # means of the jointly distributed random variables
covs = [[1,0.25],[0.25,1]] # covariance matrix
print(mvnun(low,upp,mean,cov))
这会产生以下输出:
(0.19620339269649473, 0)
简单明了,对吧?
我真正想做的是创建4个大型输入对象,每个对象包含1500个元素。这样,我就可以评估mvnun
函数1500次。我们的想法是,在每次迭代时,所有输入都与上一次不同,并且不需要前一次迭代的信息。
这是我的设置:
import theano
import numpy as np
lower = theano.tensor.dmatrix("lower") # lower bounds - dim: 1500 x 2
upper = theano.tensor.dmatrix("upper") # upper bounds - dim: 1500 x 2
means = theano.tensor.dmatrix("means") # means means - dim: 1500 x 2
covs = theano.tensor.dtensor3("covs") # cov matrices - dim: 1500 x 2 x 2
results, updates = theano.scan(fn=mvnun,
sequences=[lower,upper,means,covs])
f = theano.function(inputs=[lower, upper, means, covs],
outputs=results,
updates=updates)
但是,当我尝试运行这段代码时,我在使用scan
命令的行上收到错误。错误说明:ValueError: setting an array element with a sequence.
。错误的完整回溯如下:
追踪(最近一次呼叫最后一次):
文件"",第7行,in 序列= [下限,上限,手段,COVS])
文件" C:\ Anaconda2 \ lib \ site-packages \ theano \ scan_module \ scan.py", 第745行,在扫描中 条件,输出,更新= scan_utils.get_updates_and_outputs(fn(* args))
ValueError:使用序列设置数组元素。
我原本认为代码不起作用,因为mvnun
函数返回一个双元素元组而不是单个值。
然而,当我尝试向量化一个也返回了两元素元组的测试函数(我创建)时,事情就好了。以下是完整的示例:
# Some weird crazy function that takes in three Nx1 vectors
# and an NxN matrix and spits out a tuple of scalars.
def test_func(low_i,upp_i,mean_i,cov_i):
r1 = low_i.sum() + upp_i.sum()
r2 = np.dot(mean_i,cov_i).sum()
test_func_out = (r1,r2)
return(test_func_out)
lower = theano.tensor.dmatrix("lower") # lower
upper = theano.tensor.dmatrix("upper") # upper
means = theano.tensor.dmatrix("means") # means
covs = theano.tensor.dtensor3("covs") # covs
results, updates = theano.scan(fn=test_func,
sequences=[lower,upper,means,covs])
f = theano.function(inputs=[lower, upper, means, covs],
outputs=results,
updates=updates)
np.random.seed(666)
obs = 1500 # number of elements in the dataset
dim = 2 # dimension of multivariate normal distribution
# Generating random values for the lower bounds, upper bounds and means
lower_vals = np.random.rand(obs,dim)
upper_vals = lower_vals + np.random.rand(obs,dim)
means_vals = np.random.rand(obs,dim)
# Creates a symmetric matrix - used for the random covariance matrices
def make_sym_matrix(dim,vals):
m = np.zeros([dim,dim])
xs,ys = np.triu_indices(dim,k=1)
m[xs,ys] = vals[:-dim]
m[ys,xs] = vals[:-dim]
m[ np.diag_indices(dim) ] = vals[-dim:]
return m
# Generating the random covariance matrices
covs_vals = []
for i in range(obs):
cov_vals = np.random.rand((dim^2 - dim)/2+dim)
cov_mtx = make_sym_matrix(dim,cov_vals)
covs_vals.append(cov_mtx)
covs_vals = np.array(covs_vals)
# Evaluating the test function on all 1500 elements
print(f(lower_vals,upper_vals,means_vals,covs_vals))
当我运行这段代码时,一切都运行正常,我得到的输出是一个包含2个数组的列表,每个数组包含1500个元素:
[array([ 4.24700864, 3.80830129, 2.60806493, ..., 3.12995381, 4.41907055, 4.12880839]),
array([ 0.87814314, 1.01768617, 0.45072405, ..., 1.15788282, 0.15766754, 1.32393402])]
值得注意的是,矢量化函数从序列中获取元素的顺序是完美的。我对列表中的前3个数字进行了健全性检查:
for i in range(3):
print(test_func(lower_vals[i],upper_vals[i],means_vals[i],covs_vals[i]))
结果是:
(4.2470086396797502, 0.87814313729162796)
(3.808301289302495, 1.017686166097616)
(2.6080649327828564, 0.45072405177076169)
这些值实际上与矢量化方法中的前3个输出值相同。
回到主要问题:当我在mvnun
语句中使用scan
函数时,为什么我无法使用ValueError
函数?为什么我会得到这个奇怪的par
?
任何建议都会非常有用!!!
感谢!!!