Как лямбдифицировать выражение SymPy, содержащее функцию erf, для использования с NumPy

Я хотел бы осветить символическое выражение, содержащее функцию erf, с помощью SymPy. Это можно сделать для скалярных аргументов следующим образом:

log_normal = 0.5 + 0.5 * sym.erf((sym.log(x) - mu) / sym.sqrt(2 * sigma**2))
F = sym.lambdify([x, mu, sigma], log_normal)
F(1.0, 0.0, 1.0)

Я хотел бы векторизовать вышесказанное. Обычно я делал бы следующее ...

log_normal = 0.5 + 0.5 * sym.erf((sym.log(x) - mu) / sym.sqrt(2 * sigma**2))
vector_F = sym.lambdify([x, mu, sigma], log_normal, modules='numpy')
vector_F(1.0, 0.0, 1.0)

Однако вышеупомянутое вызывает _3 _...

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-29-14adde48d4a1> in <module>()
----> 1 vector_F(1.0, 0.0, 1.0)

/Users/drpugh/anaconda/lib/python2.7/site-packages/numpy/__init__.pyc in <lambda>(x, mu,     sigma)

NameError: global name 'erf' is not defined

Это ошибка или я упускаю что-то тривиальное?


person davidrpugh    schedule 30.09.2014    source источник


Ответы (2)


Вы сказали lambdify, что у него есть только numpy как модуль, с которым можно поиграть; дайте ему источник для erf. IOW, у вас есть

>>> vector_F = sym.lambdify([x, mu, sigma], log_normal, modules=['numpy'])
>>> vector_F(1.0, 0.0, 1.0)
Traceback (most recent call last):
  File "<ipython-input-10-14adde48d4a1>", line 1, in <module>
    vector_F(1.0, 0.0, 1.0)
  File "<string>", line 1, in <lambda>
NameError: global name 'erf' is not defined

но

>>> vector_F = sym.lambdify([x, mu, sigma], log_normal, modules=['numpy', 'sympy'])
>>> vector_F(1.0, 0.0, 1.0)
0.500000000000000

or

>>> vector_F = sym.lambdify([x, mu, sigma], log_normal, modules=['numpy', 'math'])
>>> vector_F(1.0, 0.0, 1.0)
0.5

или в зависимости от того, что erf вы предпочитаете, в зависимости от того, хотите ли вы sympy.core.numbers.Float или float.

person DSM    schedule 30.09.2014
comment
Вы также можете использовать modules=['numpy', {'erf': scipy.special.erf}], чтобы использовать scipy erf. - person asmeurer; 02.10.2014
comment
@asmeurer Думаю, этот комментарий должен быть отдельным ответом. Использование erf у меня не работает. Однако при использовании вашего решения. - person NichtJens; 22.01.2019

Начиная с SymPy 1.3, scipy автоматически поддерживается в lambdify. Если вы опустите аргумент modules, он автоматически добавит scipy. Или вы можете использовать modules=['numpy', 'scipy'].

>>> log_normal = 0.5 + 0.5 * sym.erf((sym.log(x) - mu) / sym.sqrt(2 * sigma**2))
>>> vector_F = sym.lambdify([x, mu, sigma], log_normal)
>>> vector_F(1.0, 0.0, 1.0)
0.5

В общем, для поддержки функции, о которой lambdify не знает, добавьте ее в качестве словаря к аргументу modules. Аргумент modules определяет пространство имен, в котором выполняется лямбдифицируемая функция. См. документацию по lambdify. Например, для поддержки erf в SymPy ‹1.3:

>>> import scipy.special
>>> vector_F = sym.lambdify([x, mu, sigma], log_normal, modules=['numpy', {'erf': scipy.special.erf}])
>>> vector_F(1.0, 0.0, 1.0)
0.5
person asmeurer    schedule 22.01.2019