예제 #1
0
        private AccordResult CalculateLinearRegression(List <BalancePointPair> allBalancePointPairs, WthNormalParams normalParamsKey)
        {
            var allBalancePointGroups = allBalancePointPairs.GroupBy(s => new { s.CoolingBalancePoint, s.HeatingBalancePoint });

            List <AccordResult> accordResults = new List <AccordResult>();

            foreach (var group in allBalancePointGroups)
            {
                try
                {
                    List <BalancePointPair> IdenticalBalancePointPairsFromAllReadings = group.ToList();
                    BalancePointPair        _pointPair = IdenticalBalancePointPairsFromAllReadings.First();
                    int readingsCount = IdenticalBalancePointPairsFromAllReadings.Count;

                    double[] fullYData         = new double[readingsCount];
                    double[] fullYDataDailyAvg = new double[readingsCount];

                    double[][] hcddMatrix = new double[readingsCount][];

                    double[][] hcddMatrixNonDaily = new double[readingsCount][];

                    foreach (BalancePointPair balancePointPair in IdenticalBalancePointPairsFromAllReadings)
                    {
                        fullYData[IdenticalBalancePointPairsFromAllReadings.IndexOf(balancePointPair)] = (balancePointPair.ActualUsage);

                        fullYDataDailyAvg[IdenticalBalancePointPairsFromAllReadings.IndexOf(balancePointPair)]
                            = (balancePointPair.ActualUsage / balancePointPair.DaysInReading);

                        hcddMatrix[IdenticalBalancePointPairsFromAllReadings.IndexOf(balancePointPair)] = new double[]
                        {
                            (balancePointPair.HeatingDegreeDays / balancePointPair.DaysInReading),
                            (balancePointPair.CoolingDegreeDays / balancePointPair.DaysInReading)
                        };
                    }

                    if (!(fullYData.Sum() > 0))
                    {
                        return(new AccordResult());
                    }

                    double[] avgHddsForEachReadingInYear = new double[readingsCount];
                    double[] avgCddsForEachReadingInYear = new double[readingsCount];

                    for (int i = 0; i < readingsCount; i++)
                    {
                        avgHddsForEachReadingInYear[i] = hcddMatrix[i][0];
                        avgCddsForEachReadingInYear[i] = hcddMatrix[i][1];
                    }

                    double[] modelParams = new double[3];
                    modelParams[0] = 0;
                    modelParams[1] = 0;
                    modelParams[2] = 0;

                    if (_pointPair.HeatingBalancePoint == 0 && _pointPair.CoolingBalancePoint == 0)
                    {
                        double[] onesVector = new double[readingsCount];

                        for (int i = 0; i < readingsCount; i++)
                        {
                            onesVector[i] = 1;
                        }

                        modelParams[0] = Fit.LineThroughOrigin(onesVector, fullYDataDailyAvg);

                        OrdinaryLeastSquares ols = new OrdinaryLeastSquares()
                        {
                            UseIntercept = false
                        };

                        double r2 = MathNet.Numerics.GoodnessOfFit.CoefficientOfDetermination(
                            onesVector.Select(x => x * modelParams[0]), fullYDataDailyAvg);

                        AccordResult accordResult = new AccordResult()
                        {
                            IsSimpleSingleRegression = true,
                            HeatingBP = _pointPair.HeatingBalancePoint,
                            CoolingBP = _pointPair.CoolingBalancePoint,
                            Intercept = modelParams[0],
                            R2Accord  = r2,
                            //R2Accord = 0
                        };

                        accordResults.Add(accordResult);
                    }
                    else if (_pointPair.CoolingBalancePoint != 0 && _pointPair.HeatingBalancePoint != 0)
                    {
                        try
                        {
                            MultipleLinearRegressionAnalysis mlra = new MultipleLinearRegressionAnalysis(intercept: true);
                            mlra.Learn(hcddMatrix, fullYDataDailyAvg);

                            var regressionAccord = mlra.Regression;

                            double[] predictedAccord = regressionAccord.Transform(hcddMatrix);

                            double r2Accord = new RSquaredLoss(numberOfInputs: 2, expected: fullYDataDailyAvg)
                            {
                                Adjust = false
                            }.Loss(predictedAccord);

                            double r2Coeff = regressionAccord.CoefficientOfDetermination(hcddMatrix, fullYDataDailyAvg, adjust: false);

                            bool FTestFailed = !mlra.FTest.Significant;

                            AccordResult accordResult = new AccordResult()
                            {
                                IsMultipleLinearRegression = true,
                                HeatingBP   = _pointPair.HeatingBalancePoint,
                                CoolingBP   = _pointPair.CoolingBalancePoint,
                                Intercept   = regressionAccord.Intercept,
                                B2          = regressionAccord.Weights[0],
                                B4          = regressionAccord.Weights[1],
                                R2Accord    = r2Accord,
                                FTestFailed = FTestFailed
                            };

                            //int degreesOfFreedom = normalParamsKey.MoCt - 3;

                            double degreesOfFreedomAsDouble = mlra.Regression.GetDegreesOfFreedom(readingsCount);
                            int    degreesOfFreedom         = Convert.ToInt32(degreesOfFreedomAsDouble);

                            //if (degreesOfFreedom != 9)
                            //{
                            //    Log.Warning($"Multivariable regression. DOF expected to be 9. is: {degreesOfFreedom}");
                            //}

                            //if (degreesOfFreedom != dof)
                            //{
                            //    Console.WriteLine($"dof different. mlra.dof = {dof} expected = {degreesOfFreedom}");
                            //}

                            double s = Math.Sqrt(fullYDataDailyAvg.Subtract(predictedAccord).Pow(2).Sum() / degreesOfFreedom);

                            double ssxHdd = Math.Sqrt((avgHddsForEachReadingInYear.Subtract(avgHddsForEachReadingInYear.Mean())).Pow(2).Sum());
                            double ssxCdd = Math.Sqrt((avgCddsForEachReadingInYear.Subtract(avgCddsForEachReadingInYear.Mean())).Pow(2).Sum());

                            double seSubHdd = s / ssxHdd;
                            double seSubCdd = s / ssxCdd;

                            double tStatisticHdd = regressionAccord.Weights[0] / seSubHdd;
                            double tStatisticCdd = regressionAccord.Weights[1] / seSubCdd;

                            double tCriticalFivePercent = 2.262156;
                            double tCriticalTenPercent  = 1.833113;

                            bool myTestHdd = Math.Abs(tStatisticHdd) >= tCriticalTenPercent;
                            bool myTestCdd = Math.Abs(tStatisticCdd) >= tCriticalTenPercent;

                            //if (myTestHdd != mlra.Coefficients[0].TTest.Significant && degreesOfFreedom != 9)
                            //{
                            //    Console.WriteLine($"nope. mystat - {tStatisticHdd} accordstat - {mlra.Coefficients[0].TTest.Statistic} " +
                            //        $"accordCritical - {mlra.Coefficients[0].TTest.CriticalValue}");
                            //}

                            //if (myTestCdd != mlra.Coefficients[1].TTest.Significant && degreesOfFreedom != 9)
                            //{
                            //    Console.WriteLine($"nope. mystat - {tStatisticCdd} accordstat - {mlra.Coefficients[1].TTest.Statistic} " +
                            //        $"accordCritical - {mlra.Coefficients[1].TTest.CriticalValue}");
                            //}

                            //if (mlra.Coefficients.All(x => x.TTest.Significant) &&
                            //    mlra.Coefficients.All(x => x.Value > 0) &&
                            //    mlra.Regression.Intercept > 0 &&
                            //    r2Accord >= 0.7500)
                            //{
                            //    accordResults.Add(accordResult);
                            //}
                            if (
                                myTestHdd &&
                                myTestCdd &&
                                mlra.Coefficients.All(x => x.Value > 0) &&
                                mlra.Regression.Intercept > 0
                                //&& accordResult.R2Accord >= 0.75
                                )
                            {
                                accordResults.Add(accordResult);
                            }
                        }
                        catch (Exception e)
                        {
                            Log.Debug($"AccID/UtilID/UnitID: {normalParamsKey.AccID}/{normalParamsKey.UtilID}/{normalParamsKey.UnitID} >> " +
                                      $"MultipleLinearRegressionAnalysis Exception: {e.Message}");
                        }
                    }
                    else if (_pointPair.HeatingBalancePoint > 0)
                    {
                        OrdinaryLeastSquares ols = new OrdinaryLeastSquares()
                        {
                            UseIntercept = true
                        };

                        SimpleLinearRegression regressionAccord = ols.Learn(avgHddsForEachReadingInYear, fullYDataDailyAvg);

                        double[] predictedAccord = regressionAccord.Transform(avgHddsForEachReadingInYear);

                        double r2Accord = new RSquaredLoss(1, fullYDataDailyAvg).Loss(predictedAccord);

                        //int degreesOfFreedom = normalParamsKey.MoCt - 2;

                        double degreesOfFreedomAsDouble = regressionAccord.GetDegreesOfFreedom(readingsCount);
                        int    degreesOfFreedom         = Convert.ToInt32(degreesOfFreedomAsDouble);

                        //if (degreesOfFreedom != 10)
                        //{
                        //    Log.Warning($"Single variable regression. DOF expected to be 10. is: {degreesOfFreedom}");
                        //}

                        double ssx = Math.Sqrt((avgHddsForEachReadingInYear.Subtract(avgHddsForEachReadingInYear.Mean())).Pow(2).Sum());
                        double s   = Math.Sqrt(fullYDataDailyAvg.Subtract(predictedAccord).Pow(2).Sum() / degreesOfFreedom);

                        double error = regressionAccord.GetStandardError(avgHddsForEachReadingInYear, fullYDataDailyAvg);

                        double seSubB = s / ssx;

                        double hypothesizedValue = 0;

                        double tStatistic = regressionAccord.Slope / seSubB;

                        double tCriticalFivePercent = 2.228138;
                        double tCriticalTenPercent  = 1.812461;

                        bool myTest = Math.Abs(tStatistic) >= tCriticalTenPercent;

                        //TTest tTest = new TTest(
                        //    estimatedValue: regressionAccord.Slope, standardError: seSubB, degreesOfFreedom: degreesOfFreedom,
                        //    hypothesizedValue: hypothesizedValue, alternate: OneSampleHypothesis.ValueIsDifferentFromHypothesis
                        //    );

                        //if (myTest != tTest.Significant)
                        //{
                        //    Console.WriteLine($"nope. mystat - {tStatistic} accordstat - {tTest.Statistic} accordCritical - {tTest.CriticalValue}");
                        //}

                        AccordResult accordResult = new AccordResult()
                        {
                            IsSimpleSingleRegression = true,
                            HeatingBP = _pointPair.HeatingBalancePoint,
                            Intercept = regressionAccord.Intercept,
                            B2        = regressionAccord.Slope,
                            R2Accord  = r2Accord
                        };

                        //if (tTest.Significant && accordResult.B2 > 0 && r2Accord >= 0.7500)
                        //{
                        //    accordResults.Add(accordResult);
                        //}
                        if (myTest &&
                            accordResult.B2 > 0 &&
                            accordResult.Intercept > 0
                            //&& r2Accord >= 0.7500
                            )
                        {
                            accordResults.Add(accordResult);
                        }
                    }
                    else if (_pointPair.CoolingBalancePoint > 0)
                    {
                        OrdinaryLeastSquares ols = new OrdinaryLeastSquares()
                        {
                            UseIntercept = true
                        };

                        SimpleLinearRegression regressionAccord = ols.Learn(avgCddsForEachReadingInYear, fullYDataDailyAvg);

                        double[] predictedAccord = regressionAccord.Transform(avgCddsForEachReadingInYear);
                        double   r2Accord        = new RSquaredLoss(1, fullYDataDailyAvg).Loss(predictedAccord);

                        //int degreesOfFreedom = normalParamsKey.MoCt - 2;

                        double degreesOfFreedomAsDouble = regressionAccord.GetDegreesOfFreedom(readingsCount);
                        int    degreesOfFreedom         = Convert.ToInt32(degreesOfFreedomAsDouble);

                        //if (degreesOfFreedom != 10)
                        //{
                        //    Log.Warning($"Single variable regression. DOF expected to be 10. is: {degreesOfFreedom}");
                        //}

                        double ssx = Math.Sqrt(avgCddsForEachReadingInYear.Subtract(avgCddsForEachReadingInYear.Mean()).Pow(2).Sum());
                        double s   = Math.Sqrt(fullYDataDailyAvg.Subtract(predictedAccord).Pow(2).Sum() / degreesOfFreedom);

                        double seSubB            = s / ssx;
                        double hypothesizedValue = 0;

                        double tStatistic = regressionAccord.Slope / seSubB;

                        double tCriticalFivePercent = 2.22813885198627;
                        double tCriticalTenPercent  = 1.812461;

                        bool myTest = Math.Abs(tStatistic) >= tCriticalTenPercent;

                        //TTest tTest = new TTest(
                        //    estimatedValue: regressionAccord.Slope, standardError: seSubB, degreesOfFreedom: degreesOfFreedom,
                        //    hypothesizedValue: hypothesizedValue, alternate: OneSampleHypothesis.ValueIsDifferentFromHypothesis
                        //    );

                        //if (myTest != tTest.Significant)
                        //{
                        //    Console.WriteLine($"nope. mystat - {tStatistic} accordstat - {tTest.Statistic} accordCritical - {tTest.CriticalValue}");
                        //}

                        AccordResult accordResult = new AccordResult()
                        {
                            IsSimpleSingleRegression = true,
                            CoolingBP = _pointPair.CoolingBalancePoint,
                            Intercept = regressionAccord.Intercept,
                            B4        = regressionAccord.Slope,
                            R2Accord  = r2Accord
                        };

                        //if (tTest.Significant && accordResult.B4 > 0 && r2Accord >= 0.7500)
                        //{
                        //    accordResults.Add(accordResult);
                        //}
                        if (
                            myTest &&
                            accordResult.B4 > 0
                            //&& r2Accord >= 0.7500
                            )
                        {
                            accordResults.Add(accordResult);
                        }
                    }
                }
                catch (Exception e)
                {
                    Log.Debug($"AccID/UtilID/UnitID: {normalParamsKey.AccID}/{normalParamsKey.UtilID}/{normalParamsKey.UnitID} >> {e.Message} {e.StackTrace}");
                }
            }

            AccordResult accordWinner = accordResults
                                        .Where(s => s.Intercept >= 0)
                                        .OrderByDescending(s => s.R2Accord).ToList().FirstOrDefault();

            return(accordWinner);
        }