Skip to main content

numerics - Finding a fit to a multi-dimensioned function


I have a model function f:R2→R2, and a bunch of data points for which I'd like Mathematica to fit for me. Unfortunately FindFit seems to only deal with functions Rn→R. I guess I could make my own square difference from the data to the model and use NMinimize on that, but I wondering if there was an easier way?


Edit - toy example with answers


$g\left(x,y\right)=\left$


g[{x_, y_}, {a_, b_, c_, d_}] := {a b x + (2 c + d) y, (2 a + b) x + c d y};
points = Flatten[Table[{{x, y}, g[{x, y}, {1, 2, 3, 4}]},
{x, -1, 1, 0.5}, {y, -1, 1, 0.5}], 1];


Finding a fit for each component separately doesn't work:


data1 = points /. {{x_, y_}, {u_, v_}} -> {x, y, u};
data2 = points /. {{x_, y_}, {u_, v_}} -> {x, y, v};
FindFit[data1, g[{x, y}, {a, b, c, d}][[1]], {a, b, c, d}, {x, y}]
FindFit[data2, g[{x, y}, {a, b, c, d}][[2]], {a, b, c, d}, {x, y}]


{a -> 0.729723, b -> 2.74077, c -> 3.35659, d -> 3.28681}


{a -> 1.48555, b -> 1.02891, c -> 2.81936, d -> 4.25629}




Jens suggestion works well:


data3 = points /. {{x_, y_}, {u_, v_}} -> Sequence[{x, y, 0, u}, {x, y, 1, v}];
FindFit[data3, g[{x, y}, {a, b, c, d}].{1 - s, s}, {a, b, c, d}, {x, y, s}]


{a -> 1., b -> 2., c -> 3., d -> 4.}



My original suggestion (which is similar to user840's links)


error = Plus @@ (points /.
{{x_, y_}, {u_, v_}} -> Norm[g[{x, y}, {a, b, c, d}] - {u, v}]^2);

NMinimize[error, {a, b, c, d}]

Gives a different, but still correct, solution (or at least a close approximation thereof)



{1.41754*10^-13, {a -> 1.00004, b -> 1.99993, c -> 2., d -> 6.}}




Answer



Without a specific example, I can only make general suggestions here.


The first thing that comes to mind is that you could fit each of the two components of your vector field independently. I.e., if →f:R2→R2 is split up into →f={fx,fy} with f1,2:R2→R, then FindFit would work on each of these component functions.


If you don't want the fits to be determined independently, it could still be possible to use FindFit by introducing an auxiliary variable s that labels the two component functions above, fs, and then provide the fitting data with this variable s included. Here, s can only have two discrete values (I borrowed the idea from spin-half quantum mechanics). Let's choose s = 0 for the function fx and s = 1 for fy. So you'd have data in the form



data = {{x1, y1, 0, fx1}, {x1, y1, 1, fy1}, ...}

where fx1 is the first value of fx and fy1 the first value of fy, both at the point x1, y1.


Your model could then look something like this:


model[x_, y_, s_] := modely[x, y]*s + modelx[x, y]*(1 - s)

where modely[x, y] is the model for fy and modelx[x, y] is the model for fx. The variables in the FindFit call would be x, y, s, and the parameters in the models modelx, modely could be the same (or different).


There are probably many other reasonable ways to do such a fit, but these are some ideas.


Comments

Popular posts from this blog

functions - Get leading series expansion term?

Given a function f[x] , I would like to have a function leadingSeries that returns just the leading term in the series around x=0 . For example: leadingSeries[(1/x + 2)/(4 + 1/x^2 + x)] x and leadingSeries[(1/x + 2 + (1 - 1/x^3)/4)/(4 + x)] -(1/(16 x^3)) Is there such a function in Mathematica? Or maybe one can implement it efficiently? EDIT I finally went with the following implementation, based on Carl Woll 's answer: lds[ex_,x_]:=( (ex/.x->(x+O[x]^2))/.SeriesData[U_,Z_,L_List,Mi_,Ma_,De_]:>SeriesData[U,Z,{L[[1]]},Mi,Mi+1,De]//Quiet//Normal) The advantage is, that this one also properly works with functions whose leading term is a constant: lds[Exp[x],x] 1 Answer Update 1 Updated to eliminate SeriesData and to not return additional terms Perhaps you could use: leadingSeries[expr_, x_] := Normal[expr /. x->(x+O[x]^2) /. a_List :> Take[a, 1]] Then for your examples: leadingSeries[(1/x + 2)/(4 + 1/x^2 + x), x] leadingSeries[Exp[x], x] leadingSeries[(1/x + 2 + (1 - 1/x...

mathematical optimization - Minimizing using indices, error: Part::pkspec1: The expression cannot be used as a part specification

I want to use Minimize where the variables to minimize are indices pointing into an array. Here a MWE that hopefully shows what my problem is. vars = u@# & /@ Range[3]; cons = Flatten@ { Table[(u[j] != #) & /@ vars[[j + 1 ;; -1]], {j, 1, 3 - 1}], 1 vec1 = {1, 2, 3}; vec2 = {1, 2, 3}; Minimize[{Total@((vec1[[#]] - vec2[[u[#]]])^2 & /@ Range[1, 3]), cons}, vars, Integers] The error I get: Part::pkspec1: The expression u[1] cannot be used as a part specification. >> Answer Ok, it seems that one can get around Mathematica trying to evaluate vec2[[u[1]]] too early by using the function Indexed[vec2,u[1]] . The working MWE would then look like the following: vars = u@# & /@ Range[3]; cons = Flatten@{ Table[(u[j] != #) & /@ vars[[j + 1 ;; -1]], {j, 1, 3 - 1}], 1 vec1 = {1, 2, 3}; vec2 = {1, 2, 3}; NMinimize[ {Total@((vec1[[#]] - Indexed[vec2, u[#]])^2 & /@ R...

plotting - Plot 4D data with color as 4th dimension

I have a list of 4D data (x position, y position, amplitude, wavelength). I want to plot x, y, and amplitude on a 3D plot and have the color of the points correspond to the wavelength. I have seen many examples using functions to define color but my wavelength cannot be expressed by an analytic function. Is there a simple way to do this? Answer Here a another possible way to visualize 4D data: data = Flatten[Table[{x, y, x^2 + y^2, Sin[x - y]}, {x, -Pi, Pi,Pi/10}, {y,-Pi,Pi, Pi/10}], 1]; You can use the function Point along with VertexColors . Now the points are places using the first three elements and the color is determined by the fourth. In this case I used Hue, but you can use whatever you prefer. Graphics3D[ Point[data[[All, 1 ;; 3]], VertexColors -> Hue /@ data[[All, 4]]], Axes -> True, BoxRatios -> {1, 1, 1/GoldenRatio}]