【问题标题】:How to serialize sympy lambdified function?如何序列化 sympy lambdified 函数?
【发布时间】:2015-09-27 15:40:45
【问题描述】:

标题说明了一切。有没有办法序列化 sympy.lambdify 生成的函数?:

import sympy as sym
import pickle
import dill
a, b = sym.symbols("a, b")
expr = sym.sin(a) + sym.cos(b)
lambdified_expr = sym.lambdify((a, b), expr, modules="numpy")
pickle.dumps(lambdified_expr) # won't work
dill.dumps(lambdified_expr) # won't work either

...我想这样做的原因是因为我的代码生成了很多lambdified函数,但我发现每次都花费太长时间。

【问题讨论】:

    标签: python numpy serialization pickle sympy


    【解决方案1】:

    你实际上可以使用dill来腌制它。 dill 的最新版本(例如在 github 上)具有“设置”,允许在 dump 上构造泡菜的方式的变体。是的,dill 的默认设置在此对象上失败,但如果您使用递归跟踪全局引用的设置(即recurse = True),则不会。此设置类似于cloudpickle 默认为您提供的设置。

    >>> import sympy as sym
    >>> import pickle
    >>> import dill
    >>> a, b = symbols("a, b")
    >>> a, b = sym.symbols("a, b")
    >>> expr = sym.sin(a) + sym.cos(b)
    >>> lambdified_expr = sym.lambdify((a, b), expr, modules="numpy")
    >>> 
    >>> dill.settings
    {'recurse': False, 'byref': False, 'protocol': 2, 'fmode': 0}
    >>> dill.settings['recurse'] = True
    >>> dill.dumps(lambdified_expr)
    '\x80\x02cdill.dill\n_create_function\nq\x00(cdill.dill\n_unmarshal\nq\x01U\x83c\x02\x00\x00\x00\x02\x00\x00\x00\x03\x00\x00\x00C \x00\x00s\x14\x00\x00\x00t\x00\x00|\x00\x00\x83\x01\x00t\x01\x00|\x01\x00\x83\x01\x00\x17S(\x01\x00\x00\x00N(\x02\x00\x00\x00t\x03\x00\x00\x00sint\x03\x00\x00\x00cos(\x02\x00\x00\x00t\x01\x00\x00\x00at\x01\x00\x00\x00b(\x00\x00\x00\x00(\x00\x00\x00\x00s\x08\x00\x00\x00<string>t\x08\x00\x00\x00<lambda>\x01\x00\x00\x00s\x00\x00\x00\x00q\x02\x85q\x03Rq\x04}q\x05(U\x03cosq\x06cnumpy.core.umath\ncos\nq\x07U\x03sinq\x08cnumpy.core.umath\nsin\nq\tuU\x08<lambda>q\nNN}q\x0btq\x0cRq\r.'
    

    附:我是dill作者,所以我知道。

    【讨论】:

    • 为什么 recurse=True 不是默认选项?
    • 因为dill 可以序列化范围广泛的对象,而recurse=False 提供了最广泛的覆盖范围。如果您使用recurse=True,它对某些对象非常有效,但在许多情况下会中断序列化。如果(或何时)我解决了它中断的情况,那么它将成为默认值。在那之前,最好的选择是删除默认功能,而是通过设置提供新功能。见:github.com/uqfoundation/dill/issues/105
    • @MikeMcKerns 我有一个警告,对于相当大的lambadified函数,我得到RuntimeError: maximum recursion depth exceeded while calling a Python object
    • 显然,dill.dump 有一个recurse 参数:Signature: dill.dump(obj, file, protocol=None, byref=None, fmode=None, recurse=None)。这与您可以在您提供的 sn-p 中全局设置的选项相同吗?那么,我可以不使用dill.settings['recurse'] = True 而是使用dill.dump(..., recurse=True) 吗?
    • @Spiros:没错,你可以根据每个调用来设置。
    【解决方案2】:

    确实 - pickle、cPickle 甚至 dill 在此示例中使用默认设置都会失败。

    但 cloudpickle 不会失败!

    pip install cloudpickle
    

    https://github.com/cloudpipe/cloudpickle

    import sympy as sym
    from cloudpickle import dumps, loads
    a, b = sym.symbols("a, b")
    expr = sym.sin(a) + sym.cos(b)
    lambdified_expr = sym.lambdify((a, b), expr, modules="numpy")
    var=dumps(lambdified_expr)
    a1=lambdified_expr(10,10)
    del lambdified_expr
    lambdified_expr=loads(var)
    a2=lambdified_expr(10,10)
    a1==a2  # True
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-28
      • 2014-11-06
      • 2018-05-28
      相关资源
      最近更新 更多