What happened?
Heyo PySR team! The num_features parameter in TemplateExpressionSpec is described in the API Reference as taking a Python dictionary as input, but doesn't behave that way, yielding a TypeError as shown below:
The Code & The Error
Code yielding TypeError:
# Create data
X = np.random.randn(1000, 5)
y = np.sin(X[:, 0] + X[:, 3] + X[:, 4]) * X[:, 2]**2
# Define template: we want f(x1, x4, x5) + g(x3)
# We'll obtain independent expressions for f and g
# where the respective variables of each are expressed
# as #1 for the first variable, #2 for the second,
# and so on.
# While the output can be evaluated, it is NOT compatible with
# the exporting features for typesetting and modeling in other libraries.
#
template_py = TemplateExpressionSpec(
function_symbols=["f", "g"],
combine="""((; f, g), (a, b, c, d, e)) -> let
_f = f(a, d, e)
_g = g(c)
_out = _f + _g
end""",
num_features={"f": 2, "g": 1},
)
model = PySRRegressor(
expression_spec=template_py,
binary_operators=["+", "*", "-", "/"],
unary_operators=["sin"],
model_selection="score",
maxsize=25,
tournament_selection_n=15,
tournament_selection_p=0.9,
niterations=50,
populations=100,
population_size=80,
should_simplify=True,
topn=10,
# annealing=True,
# alpha=2,
#full_objective=jl.seval(objective),
)
model.fit(X, y)
ERROR:
JuliaError: TypeError: in typeassert, expected Symbol, got a value of type String
The Fix
This error is fixed if you rewrite the dictionary in Julia rather than Python, but I haven't managed to get it to pass a Python dict as described in the documentation. Here's the template with the single line change that allows the model to run:
template_jl = TemplateExpressionSpec(
function_symbols=["f", "g"],
combine="""((; f, g), (a, b, c, d, e)) -> let
_f = f(a, d, e)
_g = g(c)
_out = _f + _g
end""",
num_features=jl.seval("""Base.Dict(Symbol("f") => 3, Symbol("g") => 1)"""),
)
The ExpressionSpec feature is a great addition, but it has some drawbacks which are bypassed by using a custom objective instead, though not without writing a bit of Julia.
The expression output when using the templates is a tad confusing at first (outputting the numbers corresponding to variables in an expression, and restarting the numbering in the other expression) and it would be good to note that in the relevant section of the documentation.
Version
1.3.1
Operating System
Linux
Package Manager
pip
Interface
Jupyter Notebook
Relevant log output
JuliaError: TypeError: in typeassert, expected Symbol, got a value of type String
Stacktrace:
[1] merge(a::@NamedTuple{}, itr::PyDict{Any, Any})
@ Base ./namedtuple.jl:372
[2] _pysr_create_template_structure(function_symbols::AbstractVector, combine::Function, num_features::Union{Nothing, AbstractDict})
@ Main ./none:10
[3] pyjlany_call(self::typeof(_pysr_create_template_structure), args_::Py, kwargs_::Py)
@ PythonCall.JlWrap ~/.julia/packages/PythonCall/Nr75f/src/JlWrap/any.jl:43
[4] _pyjl_callmethod(f::Any, self_::Ptr{PythonCall.C.PyObject}, args_::Ptr{PythonCall.C.PyObject}, nargs::Int64)
@ PythonCall.JlWrap ~/.julia/packages/PythonCall/Nr75f/src/JlWrap/base.jl:73
[5] _pyjl_callmethod(o::Ptr{PythonCall.C.PyObject}, args::Ptr{PythonCall.C.PyObject})
@ PythonCall.JlWrap.Cjl ~/.julia/packages/PythonCall/Nr75f/src/JlWrap/C.jl:63
Extra Info
No response
What happened?
Heyo PySR team! The
num_featuresparameter inTemplateExpressionSpecis described in the API Reference as taking a Python dictionary as input, but doesn't behave that way, yielding aTypeErroras shown below:The Code & The Error
Code yielding TypeError:
ERROR:
JuliaError: TypeError: in typeassert, expected Symbol, got a value of type StringThe Fix
This error is fixed if you rewrite the dictionary in Julia rather than Python, but I haven't managed to get it to pass a Python dict as described in the documentation. Here's the template with the single line change that allows the model to run:
The
ExpressionSpecfeature is a great addition, but it has some drawbacks which are bypassed by using a custom objective instead, though not without writing a bit of Julia.The expression output when using the templates is a tad confusing at first (outputting the numbers corresponding to variables in an expression, and restarting the numbering in the other expression) and it would be good to note that in the relevant section of the documentation.
Version
1.3.1
Operating System
Linux
Package Manager
pip
Interface
Jupyter Notebook
Relevant log output
Extra Info
No response