C# 拟合曲线


C# 拟合曲线项目:PolyFitCSharp

C# 拟合曲线参考资料:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Research.DynamicDataDisplay;
using Microsoft.Research.DynamicDataDisplay.DataSources;
using Microsoft.Research.DynamicDataDisplay.PointMarkers;
using ViliPetek.LinearAlgebra;

using MathNet;
using MathNet.Numerics;
using MathNet.Numerics.Differentiation;
using MathNet.Numerics.Distributions;
using MathNet.Numerics.Financial;
using MathNet.Numerics.IntegralTransforms;
using MathNet.Numerics.Integration;
using MathNet.Numerics.Interpolation;
using MathNet.Numerics.LinearAlgebra;
using MathNet.Numerics.LinearRegression;
using MathNet.Numerics.OdeSolvers;
using MathNet.Numerics.Optimization;
using MathNet.Numerics.Properties;
using MathNet.Numerics.Providers;
using MathNet.Numerics.Random;
using MathNet.Numerics.RootFinding;
using MathNet.Numerics.Statistics;
using MathNet.Numerics.LinearAlgebra.Double;
using MathNet.Numerics.LinearAlgebra.Factorization;

namespace PolyFitExample
{

    ///// <summary>
    ///// 摘自:https://stackoverflow.com/questions/7792088/non-linear-regression-in-c-sharp
    ///// </summary>
    //public class PolynomialRegression1
    //{
    //    Vector x_data, y_data, coef;
    //    int order;

    //    public PolynomialRegression1(Vector x_data, Vector y_data, int order)
    //    {
    //        if (x_data.Count != y_data.Count)
    //        {
    //            throw new IndexOutOfRangeException();
    //        }
    //        this.x_data = x_data;
    //        this.y_data = y_data;
    //        this.order = order;
    //        int N = x_data.Count;
    //        MathNet.Numerics.LinearAlgebra.Double.Matrix A = new MathNet.Numerics.LinearAlgebra.Double.Matrix(N, order + 1);
    //        for (int i = 0; i < N; i++)
    //        {
    //            A.SetRow(VandermondeRow(x_data[i]), i);
    //        }
         
    //    // Least Squares of |y=A(x)*c| 
    //    //  tr(A)*y = tr(A)*A*c
    //    //  inv(tr(A)*A)*tr(A)*y = c
    //    Matrix At = Matrix.Transpose(A);
    //        Matrix y2 = new Matrix(y_data, N);
    //        coef = (At * A).Solve(At * y2).GetColumnVector(0);
    //    }

    //    Vector VandermondeRow(double x)
    //    {
    //        double[] row = new double[order + 1];
    //        for (int i = 0; i <= order; i++)
    //        {
    //            row[i] = Math.Pow(x, i);
    //        }
    //        return new DenseVector(row);
    //    }

    //    public double Fit(double x)
    //    {
            
          
    //        return Vector.ScalarProduct(VandermondeRow(x), coef);
    //    }

    //    public int Order { get { return order; } }
    //    public Vector Coefficients { get { return coef; } }
    //    public Vector XData { get { return x_data; } }
    //    public Vector YData { get { return y_data; } }
    //}

}

C# 拟合曲线实际应用:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Research.DynamicDataDisplay;
using Microsoft.Research.DynamicDataDisplay.DataSources;
using Microsoft.Research.DynamicDataDisplay.PointMarkers;
using ViliPetek.LinearAlgebra;

using MathNet;
using MathNet.Numerics;
using MathNet.Numerics.Differentiation;
using MathNet.Numerics.Distributions;
using MathNet.Numerics.Financial;
using MathNet.Numerics.IntegralTransforms;
using MathNet.Numerics.Integration;
using MathNet.Numerics.Interpolation;
using MathNet.Numerics.LinearAlgebra;
using MathNet.Numerics.LinearRegression;
using MathNet.Numerics.OdeSolvers;
using MathNet.Numerics.Optimization;
using MathNet.Numerics.Properties;
using MathNet.Numerics.Providers;
using MathNet.Numerics.Random;
using MathNet.Numerics.RootFinding;
using MathNet.Numerics.Statistics;
using MathNet.Numerics.LinearAlgebra.Double;
using MathNet.Numerics.LinearAlgebra.Factorization;




namespace PolyFitExample
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : System.Windows.Window
    {
        private ObservableCollection<Point> _dataSeries;
        private ObservableCollection<Point> _fittedSeries;

        public MainWindow()
        {
            InitializeComponent();
            InitializeGraphs();
       
        }

        private void InitializeGraphs()
        {
            // create the storage for the series
            _dataSeries = new ObservableCollection<Point>();
            _fittedSeries = new ObservableCollection<Point>();

            // create the series
            chartPlotter.AddLineGraph(_dataSeries.AsDataSource(), new Pen(Brushes.Blue, 1),
                new CircleElementPointMarker { Size = 3, Brush = Brushes.Blue, Fill = Brushes.Blue },
                new PenDescription("Data"));
            chartPlotter.AddLineGraph(_fittedSeries.AsDataSource(), new Pen(Brushes.Red, 3), new PenDescription("PolyFit"));

            // hide the standard legend
            chartPlotter.LegendVisibility = System.Windows.Visibility.Hidden;
            chartPlotter.NewLegendVisible = false;
        }


        private void graphButton_Click(object sender, RoutedEventArgs e)
        {
            const int DataSize = 1024;
            double[] x = new double[DataSize];
            double[] y = new double[DataSize];
            Random rand = new Random();
            for (int i = 0; i < DataSize; i++)
            {
                x[i] = i;
                y[i] = Math.Sin(Math.PI * (i / (double)180)); //Math.Sin((double)i / 1024.0 * Math.PI * 2) + (rand.NextDouble() - 0.5);
            }

            //方法一
            //Vector<double> pp = Polyfit01(x, y, (int)orderField.Value);
            //List<double> fity = new List<double>();
            //foreach (int xitem in x)
            //{
            //    double yitem = Polyval(pp, xitem, (int)orderField.Value);
            //    fity.Add(yitem);
            //}

            //方法二
            //Vector<double> desRes = Polyfit02(x, y, (int)orderField.Value);
            //List<double> fity = new List<double>();
            //foreach (int xitem in x)
            //{
            //    double yitem = Polyval(desRes, xitem, (int)orderField.Value);
            //    fity.Add(yitem);
            //}

            //方法三
            Vector<double> desRes = Polyfit03(x, y, (int)orderField.Value);
            List<double> fity = new List<double>();
            foreach (int xitem in x)
            {
                double yitem = Polyval(desRes, xitem, (int)orderField.Value);
                fity.Add(yitem);
            }



            // plot the data
            _dataSeries.SetXY(x, y);
            _fittedSeries.SetXY(x, fity.ToArray());
        }


        public static Vector<double> Polyfit01(DenseVector xData, DenseVector yData, int order)
        {
            DenseMatrix vandMatrix = new DenseMatrix(xData.Count, order + 1);
            
            for (int i = 0; i < xData.Count; i++)
            {
                double[] rowResult = new double[vandMatrix.ColumnCount];
                double mult = 1;
                for (int rowIndex = 0; rowIndex < rowResult.Count(); rowIndex++)
                {
                    rowResult[rowIndex] = mult;
                    mult *= xData[i];
                }
                vandMatrix.SetRow(i, new DenseVector(rowResult));
            }

            DenseVector result = new DenseVector(vandMatrix.ColumnCount);
            for (int j = 0; j < vandMatrix.RowCount; j++)
            {
                for (int i = 0; i < vandMatrix.ColumnCount; i++)
                {
                    result[i] += vandMatrix[j, i] * yData[j];
                }
            }
            return vandMatrix.TransposeThisAndMultiply(vandMatrix).LU().Solve(result);
        }



        public static Vector<double> Polyfit02(double[] x, double[] y, int order)
        {
            Matrix<double> design = Matrix<double>.Build.Dense(x.Length, order + 1, (i, j) => Math.Pow(x[i], j));
            return MultipleRegression.QR(design, Vector<double>.Build.Dense(y));
        }

  

        public static Vector<double> Polyfit03(double[] x, double[] y, int degree)
        {
            DenseMatrix v = new DenseMatrix(x.Length, degree + 1);
            for (int i = 0; i < v.RowCount; i++)
                for (int j = 0; j <= degree; j++) v[i, j] = Math.Pow(x[i], j);
            Matrix<double> yv = new DenseVector(y).ToColumnMatrix();
            QR<double> qr = v.QR();
            var r = qr.R.SubMatrix(0, degree + 1, 0, degree + 1);
            var q = v.Multiply(r.Inverse());
            var p = r.Inverse().Multiply(q.TransposeThisAndMultiply(yv));
            return p.Column(0);
        }

        public static double Polyval(Vector<double> _coefs, double x, int order)
        {
            double[] result = new double[order + 1];
            double mult = 1;
            for (int i = 0; i < result.Count(); i++)
            {
                result[i] = mult;
                mult *= x;
            }
            return _coefs * new DenseVector(result);
        }

        //polyfit用于多项式曲线拟合
        //p = polyfit(x, y, m)
        //其中, x, y为已知数据点向量, 分别表示横,纵坐标, m为拟合多项式的次数, 结果返回m次拟合多项式系数, 从高次到低次存放在向量p中.
        //y0=polyval(p, x0)
        //可求得多项式在x0处的值y0

        //public static void TestGet()
        //{
        //    const int degree = 2;
        //    var x = new[] { 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0 };
        //    var y = new[] { 1.0, 6.0, 17.0, 34.0, 57.0, 86.0, 121.0, 162.0, 209.0, 262.0, 321.0 };
        //    var p = Polyfit(x, y, degree);
        //    foreach (var d in p) Console.Write("{0} ", d);
        //    Console.WriteLine();
        //    for (int i = 0; i < x.Length; i++)
        //        Console.WriteLine("{0} => {1} diff {2}", x[i], Polyval(p, x[i]), y[i] - Polyval(p, x[i]));
        //    Console.ReadKey(true);
        //}
    }

}

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM