зеркало из https://github.com/dotnet/infer.git
InnerQuantiles and OuterQuantiles throw on infinite quantiles. InnerQuantiles.GetLogProb and GetQuantile are non-decreasing.
This commit is contained in:
Родитель
70ae46cd79
Коммит
b7ab86af1b
|
@ -2585,9 +2585,8 @@ namespace Microsoft.ML.Probabilistic.Math
|
|||
// Therefore scale <= double.MaxValue/Y.Count/abs(Y[j]*US[j,k]).
|
||||
double absY = System.Math.Abs(Y[j]);
|
||||
double absU = System.Math.Abs(US[j, k]);
|
||||
bool Ygt1 = (absY > 1);
|
||||
double thisUpperBound;
|
||||
if (Ygt1)
|
||||
if (absY > 1)
|
||||
{
|
||||
thisUpperBound = limit / absY / absU;
|
||||
}
|
||||
|
|
|
@ -48,6 +48,8 @@ namespace Microsoft.ML.Probabilistic.Distributions
|
|||
{
|
||||
this.quantiles[i] = canGetQuantile.GetQuantile((i + 1.0) / (quantileCount + 1.0));
|
||||
}
|
||||
OuterQuantiles.AssertFinite(quantiles, nameof(canGetQuantile));
|
||||
OuterQuantiles.AssertNondecreasing(quantiles, nameof(canGetQuantile));
|
||||
lowerGaussian = GetLowerGaussian(quantiles);
|
||||
upperGaussian = GetUpperGaussian(quantiles);
|
||||
}
|
||||
|
@ -72,16 +74,17 @@ namespace Microsoft.ML.Probabilistic.Distributions
|
|||
return quantiles;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public double GetProbLessThan(double x)
|
||||
{
|
||||
int n = quantiles.Length;
|
||||
if (x < quantiles[0])
|
||||
{
|
||||
return lowerGaussian.GetProbLessThan(x);
|
||||
return Math.Min(lowerGaussian.GetProbLessThan(x), 1.0/(n+1));
|
||||
}
|
||||
int n = quantiles.Length;
|
||||
if (x > quantiles[n - 1])
|
||||
{
|
||||
return upperGaussian.GetProbLessThan(x);
|
||||
return Math.Max(upperGaussian.GetProbLessThan(x), n/(n+1.0));
|
||||
}
|
||||
return GetProbLessThan(x, quantiles);
|
||||
}
|
||||
|
@ -156,7 +159,7 @@ namespace Microsoft.ML.Probabilistic.Distributions
|
|||
double mean, stddev;
|
||||
GetGaussianFromQuantiles(quantiles[0], p0, quantiles[i], p1, out mean, out stddev);
|
||||
Gaussian result = Gaussian.FromMeanAndVariance(mean, stddev * stddev);
|
||||
if (!result.IsProper() || double.IsNaN(result.GetMean()) || double.IsInfinity(result.GetMean()))
|
||||
if (result.IsPointMass || !result.IsProper() || double.IsNaN(result.GetMean()) || double.IsInfinity(result.GetMean()))
|
||||
{
|
||||
return Gaussian.PointMass(quantiles[0]);
|
||||
}
|
||||
|
@ -184,6 +187,10 @@ namespace Microsoft.ML.Probabilistic.Distributions
|
|||
double p1 = (i + 1.0) / (n + 1);
|
||||
double mean, stddev;
|
||||
GetGaussianFromQuantiles(quantiles[n - 1], p0, quantiles[i], p1, out mean, out stddev);
|
||||
if (double.IsNaN(mean) || double.IsInfinity(mean))
|
||||
{
|
||||
return Gaussian.PointMass(quantiles[n - 1]);
|
||||
}
|
||||
Gaussian result = Gaussian.FromMeanAndVariance(mean, stddev * stddev);
|
||||
if (!result.IsProper() || double.IsNaN(result.GetMean()) || double.IsInfinity(result.GetMean()))
|
||||
{
|
||||
|
|
|
@ -32,8 +32,8 @@ namespace Microsoft.ML.Probabilistic.Distributions
|
|||
{
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
if (double.IsInfinity(array[i])) throw new ArgumentOutOfRangeException(paramName, $"{paramName}[{i}] {array[i]}");
|
||||
if (double.IsNaN(array[i])) throw new ArgumentOutOfRangeException(paramName, $"{paramName}[{i}] {array[i]}");
|
||||
if (double.IsInfinity(array[i])) throw new ArgumentOutOfRangeException(paramName, array[i], $"Array element is infinite: {paramName}[{i}]={array[i]}");
|
||||
if (double.IsNaN(array[i])) throw new ArgumentOutOfRangeException(paramName, array[i], $"Array element is NaN: {paramName}[{i}]={array[i]}");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ namespace Microsoft.ML.Probabilistic.Distributions
|
|||
{
|
||||
for (int i = 1; i < array.Length; i++)
|
||||
{
|
||||
if (array[i] < array[i - 1]) throw new ArgumentException($"Array is not non-decreasing: {paramName}[{i}] {array[i]} < {paramName}[{i - 1}] {array[i - 1]}", paramName);
|
||||
if (array[i] < array[i - 1]) throw new ArgumentException($"Decreasing array elements: {paramName}[{i}] {array[i]} < {paramName}[{i - 1}] {array[i - 1]}", paramName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -124,19 +124,23 @@ namespace Microsoft.ML.Probabilistic.Distributions
|
|||
/// <summary>
|
||||
/// Returns the largest quantile such that ((quantile - lowerItem)/(upperItem - lowerItem) + lowerIndex)/(n-1) <= probability.
|
||||
/// </summary>
|
||||
/// <param name="probability"></param>
|
||||
/// <param name="probability">A number between 0 and 1.</param>
|
||||
/// <param name="lowerIndex"></param>
|
||||
/// <param name="lowerItem"></param>
|
||||
/// <param name="upperItem"></param>
|
||||
/// <param name="n"></param>
|
||||
/// <param name="lowerItem">Must be finite.</param>
|
||||
/// <param name="upperItem">Must be finite and at least lowerItem.</param>
|
||||
/// <param name="n">Must be greater than 1</param>
|
||||
/// <returns></returns>
|
||||
internal static double GetQuantile(double probability, double lowerIndex, double lowerItem, double upperItem, long n)
|
||||
{
|
||||
if (n == 1) throw new ArgumentOutOfRangeException("n == 1");
|
||||
if(probability < 0) throw new ArgumentOutOfRangeException(nameof(probability), probability, $"{nameof(probability)} < 0");
|
||||
if (probability > 1) throw new ArgumentOutOfRangeException(nameof(probability), probability, $"{nameof(probability)} > 1");
|
||||
if (n <= 1) throw new ArgumentOutOfRangeException(nameof(n), n, "n <= 1");
|
||||
double pos = MMath.LargestDoubleProduct(n - 1, probability);
|
||||
double frac = MMath.LargestDoubleSum(-lowerIndex, pos);
|
||||
if (upperItem < lowerItem) throw new ArgumentOutOfRangeException(nameof(upperItem), upperItem, $"{nameof(upperItem)} ({upperItem}) < {nameof(lowerItem)} ({lowerItem})");
|
||||
if (upperItem == lowerItem) return lowerItem;
|
||||
// The above check ensures diff > 0
|
||||
double diff = upperItem - lowerItem;
|
||||
if (diff == 0) return lowerItem;
|
||||
double offset = MMath.LargestDoubleProduct(diff, frac);
|
||||
return MMath.LargestDoubleSum(lowerItem, offset);
|
||||
}
|
||||
|
|
|
@ -137,10 +137,12 @@ namespace Microsoft.ML.Probabilistic.Distributions
|
|||
if (probability > 1.0) throw new ArgumentOutOfRangeException(nameof(probability), "probability > 1.0");
|
||||
// compute the min and max of the retained items
|
||||
double lowerBound = double.PositiveInfinity, upperBound = double.NegativeInfinity;
|
||||
bool countGreaterThanZero = false;
|
||||
for (int bufferIndex = 0; bufferIndex < buffers.Length; bufferIndex++)
|
||||
{
|
||||
double[] buffer = buffers[bufferIndex];
|
||||
int count = countInBuffer[bufferIndex];
|
||||
if (count > 0) countGreaterThanZero = true;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
double item = buffer[i];
|
||||
|
@ -150,7 +152,7 @@ namespace Microsoft.ML.Probabilistic.Distributions
|
|||
}
|
||||
if (probability == 1.0) return MMath.NextDouble(upperBound);
|
||||
if (probability == 0.0) return lowerBound;
|
||||
if (double.IsPositiveInfinity(lowerBound)) throw new Exception("QuantileEstimator has no data");
|
||||
if (!countGreaterThanZero) throw new Exception("QuantileEstimator has no data");
|
||||
if (lowerBound == upperBound) return upperBound;
|
||||
// use bisection
|
||||
while (true)
|
||||
|
|
|
@ -104,8 +104,6 @@ namespace TestApp
|
|||
#endif
|
||||
watch.Stop();
|
||||
Console.WriteLine("elapsed time = {0}ms", watch.ElapsedMilliseconds);
|
||||
|
||||
Console.ReadKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Различия файлов скрыты, потому что одна или несколько строк слишком длинны
Загрузка…
Ссылка в новой задаче