CanvasClean.LoessInterpolator.train C# (CSharp) Method

train() private method

Train a LOESS model
private train ( double xvals, double yvals, double xStep, int ascendingOrder, bool computeFitted = true ) : LoessModel
xvals double
yvals double y values
xStep double x-value step size
ascendingOrder int
computeFitted bool
return LoessModel
        private LoessModel train(double[] xvals, double[] yvals, double xStep, int[] ascendingOrder,
            bool computeFitted = true)
        {
            if (xvals.Length != yvals.Length)
            {
                throw new ApplicationException(string.Format("Loess expects the abscissa and ordinate arrays to be of the same Size, but got {0} abscisssae and {1} ordinatae", xvals.Length, yvals.Length));
            }

            int n = xvals.Length;
            if (n <= 1)
            {
                return new LoessModel(xvals, yvals, new double[] { yvals[0] }, null, ascendingOrder, null);
            }

            checkAllFiniteReal(xvals, true);
            checkAllFiniteReal(yvals, false);
            checkIncreasing(xvals);

            int bandwidthInPoints = (int)Math.Ceiling(bandwidth * n);

            int leastBandwithInPoints = 1 + polynomialDegree;
            if (bandwidthInPoints < leastBandwithInPoints)
            {
                throw new ApplicationException(string.Format(
                    "the bandwidth must be large enough to accomodate at least {0} points. There are {1} data points, and bandwidth must be at least {2} but it is only {3}",
                    leastBandwithInPoints, n, (double)leastBandwithInPoints / n, bandwidth
                ));
            }

            double[] fitted = null;
            double[] residuals = null;
            double[] robustnessWeights = null;

            if (robustnessIters > 0) { computeFitted = true; } // override computeFitted
            if (computeFitted || robustnessIters > 0) { fitted = new double[n]; }

            // Do an initial fit and 'robustnessIters' robustness iterations.
            // This is equivalent to doing 'robustnessIters+1' robustness iterations
            // starting with all robustness weights set to 1.
            if (robustnessIters > 0)
            {
                residuals = new double[n];
                robustnessWeights = new double[n];
                for (int i = 0; i < robustnessWeights.Length; i++) robustnessWeights[i] = 1;
            }

            for (int iter = 0; iter <= robustnessIters; ++iter)
            {
                int[] bandwidthInterval = { 0, bandwidthInPoints - 1 };
                // At each x, compute a local weighted linear regression
                for (int i = 0; i < n; ++i)
                {
                    double x = xvals[i];

                    // Find out the interval of source points on which
                    // a regression is to be made.
                    if (i > 0)
                    {
                        var newBandwidthInterval = updateBandwidthInterval(x, xvals, bandwidthInterval);
                        if (newBandwidthInterval != null) { bandwidthInterval = newBandwidthInterval; }
                    }

                    // Linear regression to get the coeeficients
                    if (computeFitted || robustnessIters > 0)
                    {
                        double[] coefficients = computeCoefficients(x, xvals, yvals, robustnessWeights, bandwidthInterval);
                        fitted[i] = predict(x, coefficients);
                    }
                    if (robustnessIters > 0) { residuals[i] = Math.Abs(yvals[i] - fitted[i]); }
                }

                // No need to recompute the robustness weights at the last
                // iteration, they won't be needed anymore
                if (iter == robustnessIters) { break; }

                // Recompute the robustness weights.
                double medianResidual = Utilities.Median(residuals); // Find the median residual

                if (medianResidual == 0) { break; }

                for (int i = 0; i < n; ++i)
                {
                    double arg = residuals[i] / (6 * medianResidual);
                    robustnessWeights[i] = (arg >= 1) ? 0 : Math.Pow(1 - arg * arg, 2);
                }
            }

            List<LoessInterval> intervals = computeIntervals(xvals, xStep, bandwidthInPoints);

            return new LoessModel(xvals, yvals, fitted, robustnessWeights, ascendingOrder, intervals);
        }