【问题标题】:huge numerical errors when trying to normalize data尝试规范化数据时出现巨大的数值错误
【发布时间】:2018-02-12 04:21:39
【问题描述】:

我经常通过程序来处理一些数据。做起来很简单,让我们考虑数据是一系列相同大小的数字。 当数字高得不合理时,标准化数据可能很有用。一种常见的转换是从所有值中减去平均值。在此转换之后,转换后的数据将具有平均零。

平均为零后可以进行的其他常见转换是将数据除以其标准差。应用此转换后,新数据具有单位方差。

当处理以这种方式归一化的数据时,我希望数值误差应该更小。但是,我似乎无法进行这些转换,因为即使我尝试计算标准偏差也会出现数值错误。

Bellow 是 C# 中的示例代码,我在其中尝试计算标准偏差。即使没有(公式的)统计知识,也可以很容易地看出程序的输出应该为零。 (如果数据是常数数组,则数据平方的平均值等于平均值​​的平方。)

static double standardDeviation(double[] data)
{
    double sum = 0;
    double sumOfSquares = 0;
    foreach (double number in data)
    {
        sum += number;
        sumOfSquares += number * number;
    }
    double average = sum / data.Length;
    double averageOfSquares = sumOfSquares / data.Length;
    return Math.Sqrt(averageOfSquares - average * average);
}
static void Main(string[] args)
{
    double bigNumber = 1478340000000;
    double[] data = Enumerable.Repeat(bigNumber, 83283).ToArray();
    Console.WriteLine(standardDeviation(data));
}

程序输出一个由数字错误引起的巨大数字而不是零:2133383.0308878

请注意,如果我省略 Math.Sqrt(即我将计算方差而不是标准差),那么误差会高得多。

这是什么原因,我该如何写这个带有较小的数字错误?

【问题讨论】:

    标签: c# math statistics average numerical-methods


    【解决方案1】:

    我认为您将可能的最大/最小数(±5.0 × 10−324 到 ±1.7 × 10308)与双精度可用的有效数字数(15 - 16)混淆了。

    在您的情况下,我会说您通过不首先缩放输入来浪费数字,即将您的值转换为 1.47834,您的比例因子为 1 / 10^7数值计算。

    【讨论】:

    • 缩放与这里无关。无论如何,它是由 FP 表示完成的,可以分解或不分解。
    【解决方案2】:

    尽管您用于方差的公式在数学上是正确的——即,如果你有无限的精度——它可能会导致有限精度的问题。

    N 个数据 X 的更好方法是计算

    variance = Sum{ square( X[i] - mean) }/ N
    

    在哪里

    mean = Sum{ X[i] } /N
    

    正如所写,这需要两次遍历数据。如果这很尴尬,您实际上可以一次性完成。您需要保留三个变量,n(到目前为止看到的数据项数)均值和方差。这些都应该初始化为 0(又名 0.0)。那么当你得到下一个数据项x时:

    n = n + 1
    f = 1.0/n
    d = x-mean
    mean = mean + f*d
    variance = (1.0-f)*(variance + f*d*d)
    

    在处理一个数据项n后的每个阶段,均值、方差确实是数据到目前为止的计数、均值和方差。

    【讨论】:

    • 感谢您的出色回答。我特别喜欢你一次完成的方式。我明白这个意思是正确的。然而,方差的公式对我来说似乎是错误的。下面的公式呢? vaiance = (1.0-f)*variance + f*d*d*(1.0 + f) 这对我来说更有意义。
    • 我很确定我的公式是正确的。你的不能在第一个数据项之后,当 f=1 时,你的公式给出一个非零值 2*d*d 其中 d 是第一个数据值(因为平均值被初始化为 0)。但是 1 个事物的集合的方差是 0。
    • 你的反例是对的。你的公式也是。我用你的公式对程序进行了编码,它返回了预期值。因此,我将您的答案标记为已接受。但是我仍然不明白它为什么起作用。
    • 在我看来,使用这种方法仍然会遇到大整数的问题:第一次计算 d * d(“平均值”为零,所以你有 x * x)你可能会导致巨大的错误。稍后,如果平均值变化很大,这也会引起麻烦。应事先确定有效位数,并相应调整输入数据以确保您的结果可靠...
    • C. Gonzalez:第一次迭代的方差是 (1.0-f) * ... 等于 0,因为 f 是 1/1。
    猜你喜欢
    • 2015-05-20
    • 2017-04-27
    • 2018-08-31
    • 1970-01-01
    • 1970-01-01
    • 2015-05-29
    • 2021-03-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多