Reputation: 21
I am trying to perform a cross-Validation on Piecewise Model using Symfit :
My Data :
x_data = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], dtype=float)
y_data = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10, 10, 10])
to use cross validation we need to create an estimator, so i tried to package the fitting in a class
from sklearn.model_selection import cross_validate, cross_val_score
class model:
def __init__( self, a=None, b=None, c=None ):
self.a = a
self.b = b
self.c = c
def _model_background(self, X, a, b, c):
y1 = a*x + b-a*c
y2 = b
return Model({y: Piecewise((y1, x <= c), (y2, x > c))})
def predict( self, X ):
return self._model_background( X, self.a, self.b, self.c )
def fit( self, X, y ):
from symfit import parameters, variables, Fit, Piecewise, Model
fit = Fit(self._model_background, x=x_data, y=y_data)
fit_result = fit.execute()
self.a = fit_result.value(a)
self.b = fit_result.value(b)
self.c = fit_result.value(c)
return self
def get_params( self, deep=False ):
return { 'a':self.a, 'b':self.b, 'c':self.c }
def set_params( self, **parameters ):
for parameter, value in parameters.intems():
setattr( self, parameter, value )
return self
and then I perform the cross-validation line
cross_validate( symfitmodel(), x_data, y_data, cv=5, scoring='neg_mean_squared_error' )
But it seems that I didn't create the class as it should Error message :
C:\ProgramData\Anaconda3\lib\site-packages\sklearn\model_selection\_validation.py:548: FitFailedWarning: Estimator fit failed. The score on this train-test partition for these parameters will be set to nan. Details:
Traceback (most recent call last):
File "C:\ProgramData\Anaconda3\lib\site-packages\symfit\core\support.py", line 282, in __get__
return getattr(obj, self.cache_attr)
AttributeError: 'Model' object has no attribute '_cached_connectivity_mapping'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\ProgramData\Anaconda3\lib\site-packages\sklearn\model_selection\_validation.py", line 531, in _fit_and_score
estimator.fit(X_train, y_train, **fit_params)
File "<ipython-input-3-db68eb82746d>", line 18, in fit
fit = Fit(self._model_background, x=x_data, y=y_data)
File "C:\ProgramData\Anaconda3\lib\site-packages\symfit\core\support.py", line 423, in wrapped_func
return func(*bound_args.args, **bound_args.kwargs)
File "C:\ProgramData\Anaconda3\lib\site-packages\symfit\core\fit.py", line 374, in __init__
self.model = Model(model)
File "C:\ProgramData\Anaconda3\lib\site-packages\symfit\core\models.py", line 875, in __init__
super(HessianModel, self).__init__(*args, **kwargs)
File "C:\ProgramData\Anaconda3\lib\site-packages\symfit\core\models.py", line 824, in __init__
super(GradientModel, self).__init__(*args, **kwargs)
File "C:\ProgramData\Anaconda3\lib\site-packages\symfit\core\models.py", line 125, in __init__
self._init_from_dict(model)
File "C:\ProgramData\Anaconda3\lib\site-packages\symfit\core\models.py", line 651, in _init_from_dict
super(BaseCallableModel, self)._init_from_dict(model_dict)
File "C:\ProgramData\Anaconda3\lib\site-packages\symfit\core\models.py", line 309, in _init_from_dict
ordered = list(toposort(self.connectivity_mapping))
File "C:\ProgramData\Anaconda3\lib\site-packages\symfit\core\support.py", line 285, in __get__
setattr(obj, self.cache_attr, self.fget(obj))
File "C:\ProgramData\Anaconda3\lib\site-packages\symfit\core\models.py", line 383, in connectivity_mapping
vars, params = seperate_symbols(expr)
File "C:\ProgramData\Anaconda3\lib\site-packages\symfit\core\support.py", line 82, in seperate_symbols
for symbol in func.free_symbols:
AttributeError: 'function' object has no attribute 'free_symbols'
warnings.warn("Estimator fit failed. The score on this train-test"
I tried it with curve_fit but without success:
class piecewise:
def __init__( self, x0=None, a=None, b=None ):
self.x0 = x0
self.a = a
self.b = b
def _piecewise_background(self, X, x0, a, b):
return np.piecewise(X, [X < x0], [lambda X:a*X + b-a*x0, lambda X:b])
def predict( self, X ):
return self._piecewise_background( X, self.x0, self.a, self.b )
def fit( self, X, y ):
from scipy.optimize import curve_fit
popt, pcov = curve_fit( self._piecewise_background, X, y )
self.x0 = popt[0]
self.a = popt[1]
self.b = popt[2]
return self
def get_params( self, deep=False ):
return { 'x0':self.x0, 'a':self.a, 'b':self.b }
def set_params( self, **parameters ):
for parameter, value in parameters.intems():
setattr( self, parameter, value )
return self
Any ideas ?
Upvotes: 0
Views: 242
Reputation: 1705
This is not an answer but a comment.
A direct method (not iterative, no guessed initial value) is shown in the paper : https://fr.scribd.com/document/380941024/Regression-par-morceaux-Piecewise-Regression-pdf ( Page 8 in the present case).
Of course the data given in the question is of few interest because there is no scatter. So no need for numerical calculus the result is obvious. But this can be used to test the method of piecewise regression.
EXAMPLE with SCATTERED DATA
In order to make it more representative the above data has been scattered. Example below :
Upvotes: 0