Python 断言错误:平方偏差的负和

Python 断言错误:平方偏差的负和,python,python-3.x,dictionary,statistics,standard-deviation,Python,Python 3.x,Dictionary,Statistics,Standard Deviation,作为一个更大项目的一部分,我正在编写一个函数,该函数接收整数的dict,并返回一个dict,其中每个“外部”键都链接到该子字典的平均值和标准偏差的元组(即(mean(dict[key1]),stdev(dict[key1]))。我在一个大数据集上操作(源文件是一个2.8 GB的csv文件),在计算其中一个子目录的标准偏差时,我得到了一个断言错误 虽然我将(目前正在)追踪导致以下错误的子目录,但我很好奇一般情况会导致什么样的错误,因此,如果错误发生在我的数据集中,我可以尝试避免它 我收到的错误消息

作为一个更大项目的一部分,我正在编写一个函数,该函数接收整数的dict,并返回一个dict,其中每个“外部”键都链接到该子字典的平均值和标准偏差的元组(即
(mean(dict[key1]),stdev(dict[key1])
)。我在一个大数据集上操作(源文件是一个2.8 GB的csv文件),在计算其中一个子目录的标准偏差时,我得到了一个断言错误

虽然我将(目前正在)追踪导致以下错误的子目录,但我很好奇一般情况会导致什么样的错误,因此,如果错误发生在我的数据集中,我可以尝试避免它

我收到的错误消息是:

AssertionError:负平方差和:-3734262324235.697754

从代码中:

import statistics as stat

try: #Check for single value error
    std = stat.stdev(val)
except stat.StatisticsError:
    std = 0

statiscs.py
中的代码是纯Python代码-在处理内部“平方和”)统计数据时,您似乎是分数类中一个奇怪溢出错误的受害者

我认为您现在可以做的最好的事情是在
statistics.py
文件中使用
\u ss
函数本身,并使用“if”和调用
pdb.set_trace
以交互方式查找导致错误的数据(代码中有一条注释,说明此部分存在舍入错误)。它计算一个应该为零的分数-但是为了舍入误差,并对该分数进行平方。但是平方后,已经很大的分母本身就是平方的-这可能会触发Python分数中的错误,并在它应该接近零时返回一个非常大的值


这样一个“if”子句可以允许您(1)绕过错误条件并将代码运行到底,在发现错误时强制将值设置为零;(2)记下导致错误的值,并将其作为错误报告给Python语言本身。

statiscs.py中的代码是纯Python的-在处理内部“平方和”统计信息时,您似乎是分数类中奇怪溢出错误的受害者。\u ss函数

我认为您现在可以做的最好的事情是在
statistics.py
文件中使用
\u ss
函数,并使用“if”和调用
pdb.set_trace
以交互方式查找导致错误的数据(代码中有一条注释,说明此部分存在舍入错误)。它计算一个应该为零的分数,但要计算舍入误差,然后将该分数平方。但是在平方时,已经很大的分母本身就是平方的——这可能会触发Python分数中的一个bug,并在它应该接近零时返回一个非常大的值


这样一个“if”子句可以允许您(1)绕过错误条件并将代码运行到底,在发现错误时强制将值设置为零;(2) 记下导致错误的值,并将其作为错误报告给Python语言本身。

这是@jsbueno提到的
statistics.py
文件的问题。我也有同样的错误,并通过将
statistics.stdev
替换为
numpy.std
而不是更改源代码来解决它。

这是@jsbueno提到的
statistics.py
文件的问题。我也有同样的错误,并通过将
statistics.stdev
替换为
numpy.std
而不是对源代码进行更改来解决它。

我在非常小的数字上遇到了同样的问题。求和(x²)的精确计算结果为零(分数(0,1)),但求和(x)的精确计算结果为非常小的正分数,表示舍入误差和从数据中减去平均值时的精度损失

py中的代码表明total2应该为零,但它实际上可以是任何小数字,正数或负数。total2的平方总是一个小的正分数

def _ss(data, c=None):
    """Return sum of square deviations of sequence data.

    If ``c`` is None, the mean is calculated in one pass, and the deviations
    from the mean are calculated in a second pass. Otherwise, deviations are
    calculated from ``c`` as given. Use the second case with care, as it can
    lead to garbage results.
    """
    if c is None:
        c = mean(data)
    T, total, count = _sum((x-c)**2 for x in data)
    # The following sum should mathematically equal zero, but due to rounding
    # error may not.
    U, total2, count2 = _sum((x-c) for x in data)
    assert T == U and count == count2
    total -=  total2**2/len(data)
    assert not total < 0, 'negative sum of square deviations: %f' % total
    return (T, total)
def_ss(数据,c=None):
“”“返回序列数据的平方偏差之和。”。
如果``c``为无,则一次计算平均值,并计算偏差
第二遍计算平均值的偏差。否则,偏差为
根据给定的“c”计算。请谨慎使用第二个案例
导致垃圾结果。
"""
如果c为无:
c=平均值(数据)
T、 总计,计数=_和((x-c)**2表示数据中的x)
#以下总和在数学上应等于零,但由于四舍五入
#错误可能不会发生。
U、 total2,count2=_sum((x-c)表示数据中的x)
断言T==U和count==count2
总计-=总计2**2/列(数据)
断言不总计<0,'平方差的负和:%f'%total
返回(T,总计)
因此,总方差可以在断言失败之前变为负值

根本原因是在第一次_sum函数调用中对每个值进行平方运算时发生的精度损失。浮点或np.float64值在列表中通过浮点运算进行平方

一种可能的纠正方法是在对total2进行平方运算之前将其转换为T型。它改变了语义,因为_ss返回类型为T的值,而不是精确的分数。另一种更准确的方法是,在第一次调用_sum之前,将x-c一次性转换成分数。在这两种情况下,计算速度也会更快


最合适的更正并非微不足道,因为_sum还聚合了从连续调用到_强制的类型。早期将数据转换为分数也会将结果类型更改为分数

我在非常小的数字上遇到了同样的问题。求和(x²)的精确计算结果为零(分数(0,1)),但求和(x)的精确计算结果为非常小的正分数,表示舍入误差