类型错误:当随机变量不是纯分布时,值变量必须具有相同的类型
来自这篇文章 HERE,发表于“PeerJ Comput. Sci.”,我拿了最后的代码(第28页):
import pymc as pm
import pytensor
import pytensor.tensor as pt
a = pm.Uniform.dist()
b = pm.Normal.dist(mu=a, sigma=1)
x = b + pt.as_tensor([2, 3, 4])
x_draws = pm.draw(x, draws=1_000)
x_logp = pm.logp(rv=x, value=[x_draws]).eval()
这引出了一个我不理解的长错误信息:
---------------------------------------------------------------------------
NotImplementedError Traceback (most recent call last)
~\anaconda3\lib\site-packages\pymc\distributions\logprob.py in logp(rv, value)
176 try:
--> 177 return logp_logprob(rv, value)
178 except NotImplementedError:
~\anaconda3\lib\site-packages\pymc\logprob\abstract.py in logprob(rv_var, *rv_values, **kwargs)
52 """Create a graph for the log-probability of a ``RandomVariable``."""
---> 53 logprob = _logprob(rv_var.owner.op, rv_values, *rv_var.owner.inputs, **kwargs)
54
~\anaconda3\lib\functools.py in wrapper(*args, **kw)
876
--> 877 return dispatch(args[0].__class__)(*args, **kw)
878
~\anaconda3\lib\site-packages\pymc\logprob\abstract.py in _logprob(op, values, *inputs, **kwargs)
93 """
---> 94 raise NotImplementedError(f"Logprob method not implemented for {op}")
95
NotImplementedError: Logprob method not implemented for Elemwise{add,no_inplace}
During handling of the above exception, another exception occurred:
TypeError Traceback (most recent call last)
~\anaconda3\lib\site-packages\pymc\distributions\logprob.py in logp(rv, value)
179 try:
--> 180 value = rv.type.filter_variable(value)
181 except TypeError as exc:
~\anaconda3\lib\site-packages\pytensor\tensor\type.py in filter_variable(self, other, allow_convert)
271
--> 272 raise TypeError(
273 f"Cannot convert Type {other.type} "
TypeError: Cannot convert Type TensorType(float64, (1, 1000, 3)) (of Variable TensorConstant{[[[3.41809..6263971]]]}) into Type TensorType(float64, (3,)). You can try to manually convert TensorConstant{[[[3.41809..6263971]]]} into a TensorType(float64, (3,)).
The above exception was the direct cause of the following exception:
TypeError Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_129020\3313924450.py in <module>
8 x = b + pt.as_tensor([2, 3, 4])
9 x_draws = pm.draw(x, draws=1_000)
---> 10 x_logp = pm.logp(rv=x, value=[x_draws]).eval()
~\anaconda3\lib\site-packages\pymc\distributions\logprob.py in logp(rv, value)
180 value = rv.type.filter_variable(value)
181 except TypeError as exc:
--> 182 raise TypeError(
183 "When RV is not a pure distribution, value variable must have the same type"
184 ) from exc
TypeError: When RV is not a pure distribution, value variable must have the same type
有人能解释真正的问题是什么吗?
解决方案
我认为这很可能是因为你安装的相关Python库的 版本 导致的。
为什么?先说,你的代码示例在我的机器上运行得很顺利!但我们也可以看看错误信息。
阅读堆栈跟踪是一项需要时间来培养的技能。它写着“嘿,你在 in logp(rv, value) 中得到了一个 NotImplementedError!” 这个 logp 是你在示例的最后一行调用的函数。
如果你不熟悉,NotImplementedError 是一种标准的Python错误类型,程序员在想为尚未实现的功能留出空间时会使用它(但未来是否会实现,无法保证)。
举个有趣的例子,你可能有一个绘制图形的库:
def draw_shape(coordinates, dimension):
if dimension == 3:
draw_3d_shape(coordinates)
elif dimension == 2:
draw_2d_shape(coordinates)
else:
raise NotImplementedError(
f"draw_shape can't handle {dimension} dimensions yet!"
)
当用户尝试绘制比如说一维(1D)或四维(4D)形状时,将会得到错误。
掌握了这些知识,我们继续。
更具体地说,你的错误信息是
---> 94 raise NotImplementedError(f"Logprob method not implemented for {op}")
95
NotImplementedError: Logprob method not implemented for Elemwise{add,no_inplace}
这告诉我们,在 pymc.logp 内部有一个名为 op 的变量,在你的代码中被设为 Elemwise{add,no_inplace}。一个快速的Google搜索证实 Elemwise 是一个 pytensor 类。
堆栈跟踪的其余部分并不是特别相关。它告诉我们,NotImplementedError 引发了大量其他错误,但它们不是根本原因。
所以,简单回顾:
- 你把某种
pytensor类传给pymc.logp() - 这样做时你得到一个
NotImplementedError - 你的代码示例在我的机器上可以正常运行
结论: 你很可能安装了较旧版本的 pymc。
建议: 升级你所安装的 pymc 库的版本。
最后说明:
我看到你在使用Anaconda——记得正确使用conda环境,如果你只是把一堆库安装在“base”环境中,可能会得到对某个问题有效但对其他问题无效的版本。
或者,如果你对所使用的计算机上可以安装的内容有一定控制权,我可以推荐使用 一个更现代的解决方案,比如uv。这有点“跟上潮流”,但我自己过去用过Anaconda,深知它省了我很多麻烦。