我正在写一个函数来计算二元泊松分布的概率密度函数。
当所有的参数(x, y, theta1, theta2, theta0)
都是标量时,这很容易,但如果不使用循环来放大参数,使这些参数成为向量,这就很麻烦了。
theta0
是标量-等式中的“相关参数”- 具有长度
l
的theta1
和theta2
x
、y
,它们都具有长度n
输出数组的形状为(l, n, n)
。例如,输出数组中的切片[j, :, :]
将如下所示:
第一部分(常数,在求和之前)我想我已经算出了:
import numpy as np
from scipy.special import factorial
def constant(theta1, theta2, theta0, x, y):
exponential_part = np.exp(-(theta1 + theta2 + theta0)).reshape(-1, 1, 1)
x = np.tile(x, (len(x), 1)).transpose()
y = np.tile(y, (len(y), 1))
double_factorial = (np.power(np.array(theta1).reshape(-1, 1, 1), x)/factorial(x)) * \
(np.power(np.array(theta2).reshape(-1, 1, 1), y)/factorial(y))
return exponential_part * double_factorial
但是我在求和部分遇到了困难。我如何向量化一个极限取决于变量数组的求和呢?
1条答案
按热度按时间zed5wv101#
我想我已经弄明白了,基于@w-m建议的方法:根据出现的最大x或y值,计算可能出现的每个求和项,并使用掩码去掉不需要的求和项。假设您的x和y项从0到N,按连续顺序排列,这将计算比实际需要多三倍的项,但这可以通过使用矢量化来弥补。
参考实现
我首先写了一个纯Python的参考实现,它只是用循环来实现你的问题。有了4个嵌套的循环,它不是很快,但是在测试numpy版本的时候很方便。
Numpy实作
我将其实现划分为两个函数。
函数的作用是:计算求和符号左边的所有内容。函数的作用是:计算求和符号内的所有内容。
基准测试
假设X和Y的范围从0到20,并且theta位于该范围内的某个位置,我得到的结果是numpy版本比纯python参考快大约280倍。
数值稳定性
我不确定它的数值稳定性如何。例如,当我将theta设为100时,我会得到一个浮点溢出。通常,当计算一个包含大量选择和阶乘表达式的表达式时,你会使用一些数学等价物,这会导致较小的中间和。在这种情况下,我对数学的了解非常少,我不知道你会怎么做。