【问题标题】:Confidence Intervals Using MathNET使用 MathNET 的置信区间
【发布时间】:2014-01-15 04:01:29
【问题描述】:

我有一个IEnumerable<double> 数据样本。我想计算信号/数据的 90% 置信区间。我可以使用MathNET library,但我对如何正确使用该库感到困惑。给定我的数据,想法是返回两个额外的数据数组,其中包含原始信号的置信区间

using MathNet.Numerics.Statistics;
using MathNet.Numerics.Distributions;

public static List<double[]> ConfidenceIntervals(IEnumerable<double> sample, double interval)
{
    Contract.Requires(interval > 0 && interval < 1.0);
    int sampleSize = sample.Count();
    double alpha = 1.0 - interval;
    double mean = sample.Mean();
    double sd = sample.StandardDeviation();

    double t, mu;
    double[] upper = new double[sampleSize];
    double[] lower = new double[sampleSize];
    StudentT studentT = new StudentT(mean, alpha, sampleSize - 1);
    int index = 0;
    foreach (double d in sample)
    {
        t = studentT.CumulativeDistribution(d);
        double tmp = t * (sd / Math.Sqrt(sampleSize));
        mu = mean - tmp;
        upper[index] = d + mu;
        lower[index] = d - mu;
    }
    return new List<double[]>() { upper, lower };
}

这在数学方面确实并不复杂,我只是对如何正确使用MathNET library 中可用的函数/方法感到困惑。

【问题讨论】:

    标签: c# confidence-interval math.net mathnet-numerics


    【解决方案1】:

    我不完全确定我是否理解信号的置信区间应该如何应用于信号的每个样本,但我们可以按如下方式计算样本集的置信区间:

    public static Tuple<double, double> A(double[] samples, double interval)
    {
        double theta = (interval + 1.0)/2;
        double mean = samples.Mean();
        double sd = samples.StandardDeviation();
        double T = StudentT.InvCDF(0,1,samples.Length-1,theta);
        double t = T * (sd / Math.Sqrt(samples.Length));
        return Tuple.Create(mean-t, mean+t);
    }
    

    除了我们计算 T 的行没有编译,因为不幸的是在当前的 Math.NET Numerics 中还没有 StudentT.InvCDF。但与此同时,我们仍然可以对其进行数值评估作为一种解决方法:

    var student = new StudentT(0,1,samples.Length-1);
    double T = FindRoots.OfFunction(x => student.CumulativeDistribution(x)-theta,-800,800);
    

    例如,对于 16 个样本和 alpha 0.05,我们得到 2.131,正如预期的那样。如果有超过 ~60-100 个样本,这也可以用正态分布来近似:

    double T = Nomal.InvCDF(0,1,theta);
    

    总而言之:

    public static Tuple<double, double> B(double[] samples, double interval)
    {
        double theta = (interval + 1.0)/2;
        double T = FindRoots.OfFunction(x => StudentT.CDF(0,1,samples.Length-1,x)-theta,-800,800);
    
        double mean = samples.Mean();
        double sd = samples.StandardDeviation();
        double t = T * (sd / Math.Sqrt(samples.Length));
        return Tuple.Create(mean-t, mean+t);
    }
    

    这还不是完整的答案,因为我知道您想以某种方式将置信区间应用于每个样本,但希望它有助于实现目标。

    PS:使用 Math.NET Numerics v3.0.0-alpha7

    【讨论】:

    • Crisroph,非常感谢您的回复。我现在完成了这一天,所以明天将实施并反馈。明天我可能会问另一个关于 MathNET 的问题,它是关于执行矩阵运算时的强制转换要求Matrix M = (DenseMatrix)(SomeMatrixA * SomeMatrixB)。这是一个单独的问题,所以我明天再问一个。另外,非常感谢您维护如此出色的图书馆!万事如意...
    • 抱歉,这里给您回复的延迟。我刚刚尝试使用您在上面提供的代码,但我没有可用的 StudentT.CDF 方法;然而,正态分布存在。我需要更新我的图书馆吗?
    • 注意,我说的是Normal 发行版。有一个名为CDFpublic static 方法,但我似乎无法使用最新的NuGet 包访问它;如果我下载源代码并自己编译就可以了吗?
    • StudentT.CDF 已添加到 v3.0.0-alpha7(程序集版本 3.0.0.40)中。你用的是什么版本?
    • 源代码没有按设计在本地构建上设置版本号。如果您从 GitHub 获得源代码,它们可能是最新的。对于 NuGet,您需要明确允许预发布:PM&gt; Install-Package MathNet.Numerics -Pre
    【解决方案2】:

    我注意到您没有在foreach 循环中增加索引值。这将使索引 0 处的值被下一次计算替换(当您尝试设置 upper[index]lower[index] 值时)。

    所以我想这就是你得到错误结果的原因。

    如果是这样,你的代码应该是

    using MathNet.Numerics.Statistics;
    using MathNet.Numerics.Distributions;
    
    public static List<double[]> ConfidenceIntervals(IEnumerable<double> sample, double interval)
    {
        Contract.Requires(interval > 0 && interval < 1.0);
        int sampleSize = sample.Count();
        double alpha = 1.0 - interval;
        double mean = sample.Mean();
        double sd = sample.StandardDeviation();
    
        double t, mu;
        double[] upper = new double[sampleSize];
        double[] lower = new double[sampleSize];
        StudentT studentT = new StudentT(mean, alpha, sampleSize - 1);
        int index = 0;
        foreach (double d in sample)
        {
            t = studentT.CumulativeDistribution(d);
            double tmp = t * (sd / Math.Sqrt(sampleSize));
            mu = mean - tmp;
            upper[index] = d + mu;
            lower[index] = d - mu;
            index++;
        }
        return new List<double[]>() { upper, lower };
    }
    

    【讨论】:

    • +1 您对索引增量是正确的。但是,当我输入问题时,这是一个疏忽,所以很抱歉。上面的实现给出了错误的置信水平。他们很遥远。你使用 MathNET 吗?您还可以看到与上述实现有什么不同之处吗?感谢您的宝贵时间。
    • 不,我从不使用它,但我已经安装了这个库。也许我可以为您提供更多帮助:) 我将在我的计算机上进行测试,我想知道 sampleinterval 值是什么?
    猜你喜欢
    • 2014-06-30
    • 2021-07-06
    • 1970-01-01
    • 2018-12-21
    • 2016-11-28
    • 1970-01-01
    • 2015-09-14
    • 2020-02-04
    • 1970-01-01
    相关资源
    最近更新 更多