如何在符号表达式中使用python数组?

时间:2016-04-16 01:23:38

标签: python numpy statistics sympy

对于一个项目,我想使用sympy来构造和计算离散数量的数据点的高斯分布的最大似然。 我可以在mathworld找到我遵循的方法。

但是当我尝试在带有Product和/或Sum的符号表达式中使用数组时遇到了麻烦。以下是我之前尝试的简化版本。

在Anaconda的Yupyter的笔记本中,我创建了一个python数组,比如x

N = 10
x = range(N)

我想在x中的符号表达式中使用sympy,如下所示:

from sympy import *, Symbol
i = Symbol('i', integer=True)
mu = Symbol('mu')

s = Sum( (x[i]-mu)**2, (i, 0, N-1))

但这不起作用,因为评估单元格导致:

TypeError                            Traceback (most recent call last)
<ipython-input-1-19c174235872> in <module>()
      7 mu = Symbol('mu')
      8 
----> 9 s = Sum( (x[i]-mu)**2, (i,0,N-1))

TypeError: list indices must be integers, not Symbol

另一次尝试:

X = MatrixSymbol(X, 1, N)  # No clue how to convince `sympy` to use 1-dimensional arrays using only one index.

s = Sum((X[0,i]-mu)**2, (i,0,N-1))
s.doit()

给出:

(-mu + X[0, 0])**2 + (-mu + X[0, 1])**2 + (-mu + X[0, 2])**2 + (-mu + X[0, 3])**2 + (-mu + X[0, 4])**2 + (-mu + X[0, 5])**2 + (-mu + X[0, 6])**2 + (-mu + X[0, 7])**2 + (-mu + X[0, 8])**2 + (-mu + X[0, 9])**2

有点工作,但如何将x真实值纳入该符号表达式,即将X[0,i]中的每一个替换为x[i]的值}?

另一次尝试:

X = Matrix(1,N, range(N))

s = Sum((X[i]-mu)**2, (i, 0, N-1))
s.doit()

现在python / sympy非常不高兴:

---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-7-6d106fb975e1> in <module>()
      1 X = Matrix(1,N, range(N))
      2 
----> 3 s = Sum((X[i]-mu)**2, (i, 0, N-1))
      4 s.doit()

/Users/twan/anaconda/lib/python2.7/site-packages/sympy/matrices/dense.pyc in __getitem__(self, key)
     94             if isinstance(key, slice):
     95                 return self._mat[key]
---> 96             return self._mat[a2idx(key)]
     97 
     98     def __setitem__(self, key, value):

/Users/twan/anaconda/lib/python2.7/site-packages/sympy/matrices/matrices.pyc in a2idx(j, n)
   4412             j = j.__index__()
   4413         except AttributeError:
-> 4414             raise IndexError("Invalid index a[%r]" % (j, ))
   4415     if n is not None:
   4416         if j < 0:

IndexError: Invalid index a[i]

我不知道该尝试什么,我在这里遇到sympy。我很好奇我是否遇到sympy的限制因为统计中非常重要的计算。

修改

我应该提到要求将被发展为(E**(-((x-mu)**2)/(2 * s**2)))/(s * sqrt(2 * pi))。取幂使得问题略有不同。

尽管@ unutbu的解决方案对我不起作用,但尝试使用该建议指出我应该将域限制为实数。

@Marshmallow的建议确实有效,完整的解决方案现在是:

from sympy import symbols, E, pi, sqrt, init_printing
from sympy import diff, IndexedBase
from sympy.solvers import solve

x, mu = symbols('x mu', real=True)
sigma = symbols('sigma', real=True, positive=True)

bell = (E**(-((x-mu)**2)/(2 * sigma**2)))/(sigma * sqrt(2 * pi))

def likelihood(factor, xs):
    return np.prod([factor.subs(x,i) for i in xs])

def loglikelihood(factor, xs):
    return expand_log(log(likelihood(factor, xs)))

N = 3
X = IndexedBase('X')
Xs = [X[i] for i in range(N)]

solve(diff(loglikelihood(gauss,Xs), mu).subs(sigma, 1), mu)

非常感谢@Marshmellow和@unutbu。

2 个答案:

答案 0 :(得分:1)

由于您的列表x是数字,因此您无需使用符号和来处理它。只需使用Python的列表理解对(xi-mu)**2的列表求和:

from sympy import *
N = 10
x = range(N)
mu = Symbol('mu')
s = sum([(xi-mu)**2 for xi in x])
print(s)
print(s.diff(mu))     # to show this is a symbolic expression

输出:

mu**2 + (-mu + 1)**2 + (-mu + 2)**2 + (-mu + 3)**2 + (-mu + 4)**2 + (-mu + 5)**2 + (-mu + 6)**2 + (-mu + 7)**2 + (-mu + 8)**2 + (-mu + 9)**2
20*mu - 90

答案 1 :(得分:1)

您可以使用IndexedBase来表示包含元素的数组。

X = sy.IndexedBase('X')
s = sy.Sum((X[i]-mu)**2, (i, 0, N-1))

可以使用lambdify将NmPy数组替换为SymPy符号。在这种情况下,我们希望用来自NumPy数组的值替换X[i]

目前,lambdify can not be applied to IndexedBase个对象。但它可以应用于DeferredVector。例如:

import sympy as sy
import numpy as np

i = sy.Symbol('i', integer=True)
mu = sy.Symbol('mu')

N = 10
X = sy.IndexedBase('X')
s = sy.Sum(sy.exp((X[i]-mu)**2), (i, 0, N-1))

f = sy.lambdify(sy.DeferredVector('X'), s, 'sympy')
x = np.arange(N)
print(f(x))

打印

exp(mu**2) + exp((-mu + 1)**2) + exp((-mu + 2)**2) + exp((-mu + 3)**2) + exp((-mu + 4)**2) + exp((-mu + 5)**2) + exp((-mu + 6)**2) + exp((-mu + 7)**2) + exp((-mu + 8)**2) + exp((-mu + 9)**2)

请注意,由于f(x)仍然是SymPy表达式,因此我使用'sympy'作为lambdify的第三个参数,以便sy.exp不会被数字{{1}替换功能。