#13273: extension of sage.numerical.optimize.find_fit
-----------------------------------------------------------+----------------
Reporter: hackstein | Owner:
Type: enhancement | Status:
needs_review
Priority: major | Milestone:
sage-5.3
Component: numerical | Resolution:
Keywords: fitting, interpolation, two-dimensional | Work issues:
enhancement
Report Upstream: N/A | Reviewers:
evanandel, was, ncohen
Authors: Urs Hackstein | Merged in:
Dependencies: | Stopgaps:
-----------------------------------------------------------+----------------
Changes (by hackstein):
* owner: hackstein =>
Comment:
It runs through now, but it still needs careful review. Any comments and
improvements are very welcome.
def find_fit2dim(data, model, initial_guess=None, parameters=None,
variables=None, solution_dict=False):
r"""
Finds numerical estimates for the parameters of the two-dimensional
function model to
give a best fit to data.
INPUT:
- ``data`` -- A two dimensional table of floating point numbers of the
form `[[x_{1,1}, x_{1,2}, f_{1,1}, f_{1,2}],
[x_{2,1}, x_{2,2}, f_{2,1}, f_{2,2}],
\ldots,
[x_{n,1}, x_{n,2}, f_{n,1}, f_{n,2}]]` given as either a
numpy array.
- ``model`` -- Either a pair of symbolic expressions, of symbolic
functions, or
of Python function. ``model`` has to be a function of the variables
`(x_1, x_2, \ldots, x_k)` and free parameters
`(a_1, a_2, \ldots, a_l)`.
- ``initial_guess`` -- (default: ``None``) Initial estimate for the
parameters `(a_1, a_2, \ldots, a_l)`, given as either a list, tuple,
vector or numpy array. If ``None``, the default estimate for each
parameter is `1`.
- ``parameters`` -- (default: ``None``) A list of the parameters
`(a_1, a_2, \ldots, a_l)`. If model is a symbolic function it is
ignored, and the free parameters of the symbolic function are used.
- ``variables`` -- (default: ``None``) A list of the variables
`(x_1, x_2, \ldots, x_k)`. If model is a symbolic function it is
ignored, and the variables of the symbolic function are used.
- ``solution_dict`` -- (default: ``False``) if ``True``, return the
solution as a dictionary rather than an equation.
EXAMPLES:
First we create some data points of a function f
\colon\R^{2}\to\R^{2}. Let f(x,y)=(x-1,3*y+2)
sage: data=np.array([[1,0,0,2],[1,1,0,5],[2,1,1,5],[2,3,1,11]])
We define a function with free parameters "a" and "b":
sage: model(x,y)=(a+x,b+3*y)
We search for the parameters that give the best fit to the data:
find_fit2dim(data,model)
[a == -1.0000000064095422, b == 1.9999999999999998]
ALGORITHM:
Uses ``scipy.optimize.leastsq`` which in turn uses MINPACK's lmdif and
lmder algorithms.
"""
import numpy
if not isinstance(data, numpy.ndarray):
try:
data = numpy.array(data, dtype = float)
except (ValueError, TypeError):
raise TypeError, "data has to be a numpy array"
elif data.dtype == object:
raise ValueError, "the entries of data have to be of type float"
if data.ndim != 2:
raise ValueError, "data has to be a two dimensional table of
floating point numbers"
from sage.symbolic.expression import Expression
if isinstance(model[0], Expression) and
isinstance(model[1],Expression):
if variables is None:
variables = list(model[0].arguments())
if parameters is None:
L=list(model[0].variables())
M=list(model[1].variables())
for v in L:
if v in M:
M.remove(v)
parameters=L+M
for v in variables:
parameters.remove(v)
if data.shape[1] != len(variables) + 2:
raise ValueError, "each row of data needs %d entries, only %d
entries given" % (len(variables) + 2, data.shape[1])
if parameters is None or len(parameters) == 0 or \
variables is None or len(variables) == 0:
raise ValueError, "no variables given"
if initial_guess == None:
initial_guess = len(parameters) * [1]
if not isinstance(initial_guess, numpy.ndarray):
try:
initial_guess = numpy.array(initial_guess, dtype = float)
except (ValueError, TypeError):
raise TypeError, "initial_guess has to be a list, tuple, or
numpy array"
elif initial_guess.dtype == object:
raise ValueError, "the entries of initial_guess have to be of type
float"
if len(initial_guess) != len(parameters):
raise ValueError, "length of initial_guess does not coincide with
the number of parameters"
if isinstance(model[0], Expression) and
isinstance(model[1],Expression):
var_list = variables + parameters
var_names = map(str, var_list)
func = (model[0]._fast_float_(*var_names),
model[1]._fast_float_(*var_names))
else:
func = model
def function(x1_data, x2_data, params):
s=(len(x1_data), 2)
result = numpy.zeros(s)
for row in xrange(len(x1_data)):
fparams = numpy.hstack((x1_data[row],
x2_data[row],params)).tolist()
result[row] = (func[0](*fparams),func[1](*fparams))
return result
def error_function(params, x1_data, x2_data, y1_data, y2_data):
t=(len(x1_data),2)
result = numpy.zeros(t)
result2 = numpy.zeros(len(x1_data))
for row in xrange(len(x1_data)):
fparams = [x1_data[row], x2_data[row]]+ params.tolist()
result[row]= (func[0](*fparams), func[1](*fparams))
result2[row]=(result[row,-2] - y1_data[row])*(result[row,-2] -
y1_data[row])+ (result[row,-1] - y2_data[row])*(result[row,-1] -
y2_data[row])
return result2
x1_data = data[:, -4]
x2_data = data[:, -3]
y1_data = data[:, -2]
y2_data = data[:,-1]
from scipy.optimize import leastsq
estimated_params, d = leastsq(error_function, initial_guess, args =
(x1_data, x2_data, y1_data, y2_data))
if isinstance(estimated_params, float):
estimated_params = [estimated_params]
else:
estimated_params = estimated_params.tolist()
if solution_dict:
dict = {}
for item in zip(parameters, estimated_params):
dict[item[0]] = item[1]
return dict
return [item[0] == item[1] for item in zip(parameters,
estimated_params)]
--
Ticket URL: <http://trac.sagemath.org/sage_trac/ticket/13273#comment:7>
Sage <http://www.sagemath.org>
Sage: Creating a Viable Open Source Alternative to Magma, Maple, Mathematica,
and MATLAB
--
You received this message because you are subscribed to the Google Groups
"sage-trac" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/sage-trac?hl=en.