繁体   English   中英

人类可读的 DEAP 输出

[英]Human-readable output with DEAP

我正在使用 DEAP 对数据表进行符号回归,即找到最适合数据的函数。 不幸的是,我找不到以人类可读格式获取结果的方法。 例如,如果我这样做

best_ind = tools.selBest(pop, 1)[0]
print("Best individual is %s" % (best_ind))

我的输出可能看起来像

Best individual is add(mul(add(x, 2), div(y, add(x, y))), 1)

但这对人类来说很难解释。 有没有办法以看起来更像的方式打印结果

(x+2)*(y/(x+y))+1

Ohjeahs 的回答没有按规定工作。 我修改了提供的代码并在下面提供。

import sympy
def convert_inverse_prim(prim, args):
    """
    Convert inverse prims according to:
    [Dd]iv(a,b) -> Mul[a, 1/b]
    [Ss]ub(a,b) -> Add[a, -b]
    We achieve this by overwriting the corresponding format method of the sub and div prim.
    """
    prim = copy.copy(prim)
    #prim.name = re.sub(r'([A-Z])', lambda pat: pat.group(1).lower(), prim.name)    # lower all capital letters

    converter = {
        'sub': lambda *args_: "Add({}, Mul(-1,{}))".format(*args_),
        'protectedDiv': lambda *args_: "Mul({}, Pow({}, -1))".format(*args_),
        'mul': lambda *args_: "Mul({},{})".format(*args_),
        'add': lambda *args_: "Add({},{})".format(*args_)
    }
    prim_formatter = converter.get(prim.name, prim.format)

    return prim_formatter(*args)

def stringify_for_sympy(f):
    """Return the expression in a human readable string.
    """
    string = ""
    stack = []
    for node in f:
        stack.append((node, []))
        while len(stack[-1][1]) == stack[-1][0].arity:
            prim, args = stack.pop()
            string = convert_inverse_prim(prim, args)
            if len(stack) == 0:
                break  # If stack is empty, all nodes should have been seen
            stack[-1][1].append(string)
    return string

sympy.simplify(stringify_for_sympy(best_ind))

您可以从使用sympy.simplify开始

import sympy

expr = "Add(x, 2)"
sympy.simplify(expr)  # x + 2

但是,sympy 想要 add、mul 等大写。 您还需要将Div(a, b)Mul(a, 1/b)

你可以通过像这样改变primitive.format方法来做到这一点:

def convert_inverse_prim(prim, args):
    """
    Convert inverse prims according to:
    [Dd]iv(a,b) -> Mul[a, 1/b]
    [Ss]ub(a,b) -> Add[a, -b]
    We achieve this by overwriting the corresponding format method of the sub and div prim.
    """
    prim = copy.copy(prim)
    prim.name = re.sub(r'([A-Z])', lambda pat: pat.group(1).lower(), prim.name)    # lower all capital letters

    converter = {
        'sub': lambda *args_: "Add({}, Mul(-1,{}))".format(*args_),
        'div': lambda *args_: "Mul({}, Pow({}, -1))".format(*args_)
    }
    prim_formatter = converter.get(prim.name, prim.format)

    return prim_formatter(*args)

此代码取自glyph

这个小小的对我来说效果很好:

from sympy import sympify

locals = {
    'sub': lambda x, y : x - y,
    'div': lambda x, y : x/y,
    'mul': lambda x, y : x*y,
    'add': lambda x, y : x + y,
    'neg': lambda x    : -x,
    'pow': lambda x, y : x**y,
}

# ind = 'div(add(div(x, mul(y, y)), 1), mul(x, y))'
print(f'original: {ind}')
expr = sympify(str(ind) , locals=locals)
print(f'simplified: {expr}')

输出:

original: div(add(div(x, mul(y, y)), 1), mul(x, y))
simplified: (x/y**2 + 1)/(x*y)

它甚至会显示在 Jupyter 笔记本中显示的 LaTex:

display(expr)

在此处输入图片说明

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM