在我正在编写的模型中的一步中,我必须计算数量的误差函数。我正在尝试做的事情看起来像这样:
from math import erf
import numpy as np
import pymc as pm
sig = pm.Exponential('sig', beta=0.1, size=10)
x = erf(sig ** 2)
此操作失败,因为erf
不适用于数组。我试过了:
@pm.deterministic
def x(sig=sig):
return [erf(s) for s in sig]
但没有成功,我知道有可能通过以下方式获得结果:
np_erf = np.vectorize(erf)
x = np_erf((sig ** 2).value)
但这似乎不是正确的方法,因为它不会产生pm.Deterministic
,而只是np.array
。我该怎么做呢?(PyMC 是 2.3 版)
编辑:为了清楚起见,上述示例进行了简化,这是相关段落在实际代码中的外观。理想情况下,我希望这有效:
mu = pm.LinearCombination('mu', [...], [...])
sig2 = pm.exp(mu) ** 2
f = 1 / (pm.sqrt(np.pi * sig2 / 2.0) * erf(W / sig2))
但如果失败并显示消息TypeError: only length-1 arrays can be converted to Python scalars
.走np.vectorize
路线
np_erf = np.vectorize(erf)
f = 1 / (pm.sqrt(np.pi * sig2 / 2.0) * np_erf(W / sig2))
崩溃并显示相同的错误消息。列表理解
@pm.deterministic
def f(sig2=sig2):
return [1 / (pm.sqrt(np.pi * s / 2.0) * erf(W / s)) for s in sig2]
这样工作,但在代码后面的这个位置会导致错误:
@pm.observed(plot=True)
def y(value=df['dist'], sig2=sig2, f=f):
return (np.log(np.exp(-(value ** 2) / 2.0 / sig2) * f)).sum()
并且错误是AttributeError: log
.
我已经使用数值近似来计算误差函数,这应该意味着一般设置是正确的。直接使用erf
函数会更好、更清晰。
我找到了解决方案。我没有意识到,如果您使用pymc.deterministic
装饰器创建一个变量,传递给函数的参数是numpy.array
,而不是pymc.Distribution
。这允许numpy.vectorize
函数并将其应用于变量。所以而不是
sig = pm.Exponential('sig', beta=0.1, size=10)
x = erf(sig ** 2)
你需要使用
sig = pm.Exponential('sig', beta=0.1, size=10)
np_erf = np_vectorize(erf)
@pm.deterministic
def x(sig=sig):
return np_erf(sig ** 2)
它有效。