コード例 #1
0
        internal static void ApproximateExcessDistributionParametersV4(IList <double> sortedData, out double a, out double c, out double u)
        {
            // The upper tail is defined here by an ECDF interpolating linearly from (u,0) to (x_i, i/n) for data x_1, x_2, ..., x_n all greater than u.
            // This is the model from which we compute the upper tail parameters, using method of moments.
            // This midpoint version works slightly better than the plain ECDF
            double MidpointMSE(IList <double> tailData, double scaleParam, double shapeParam)
            {
                int n = tailData.Count;

                double sum = 0;

                for (int i = 0; i < n - 1; i++)
                {
                    double GHat     = TailCDF(0.5 * (tailData[i] + tailData[i + 1]) - tailData[0], scaleParam, shapeParam);
                    double residual = (2.0 * i + 1) / (2.0 * n) - GHat;
                    sum += residual * residual;
                }
                return(sum / (n - 1));
            }

            double GetScore(double uval, out double scaleParam, out double shapeParam)
            {
                var tailData = GetTailData(sortedData, uval);

                EstimateParamsMOM(tailData, out double scaleEst, out double shapeEst);
                scaleParam = scaleEst;
                shapeParam = shapeEst;
                double score = MidpointMSE(tailData, scaleEst, shapeEst);

                return(score);
            }

            // Try several choices of u evenly spaced over (x_0, x_n-3), and keep the best fit
            var    uValues   = Interpolation.Linspace(sortedData[0], sortedData[sortedData.Count - 5], sortedData.Count / 4);
            double bestU     = 0;
            double bestA     = 0;
            double bestC     = 0;
            double bestScore = double.PositiveInfinity;

            for (int i = 0; i < uValues.Length; i++)
            {
                double score = GetScore(uValues[i], out double scaleEst, out double shapeEst);
                if (score < bestScore)
                {
                    bestScore = score;
                    bestU     = uValues[i];
                    bestA     = scaleEst;
                    bestC     = shapeEst;
                }
            }
            // --- Refine the best so far by bisection search ---
            double delta = uValues[1] - uValues[0];

            for (int i = 0; i < 10; i++)
            {
                delta *= 0.5;
                double forwardU      = Math.Min(bestU + delta, sortedData[sortedData.Count - 3]); // Don't go so high that we don't have data to work with
                double forwardScore  = GetScore(forwardU, out double forwardScale, out double forwardShape);
                double backwardScore = GetScore(bestU - delta, out double backwardScale, out double backwardShape);
                if (forwardScore < bestScore)
                {
                    bestScore = forwardScore;
                    bestU     = forwardU;
                    bestA     = forwardScale;
                    bestC     = forwardShape;
                }
                if (backwardScore < bestScore)
                {
                    bestScore = backwardScore;
                    bestU    -= delta;
                    bestA     = backwardScale;
                    bestC     = backwardShape;
                }
            }

            u = bestU;
            a = bestA;
            c = bestC;
        }