Я хочу использовать метод Уэлфорда для вычисления текущей дисперсии и среднего значения. Я наткнулся на эту реализацию метода Уэлфорда на Python. Однако при тестировании, чтобы перепроверить, что он дает тот же результат, что и стандартная реализация Numpy для расчета дисперсии, я обнаружил, что есть разница в выводе.
Выполнение следующего кода (с использованием unittest модуля Python) показывает, что они дают разные результаты (даже после многократного тестирования):
random_sample = np.random.normal(0, 1, 100)
std = np.var(random_sample, dtype=np.longdouble)
mean = np.mean(random_sample, dtype=np.longdouble)
welford = Welford()
welford.add_all(random_sample)
self.assertAlmostEqual(mean, welford.mean)
self.assertAlmostEqual(var, welford.var_s)
>> AssertionError: 1.1782075496578717837 != 1.1901086360180526 within 7 places (0.011901086360180828804 difference)
Интересно, что существует только разница в дисперсии, а не в среднем.
Для моих целей разница в 0,012 достаточно значительна, чтобы повлиять на мои результаты.
Почему может быть такая разница? Может ли это быть связано с ошибками с плавающей запятой? Если да, то лучше всего было бы переписать пакет, чтобы использовать класс Decimal
?
По умолчанию np.var вычисляет так называемую «дисперсию совокупности», в которой количество степеней свободы равно количеству элементов в массиве.
wellford.var_s
— выборочная дисперсия, в которой количество степеней свободы равно количеству элементов в массиве минус один.
Чтобы устранить несоответствие, передайте ddof=1
на np.var
:
import numpy as np
from welford import Welford
random_sample = np.random.normal(0, 1, 100)
var = np.var(random_sample, dtype=np.longdouble, ddof=1)
welford = Welford()
welford.add_all(random_sample)
np.testing.assert_allclose(var, welford.var_s)
В качестве альтернативы, если в вашем приложении уместно использовать дисперсию генеральной совокупности, используйте welford.var_p
.
var = np.var(random_sample, dtype=np.longdouble)
np.testing.assert_allclose(var, welford.var_p)
Описание разницы между ними см. в разрабатываемой версии документации np.var .