forum.alglib.net

ALGLIB forum
It is currently Mon Dec 23, 2024 5:27 pm

All times are UTC


Forum rules


1. This forum can be used for discussion of both ALGLIB-related and general numerical analysis questions
2. This forum is English-only - postings in other languages will be removed.



Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: Least Squares for Non-Linear Curve fitting in C#
PostPosted: Sun Feb 26, 2017 10:27 am 
Offline

Joined: Sun Feb 26, 2017 9:39 am
Posts: 6
I was using Math.Numerics in C# for my coding purposes but now I am learning Alglib since it has cross platform universal implementations. I am moving my Non-Linear curve fitting for the assumed equation and with sample generated data and upon successful i can fit my own data.
Curve Equation is : y = a * cos(b * x + c) + d * sin(e * x + f)

and C# code is :
Code:
class Program
    {

        public static int Main(string[] args)
        {

            /*string fileName = @"C:\Dropbox\Dropbox\Trade\AVLTreeC#\TestFiles\exchange.csv";
            GetRawDataXY(fileName);*/
            double[] coeffs=InitalizeSampleData(1000);
            System.Console.WriteLine("Curve original Coeffs are : {0}", alglib.ap.format(coeffs, 10));
            Random randNum = new Random();
           // Random randInt = new Random();
            double[] c = Enumerable.Repeat(0, 5 + 1)
                    .Select(i => randNum.NextDouble() + 1).ToArray();
            double epsf = 0;
            double epsx = 0.000001;
            int maxits = 0;
            int info;
            alglib.lsfitstate state;
            alglib.lsfitreport rep;

            //
            // Fitting without weights
            //
            alglib.lsfitcreatefgh(Curve.Xdata, Curve.Ydata, c, out state);
            alglib.lsfitsetcond(state, epsf, epsx, maxits);
            alglib.lsfitfit(state, ModelValue, ModelGradient, ModelHessian, null, null);
            alglib.lsfitresults(state, out info, out c, out rep);
            System.Console.WriteLine("{0}", info); // EXPECTED: 2
            System.Console.WriteLine("Curve Generated coeffs without weights are : {0}", alglib.ap.format(c, 10)); // EXPECTED: [1.5]

           
            System.Console.ReadLine();
            return 0;
        }

        private static double[] InitalizeSampleData(int sampleSize)
        {
            int count = 0;
            Random randNum = new Random();
            // Random randInt = new Random();
            double[] coeffs = Enumerable.Repeat(0, 5 + 1)
                    .Select(j => randNum.NextDouble() + 1).ToArray();

            Curve.Xdata = new double[sampleSize, 1];
            Curve.Ydata = new double[sampleSize];
            for (int i=0;i<sampleSize;i++)
            {
               
                Curve.Xdata[count, 0] = Convert.ToDouble(i+1);
               
                double[] xData =new double[1] { Curve.Xdata[count,0] };
                ModelValue(coeffs, xData, ref Curve.Ydata[count], null);
               
                count++;

            }
            return coeffs;
        }

        protected static void ModelValue(double[] parameters, double[] x, ref double func, object obj)
        {
            func = parameters[0] * Math.Cos(parameters[1] * x[0] + parameters[2]) + parameters[3] * Math.Sin(parameters[4] * x[0] + parameters[5]);
        }

        protected static void ModelGradient(double[] parameters, double[] x, ref double func, double[] gradient, object obj)
        {
            ModelValue(parameters, x, ref func, obj);
            gradient[0] = Math.Cos(parameters[1] * x[0] + parameters[2]);
            gradient[1] = -parameters[0] * Math.Sin(parameters[1] * x[0] + parameters[2]) * x[0];
            gradient[2] = -parameters[0] * Math.Sin(parameters[1] * x[0] + parameters[2]);
            gradient[3] = Math.Sin(parameters[4] * x[0] + parameters[5]);
            gradient[4] = parameters[3] * Math.Cos(parameters[4] * x[0] + parameters[5]) * x[0];
            gradient[5] = parameters[3] * Math.Cos(parameters[4] * x[0] + parameters[5]);
        }

        protected static void ModelHessian(double[] c, double[] x, ref double func, double[] grad, double[,] hess, object obj)
        {
            ModelValue(c, x, ref func, obj);
            ModelGradient(c, x, ref func, grad, obj);
            Hessian(x[0], c, ref hess);
        }

        private static void Hessian(double x, double[] parameters, ref double[,] hess)
        {

            hess[0, 0] = 0; //d2/du2
            hess[1, 0] = -Math.Sin(parameters[1] * x + parameters[2]) * x; //d2/dvdu
            hess[2, 0] = -Math.Sin(parameters[1] * x + parameters[2]); //d2/dwdu
            hess[3, 0] = 0;//d2/dxdu
            hess[4, 0] = 0;//d2/dydu
            hess[5, 0] = 0;//d2/dydz

            hess[0, 1] = -Math.Sin(parameters[1] * x + parameters[2]);//d2/dudv
            hess[1, 1] = -parameters[0] * Math.Cos(parameters[1] * x + parameters[2]) * x * x; //d2/dv2
            hess[2, 1] = -parameters[0] * Math.Cos(parameters[1] * x + parameters[2]) * x; //d2/dwdv
            hess[3, 1] = 0;//d2/dxdv
            hess[4, 1] = 0;//d2/dydv
            hess[5, 1] = 0;////d2/dzdv

            hess[0, 2] = -Math.Sin(parameters[1] * x + parameters[2]) * x;//d2/dudw
            hess[1, 2] = -parameters[0] * Math.Cos(parameters[1] * x + parameters[2]) * x;  //d2/dvdw
            hess[2, 2] = -parameters[0] * Math.Cos(parameters[1] * x + parameters[2]); //d2/dw2
            hess[3, 2] = 0;//d2/dxdw
            hess[4, 2] = 0;//d2/dydw
            hess[5, 2] = 0;////d2/dzdw

            hess[0, 3] = 0;//d2/dudx
            hess[1, 3] = 0;  //d2/dvdx
            hess[2, 3] = 0; //d2/dwdx
            hess[3, 3] = 0; //d2/dx2
            hess[4, 3] = Math.Cos(parameters[4] * x + parameters[5]) * x;//d2/dydx
            hess[5, 3] = Math.Cos(parameters[4] * x + parameters[5]); ////d2/dzdx

            hess[0, 4] = 0;//d2/dudy
            hess[1, 4] = 0;  //d2/dvdy
            hess[2, 4] = 0; //d2/dwdy
            hess[3, 4] = Math.Cos(parameters[4] * x + parameters[5]) * x; //d2/dxdy
            hess[4, 4] = -parameters[3] * Math.Sin(parameters[4] * x + parameters[5]) * x * x;//d2/dy2
            hess[5, 4] = -parameters[3] * Math.Sin(parameters[4] * x + parameters[5]) * x; ////d2/dzdy


            hess[0, 5] = 0;//d2/dudz
            hess[1, 5] = 0;  //d2/dvdz
            hess[2, 5] = 0; //d2/dwdz
            hess[3, 5] = Math.Cos(parameters[4] * x + parameters[5]);  //d2/dxdz
            hess[4, 5] = -parameters[3] * Math.Sin(parameters[4] * x + parameters[5]) * x;//d2/dydz
            hess[5, 5] = -parameters[3] * Math.Sin(parameters[4] * x + parameters[5]); ////d2/dz2



        }

        public static void GetRawDataXY(string filename)
        {
         
            int count = 0;

            var lines = File.ReadAllLines(filename);
            Curve.Xdata = new double[lines.Count(),1];
            Curve.Ydata = new double[lines.Count()];
            foreach (var line in lines)
            {

                var elements = line.Split(';');
                Curve.Xdata[count,0] = Convert.ToDouble(elements[0]);
                Curve.Ydata[count] = Convert.ToDouble(elements[1]);
                count++;

            }
        }
       
        public class Curve
        {
            /*Global Variables*/
            public static double[,] Xdata;
            public static double[] Ydata;
           


        }

       
    }


Ofcourse I am getting some values for Coeffs. But I wonder whether this approach is correct. I suspect on function alglib.lsfitfit algorithm. I have hard in understanding what it does. I just followed documentation. Does it minimize on R2 basis? I want my curve fitting to stop fitting when it reached below criteria:
NewCalcR2-oldCalcR2 is <= Given delta value or
Magnitude of(OldCoffVector-NewCoeffVector) <=GivenDeltaValue or IterationCount reached maximum
Ofcourse I know this by looking at Info value. I need to make sure if this is correct.

Output from Console:
Image

As you see from ouput, original and generated coeff no way near to the value. I want the generated coeffs to be as approximate equal to that. How could i achieve that?


Top
 Profile  
 
 Post subject: Re: Least Squares for Non-Linear Curve fitting in C#
PostPosted: Mon Feb 27, 2017 9:21 am 
Offline
Site Admin

Joined: Fri May 07, 2010 7:06 am
Posts: 927
Hi! I have a few thoughts:

1. You may find it easier to work with optimizer created with lsfitcreatefg (just gradient is used) or even with lsfitcreatef (you specify just function value, numerical differentiation is used, it is often convenient for fast prototyping).

2. I noticed that you use random initial point. However, your target function is notoriously hard one - sine and cosine functions result in difficult landscape with many bad local extrema. So, it is very unlikely that you will converge to the same coeffs as ones which were used to generate dataset.

If you want to solve a toy problem with aim of reproducing original coefficients used to generate dataset, it is better to distort these original coefficients a little, and pass them to lsfit optimizer as initial point. You will see whether it is able to refine them and restore original values - or not. You may start from small distortions, like 1.0E-3 in magnitude, and increase them step by step. Different coefficients will show different tolerances to distortions - ones "hidden within" sine and cosine will be most intolerable.

3. lsfit optimizer returns a lot of information in the rep parameter. Say, rep.rmserror and rep.avgerror contain different kinds of error metric on your dataset - root-mean-square and average.


Top
 Profile  
 
 Post subject: Re: Least Squares for Non-Linear Curve fitting in C#
PostPosted: Mon Feb 27, 2017 12:02 pm 
Offline

Joined: Sun Feb 26, 2017 9:39 am
Posts: 6
Thanks for the reply.

What do you mean by distort the orginal coefficients? Should i substract the magnitude or add the magnitude to the coeffs?

Can i Use distorted coeffs of sample generated data to my actual dataset?


Top
 Profile  
 
 Post subject: Re: Least Squares for Non-Linear Curve fitting in C#
PostPosted: Tue Feb 28, 2017 5:06 pm 
Offline
Site Admin

Joined: Fri May 07, 2010 7:06 am
Posts: 927
Say, generate data using coefficient vector C0. Then, generate random noise E with zero mean and unit standard deviation. Then let C1=C0 + 0.01*E, and try to solve least squares problem using C1 as initial estimate. If everything is right, it should converge to C0.


Top
 Profile  
 
 Post subject: Re: Least Squares for Non-Linear Curve fitting in C#
PostPosted: Sun Mar 05, 2017 6:01 pm 
Offline

Joined: Sun Feb 26, 2017 9:39 am
Posts: 6
Thanks, Its working..


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 5 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 14 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group