trevorstephens / gplearn

Genetic Programming in Python, with a scikit-learn inspired API
http://gplearn.readthedocs.io/
BSD 3-Clause "New" or "Revised" License
1.59k stars 279 forks source link

make_function() throw a TypeError about mpf #245

Closed Grotex closed 2 years ago

Grotex commented 2 years ago

Hi I use gplearn.functions.make_function() to bulit an 'arctanh' function for SymbolicRegressor

from gplearn.fitness import make_fitness
from gplearn.functions import make_function
from gplearn.genetic import SymbolicRegressor
from gplearn.utils import check_random_state
import numpy as np
from mpmath import si, atanh, mp
# import graphviz

mp.dps = 30
mp.pretty = True

def _maae(y, y_pred, w):
    """Calculate the maximum absolute error."""
    diffs = w * np.abs(y - y_pred)
    de = np.sum(np.abs(np.diff(y_pred)))
    if de <= 1:
        ratio = 1
    else:
        ratio = 2 - 1 / (1 + 64 / 27 * (de - 1) ** 2)
    return np.amax(diffs) * ratio

def fex(x):
    y = 2 / mp.pi * si(atanh(x))
    return y

f = np.vectorize(fex, otypes=[float])

def _arctanh(x):
    return atanh(x)

if __name__ == '__main__':
    N = 10000

    rng0 = check_random_state(2)
    rng1 = check_random_state(1031)
    rng2 = check_random_state(2053)
    rng3 = check_random_state(4099)
    rng4 = check_random_state(8209)

    h1 = rng0.binomial(1, 2/3, N).reshape(-1, 1)
    h2 = 2 * rng1.binomial(1, 1/2, N).reshape(-1, 1) - 1
    pert = h1 * h2
    cell = np.ones(N).reshape(-1, 1)

    X_train = np.linspace(1, 2 * N + 1, N) / (2 * N + 2)
    X_train = X_train.reshape(-1, 1)
    Y_train = f(X_train) + 0 * cell
    Y_train = Y_train.ravel()

    X_test = rng3.uniform(0, 1, N).reshape(-1, 1)
    X_test = np.sort(X_test, axis=0)
    Y_test = f(X_test)
    Y_test = Y_test.ravel()

    maae = make_fitness(_maae, greater_is_better=False)
    arctanh = make_function(function=_arctanh, name='arctanh', arity=1)

    er = 0
    p = (er + (er == 0)) / 1
    est_gp = SymbolicRegressor(population_size=10000, generations=20,
                               tournament_size=100, stopping_criteria=er,
                               const_range=(-1.0, 1.0), init_depth=(0, 3),
                               function_set=('add', 'mul', 'div', 'arctanh'), metric=maae,
                               parsimony_coefficient=p,
                               p_crossover=0.95, p_subtree_mutation=0,
                               p_hoist_mutation=0, p_point_mutation=0,
                               max_samples=1.0, feature_names=['X'],
                               low_memory=True, n_jobs=-1,
                               verbose=1, random_state=rng4)

    est_gp.fit(X_train, Y_train)
    print(est_gp.program)

    # dot_data = est_gp.program.export_graphviz()
    # graph = graphviz.Source(dot_data)
    # graph.view()

    score_train = est_gp.score(X_train, Y_train)
    score_test = est_gp.score(X_test, Y_test)
    print(score_train, score_test)

But it throws an error

Traceback (most recent call last):
  File "C:\Users\gsjiang\Desktop\test\poutput\Under-construction\LagSpace\SR.py", line 61, in <module>
    arctanh = make_function(function=_arctanh, name='arctanh', arity=1)
  File "C:\Python39\lib\site-packages\gplearn\functions.py", line 94, in make_function
    function(*args)
  File "C:\Users\gsjiang\Desktop\test\poutput\Under-construction\LagSpace\SR.py", line 33, in _arctanh
    return atanh(x)
  File "C:\Python39\lib\site-packages\mpmath\ctx_mp_python.py", line 1003, in f
    x = ctx.convert(x)
  File "C:\Python39\lib\site-packages\mpmath\ctx_mp_python.py", line 648, in convert
    if type(x).__module__ == 'numpy': return ctx.npconvert(x)
  File "C:\Python39\lib\site-packages\mpmath\ctx_mp_python.py", line 681, in npconvert
    raise TypeError("cannot create mpf from " + repr(x))
TypeError: cannot create mpf from array([1., 1., 1., 1., 1., 1., 1., 1., 1., 1.])

What is the problem and how to fix it?

trevorstephens commented 2 years ago

mpmath doesn't support vectorised computation. You could try https://numpy.org/doc/stable/reference/generated/numpy.arctanh.html instead ... Though you'll need a lot of work to get around NaN's with that, and I cannot help you with that.

Grotex commented 2 years ago

mpmath doesn't support vectorised computation. You could try https://numpy.org/doc/stable/reference/generated/numpy.arctanh.html instead ... Though you'll need a lot of work to get around NaN's with that, and I cannot help you with that.

Thx