Символическое определение бинома с использованием SymPy

Я пытаюсь символически определить биномиальную функцию с помощью Sympy. Моя первая попытка была такой:

import numpy as np
import scipy.stats as st
import sklearn.linear_model as lm
import matplotlib.pyplot as plt
import sympy as sp
sp.interactive.printing.init_printing(use_latex=True)

n = sp.Symbol('n', integer=True, positive=True)
r = sp.Symbol('r', integer=True, positive=True)
theta = sp.Symbol('theta')

#Create the function symbolically
from sympy import factorial
cNkLambda=  lambda n,r : (factorial(n))/ (factorial(r) *factorial(n- r))
binomLambda= lambda theta, n, r: cNkLambda(n,r)*((theta **r)*(1-theta)**(n-r))

print binomLambda (0.5, 10,5) 

Однако я понял, что здесь не использую никаких функций Sympy и ничего не оценивается символически.

Во второй попытке я удалил определение Lambda, чтобы символьная функция была определена правильно, однако это приводит к исключению:

%reset -f
import numpy as np
import scipy.stats as st
import sklearn.linear_model as lm
import matplotlib.pyplot as plt
import sympy as sp
#from sympy import binomial
#from sympy import Symbol, Rational, factorial, binomial, expand_func
sp.interactive.printing.init_printing(use_latex=True)

n = sp.Symbol('n', integer=True, positive=True)
r = sp.Symbol('r', integer=True, positive=True)
theta = sp.Symbol('theta')

#Create the function symbolically
from sympy import factorial
cNkLambda=  (factorial(n))/ (factorial(r) *factorial(n-r))
#cNkLambda_fied = sp.lambdify((n,r), cNkLambda, modules='numpy')
cNkLambda.evalf() # this works

binomLambda= cNkLambda(n,r)*((theta **r)*(1-theta)**(n-r))
#Convert it to a Numpy-callable function
#bin_likelihood = sp.lambdify((theta,r,n), binomLambda,   modules='numpy')

#print binomLambda (0.5, 10,5)

TypeError Traceback (последний вызов последний) in () 23 cNkLambda.evalf () # работает 24 ---> 25 binomLambda = cNkLambda (n, r) ((theta r) ( 1-theta) (nr)) 26 # Преобразование в функцию, вызываемую с помощью Numpy 27 #bin_likelihood = sp.lambdify ((theta, r, n), binomLambda, modules = 'numpy')

TypeError: объект Mul не вызывается

Мой вопрос: как правильно определить функцию, чтобы она была полностью символической.

Изменить 1: Нашел ссылку об этой ошибке: https://github.com/sympy/sympy/issues/8562, но я не могу понять, где в моем коде я делаю то же самое.

Изменить 2: я обновил вопрос, изменил:

binomLambda= cNkLambda(n,r)*((theta **r)*(1-theta)**(n-r))

to :

binomLambda= cNkLambda*((theta **r)*(1-theta)**(n-r)) 

Однако теперь, когда я пытаюсь осветить символическую функцию следующим образом: binomLambda.subs ({theta: 0.5, r: 5, n: 10}) # это работает

#Convert it to a Numpy-callable function

binomRealLambda = sp.lambdify((theta,r,n), binomLambda, modules='numpy')
print binomRealLambda(0.5,5,10)

Это приводит к:

NameError Traceback (последний вызов последним) in () 27 binomRealLambda = sp.lambdify ((theta, r, n), binomLambda, modules = 'numpy') 28 ---> 29 печать binomRealLambda (0.5,5,10)

/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/numpy/<▪init

NameError: глобальное имя факториал не определено

Редактировать 3: у меня это полностью работает:

 #----------------------Symbolic beta-------------------------------#
    a = sp.Symbol('a', integer=False, positive=True)
    b = sp.Symbol('b', integer=False, positive=True)
    mu = sp.Symbol('mu', integer=False, positive=True)

    # Create the function symbolically
    G = sp.gamma
    # The normalisation factor
    BetaNormSym = G(a + b)/(G(a)*G(b))
    # The functional form
    BetaFSym = mu**(a-1) * (1-mu)**(b-1)

   BetaSym=BetaNormSym * BetaFSym
   BetaSym.evalf() # this works
   # Turn Beta into a function
   BetaLambda = sp.Lambda((mu,a,b), BetaSym)
   maths(r"\operatorname{Beta}(\mu|a,b) = ")
   display(BetaSym)

   BetaLambda(0.5,1,1)
   BetaSym.subs({mu:0.5,a:1,b:1})
#----------------------Symbolic beta-------------------------------#

Спасибо,


person Haro Sato    schedule 23.07.2016    source источник
comment
Почему бы не использовать встроенные функции, такие как binomial (n, k)? Кроме того, если вы используете распределения вероятностей, вам может пригодиться модуль sympy.stats.   -  person Francesco Bonazzi    schedule 25.07.2016


Ответы (1)


cNkLambda - это выражение SymPy, которое определяется в терминах n и r. Это не функция, поэтому не вызывайте ее с cNkLambda(n,r). binomLambda можно определить следующим образом:

binomLambda = cNkLambda*((theta **r)*(1-theta)**(n-r))

In [18]: cNkLambda
Out[20]: 
     n!    
───────────
r!⋅(n - r)!

In [22]: cNkLambda*((theta **r)*(1-theta)**(n-r))
Out[22]: 
 r         n - r   
θ ⋅(-θ + 1)     ⋅n!
───────────────────
    r!⋅(n - r)!    

Чтобы сделать из binomLambda числовую функцию, вы можете использовать sympy.lambdify. Обратите внимание, однако, что binomLambda использует факториалы, а NumPy не определяет факториальную функцию.

Вы можете позвонить math.factorial или scipy.misc.factorial:

bin_likelihood = sy.lambdify((theta,r,n), binomLambda, modules='math')

or

bin_likelihood2 = sy.lambdify((theta,r,n), binomLambda,   
                              modules=[{'factorial':misc.factorial}])

Например,

import scipy.misc as misc
import numpy as np
import sympy as sy

sy.interactive.printing.init_printing(use_latex=True)

n = sy.Symbol('n', integer=True, positive=True)
r = sy.Symbol('r', integer=True, positive=True)
theta = sy.Symbol('theta')

cNkLambda=  (sy.factorial(n))/ (sy.factorial(r) * sy.factorial(n-r))
binomLambda = cNkLambda*((theta **r)*(1-theta)**(n-r))

bin_likelihood = sy.lambdify((theta,r,n), binomLambda, modules='math')
print(bin_likelihood(np.linspace(0,2*np.pi,4), 2, 5))
# [  0.00000000e+00  -5.74962672e+01  -5.68925055e+03  -5.82166577e+04]

bin_likelihood2 = sy.lambdify((theta,r,n), binomLambda,   
                              modules=[{'factorial':misc.factorial}])
print(bin_likelihood2(np.linspace(0,2*np.pi,4), 2, 5))
# [  0.00000000e+00  -5.74962672e+01  -5.68925055e+03  -5.82166577e+04]
person unutbu    schedule 23.07.2016
comment
Спасибо! обратите внимание, что sp.Lambda работает для моей первой версии с факториальным импортом из SymPy, тогда как sp.lambdify - нет. - person Haro Sato; 23.07.2016
comment
@HaroSato Lambda создает символическую функцию. lambdify преобразует символьное выражение в числовую функцию. - person asmeurer; 26.07.2016