Community Tip - Learn all about the Community Ranking System, a fun gamification element of the PTC Community. X
I am looking for an implementation of a program for curve fitting. I have already achieved a good approximation using the genfit function.
Currently, I am trying to improve the fit further by using a routine with while loops that iteratively adjusts the three variables to achieve a better approximation.
However, when I start the loop, it runs indefinitely and fails to find a solution. Could anyone help me resolve this issue?
Solved! Go to Solution.
Ah, I had overlooked that you wrote MC13 in the topic.
Find attached the file saved in MC13 format.
Comparing the three fitting functions it shows (especially in the log-lin plot) that neither provides a good fit for x-values below 100.
For higher values of x, minimize and minerr returned a much better fit compared to genfit.
You have to make ajpha1 an additional argument of functions Phi3P and also Delta as otherwise always the same function Phi3P is used, not considering the change in alpha1.
BTW, are you sure that it should read "< 0.0005" in the while condition and not "> 0.005" ?!!
I don't think that you can improve genfits alpha value with your method, which is also very inefficient concerning run time. You should rely on the built-in algorithms an may consider using minimize or a solve block with minerr instead of genfit.
You may test and also plot the cumulated absolute error values
Using this test function you may also use "minimize" to get the best value. It differs a liitle bit from the value derived by genfit and according to the test function its a little bit better.
But this is only a near to optimal value considering that beta and gamma are constant.
Your fit needs you to jiggle around with all three values at the same time, though.
So why not set up the test function dependent on all three and again use minimize:
The result is clearly much better than what genfit could come up with.
While we are at it, we can also try a solve block with minimize
The fit now is even (very slightly) better!
Thank you for the quick response and detailed explanation, Mr. Werner_E.
Although your explanation of the algorithm is clear, I would like to access your Mathcad file. However, it seems your version is newer than mine ( I am using Mathcad 13.0 ). Could you please save the file in this version for me?
Ah, I had overlooked that you wrote MC13 in the topic.
Find attached the file saved in MC13 format.
Comparing the three fitting functions it shows (especially in the log-lin plot) that neither provides a good fit for x-values below 100.
For higher values of x, minimize and minerr returned a much better fit compared to genfit.
Mr. Werner_E,
I recently asked you for help, and you provided several options that could solve my problems.
I cannot thank you enough for your support, as it is greatly contributing to my research.
May God bless you.
You are welcome.
BTW, I found that genfit provides a fit similar to minimize or minerr using your error function, when we omit the first six data entries:
Mr. Werner,
I have a question that is not directly related to my initial query, but I would like to understand it better.
Why is a "log-lin plot" used to analyze the results?
@MB_12486492 wrote:
Mr. Werner,
I have a question that is not directly related to my initial query, but I would like to understand it better.
Why is a "log-lin plot" used to analyze the results?
Because the x-values span a wide range and I noticed that the distance between the x-values was rather small in the lower range and much larger in the range of higher values. Something typical for equally spaced log values. So I thought I would try a log-lin plot to have a better look at the lower range values.
I agree with you that better results could likely be achieved using "minerr" and "minimize."
However, I am curious to try finding the optimal values for "alpha," "beta," and "gamma" using an iterative process with a while loop. Unfortunately, it hasn’t been working in my simulations.
Do you think this approach is feasible? Is there a way to make it work effectively?
For the program on the right hand side, function Delta would have to be (re)defined with alpha, beta and gamma as its additional arguments.
To return all three values, you would have to return a vector of values.
But to achieve a good result you would have to change the the three values independently from each other. he way you try to do it they change synchronous, every iteration step would increase all three values for 0.001.
You could use three nested for loops and keep the values which create the minimum value of your error expression. This approach would take up a lot of time and will sure not give better precision than the built-in methods.
I also wonder why you use gamma=45 as start value.
And, no, I don't think a simple approach as you show is feasible in any way.
If you really don't trust the built-in algorithm, you will have to study the various non-linear multidimensional solve algorithms. Most are based on Newton with a twist or two. Then you would have to implement the algorithm of your choice yourself in Mathcad but I don't think that you will gain precision or calc time that way.
Mathcad by default uses an optimized Levenberg-Marquardt algorithm for genfit, Conjugate Gradient algorithm for minimize and Levenberg-Marquardt for minerr.
You can change the algorithm used when you right-click the keyword genfit, minimize or minerr, but usually the defaults are best choice.
Not every algorithm is available for all functions.
Thanks for the answer, Mr. Werner,
I really trust in the built-in algorithm and I am very satisfied with the precision.
I guess it is much better than I was thinking before, using an iteration process.
I would just like to have the script (perhaps with coarser increments) to compare in my research and show that functions like genfit, minimize, and minerr have a much better approximation with a lower computational cost.
Initially, I tried to model with a for loop, but I am not writing the correct script using (MATHCAD 13).
Is it possible to get any help or any link that could have a good example ?
You sure should lookup the syntax for a for-loop in Mathcad in the help!
Here is the implementation of the aforementioned brute force method.
Within a given range and step width for each of the three parameters the error function is evaluated for every value of alpha, beta and gamma and the values which yield the minimum are returned.
The method is highly inefficient and sure not recommended.
The example shows very large step widths (0.1, 30 and 0.1) to speed up calculation - only 72 calls to the error function are made..
If you use step widths 0.001, 0.5 and 0.001 instead, slightly less than 20 millions (19 420 821) calls to the error function would be made and this sure would take VERY long and the precision still would be rather unsatisfactory.
Here are the results of using a finer grid and needs 'just' 22 050 calls to the error function. It already takes a few minutes to finish and while the precision is not very high, the fit already looks much better:
MC13 sheet attached
Another possible approach is a Monte Carlo simulation.
Generate a certain number (parameter N) of random values for alpha, beta and gamma within a given range (parameter vectors A, B and C), calculate the error function for each triple and return the parameters that give the smallest value.
The picture shows a run with 10^4 random triples. Every new run (F9) will give you slightly different results, of course.
MC13 file attached
Thanks Mr Werner,
Could you please convert this last one for my version (Mathcad 13.0) ?
Could you please convert this last one for my version (Mathcad 13.0) ?
Damned! Actually I thought I had done so.
Hope it works this time ...
It worked very well,
I was trying another approach to stop when a certain precision is reached, but I am making some mistakes.
Forgot to transpose the return vector.
0.005 is not a very ambitious value. You may try 0.00036.
Lower values return an error which means that no triple was fund which yields a lower error value.
I changed the return value in this case from a simple NaN to a 3x1 vector of NaNs.
You may try to decrease the step widths then - of course at the cost of calculation time.
IMHO the Monte Carlo approach gave surprising good results within reasonable calc time - so for a brute force attack (as opposed to using a more sophisticated Newton like algorithm) I would vote for it.