Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
有条件计算的最适合Python的方式是什么?_Python_Numpy_Conditional Statements_Dynamic Programming - Fatal编程技术网

有条件计算的最适合Python的方式是什么?

有条件计算的最适合Python的方式是什么?,python,numpy,conditional-statements,dynamic-programming,Python,Numpy,Conditional Statements,Dynamic Programming,我正在用Python/NumPy实现贝叶斯变化点检测(如果您有兴趣,请看一下)。我需要计算范围[a,b]中数据的可能性,其中a和b可以具有1到n的所有值。然而,我可以在某些点上删减计算,这样我就不必计算所有的可能性。另一方面,一些似然数被多次使用,因此我可以通过将值保存在矩阵P[a,b]中来节省时间。现在,每当我使用它时,我都会检查这个值是否已经计算过了,但我发现这有点麻烦。看起来是这样的: # ... P = np.ones((n, n)) * np.inf # a likelihood c

我正在用Python/NumPy实现贝叶斯变化点检测(如果您有兴趣,请看一下)。我需要计算范围
[a,b]
中数据的可能性,其中
a
b
可以具有
1
n
的所有值。然而,我可以在某些点上删减计算,这样我就不必计算所有的可能性。另一方面,一些似然数被多次使用,因此我可以通过将值保存在矩阵
P[a,b]
中来节省时间。现在,每当我使用它时,我都会检查这个值是否已经计算过了,但我发现这有点麻烦。看起来是这样的:

# ...
P = np.ones((n, n)) * np.inf  # a likelihood can't get inf, so I use it 
                            # as pseudo value

for a in range(n):
    for b in range(a, n):

        # The following two lines get annoying and error prone if you 
        # use P more than once

        if P[a, b] == np.inf:  
            P[a, b] = likelihood(data, a, b)

        Q[a] += P[a, b] * g[a] * Q[a - 1]  # some computation using P[a, b]
        # ...
我想知道,是否有一种更直观、更通俗的方法来实现这一点,而不必在每次使用
p[a,b]
之前都使用
if…
语句。如果不满足某些条件,则类似于自动函数调用。当然,我可以让
likelion
函数知道它可以保存值,但是它需要某种状态(例如,成为对象)。我想避免这种情况

似然函数

因为它是在评论中要求的,所以我添加了似然函数。它实际上先计算共轭先验,然后计算似然。和所有的日志表示。。。所以很复杂

from scipy.special import gammaln
def gaussian_obs_log_likelihood(data, t, s):
    n = s - t
    mean = data[t:s].sum() / n

    muT = (n * mean) / (1 + n)
    nuT = 1 + n
    alphaT = 1 + n / 2
    betaT = 1 + 0.5 * ((data[t:s] - mean) ** 2).sum() + ((n)/(1 + n)) * (mean**2 / 2)
    scale = (betaT*(nuT + 1))/(alphaT * nuT)

    # splitting the PDF of the student distribution up is /much/ faster. (~ factor 20)
    prob = 1
    for yi in data[t:s]:
        prob += np.log(1 + (yi - muT)**2/(nuT * scale)) 

    lgA = gammaln((nuT + 1) / 2) - np.log(np.sqrt(np.pi * nuT * scale)) - gammaln(nuT/2)

    return n * lgA - (nuT + 1)/2 * prob

虽然我使用的是Python 2.7,但2.7和3.x的答案都很受欢迎。

我会使用
defaultdict
的兄弟(您不能直接使用
defaultdict
,因为它不会告诉您缺少的密钥):


另一种方法是在
似然

上使用缓存装饰器。您能给我们展示一下您的似然函数吗?要使该函数在向量而不是scalars上工作,可以使用初始值
None
?然后可以使用
P[a,b]=似然(data,a,b),如果不是P[a,b]
它实际上对向量有效
a
b
只是计算可能性的
数据的范围。我还是要添加它。既然整个数组
P
被初始化为
inf
,那么
if
的条件不应该总是真的吗?或者您是否在代码的其他部分更改了
P
P[a,b]
被多次使用。因此,
if…
语句只用于计算一次。第一次
P[a,b]
是需要的。实际上,我在
if
语句中更改了它。代码稍微简化了一些,使问题更加清晰。我喜欢decorator解决方案!我也喜欢decorator解决方案,但是如果您需要控制缓存的生存期,那么代码片段就可以了。。。但是,在dict上使用.get(key)而不是try:catch,它的速度更快…@Retozi:Optimized:-)
class Cache(object):
    def __init__(self):
        self.cache = {}

    def get(self, a, b):
        key = (a,b)

        result = self.cache.get(key, None)
        if result is None:
            result = likelihood(data, a, b)
            self.cache[key] = result

        return result