Алгоритмы расчета дисперсии - Algorithms for calculating variance

Алгоритмы расчета дисперсии играть важную роль в вычислительная статистика. Ключевая трудность в дизайне хорошего алгоритмы для этой проблемы состоит в том, что формулы для отклонение может включать суммы квадратов, что может привести к числовая нестабильность а также арифметическое переполнение при работе с большими значениями.

Наивный алгоритм

Формула для расчета дисперсии всего численность населения размера N является:

С помощью Поправка Бесселя рассчитать беспристрастный оценка дисперсии совокупности от конечного образец из п наблюдений формула:

Следовательно, наивный алгоритм вычисления предполагаемой дисперсии имеет следующий вид:

  • Позволять п ← 0, Сумма ← 0, SumSq ← 0
  • Для каждой базы данных Икс:
    • пп + 1
    • Сумма ← Сумма + Икс
    • SumSq ← SumSq + Икс × Икс
  • Var = (SumSq - (Сумма × Сумма) / n) / (n - 1)

Этот алгоритм можно легко адаптировать для вычисления дисперсии конечной совокупности: просто разделите на N вместо п - 1 в последней строке.

Потому что SumSq и (Сумма × Сумма) /п могут быть очень похожие числа, отмена может привести к точность результата будет намного меньше, чем присущая точность арифметика с плавающей запятой используется для выполнения вычислений. Таким образом, этот алгоритм не следует использовать на практике,[1][2] и было предложено несколько альтернативных, численно устойчивых алгоритмов.[3] Это особенно плохо, если стандартное отклонение мало по сравнению со средним значением. Однако алгоритм можно улучшить, приняв метод предполагаемое среднее.

Вычисление смещенных данных

Разница составляет инвариантный относительно изменений в параметр местоположения, свойство, которое можно использовать, чтобы избежать катастрофической отмены в этой формуле.

с любая константа, которая приводит к новой формуле

чем ближе соответствует среднему значению, тем точнее будет результат, но простой выбор значения в пределах диапазона выборки гарантирует желаемую стабильность. Если значения малы, то нет проблем с суммой его квадратов, наоборот, если они большие, это обязательно означает, что и дисперсия велика. В любом случае второй член в формуле всегда меньше первого, поэтому отмены не происходит.[2]

Если в качестве алгоритм можно записать на Язык программирования Python в качестве

def shift_data_variance(данные):    если len(данные) < 2:        возвращаться 0.0    K = данные[0]    п = Бывший = Ex2 = 0.0    за Икс в данные:        п = п + 1        Бывший += Икс - K        Ex2 += (Икс - K) * (Икс - K)    отклонение = (Ex2 - (Бывший * Бывший) / п) / (п - 1)    # используйте n вместо (n-1), если хотите вычислить точную дисперсию заданных данных    # используйте (n-1), если данные являются выборками для большей совокупности    возвращаться отклонение

Эта формула также облегчает инкрементные вычисления, которые можно выразить как

K = п = Бывший = Ex2 = 0.0def add_variable(Икс):    Глобальный K, п, Бывший, Ex2    если п == 0:        K = Икс    п += 1    Бывший += Икс - K    Ex2 += (Икс - K) * (Икс - K)def remove_variable(Икс):    Глобальный K, п, Бывший, Ex2    п -= 1    Бывший -= Икс - K    Ex2 -= (Икс - K) * (Икс - K)def get_mean():    Глобальный K, п, Бывший    возвращаться K + Бывший / пdef get_variance():    Глобальный п, Бывший, Ex2    возвращаться (Ex2 - (Бывший * Бывший) / п) / (п - 1)

Двухпроходный алгоритм

Альтернативный подход, использующий другую формулу для дисперсии, сначала вычисляет выборочное среднее,

а затем вычисляет сумму квадратов отличий от среднего,

куда s стандартное отклонение. Это дается следующим кодом:

def two_pass_variance(данные):    п = сумма1 = сумма2 = 0    за Икс в данные:        п += 1        сумма1 += Икс    иметь в виду = сумма1 / п    за Икс в данные:        сумма2 += (Икс - иметь в виду) * (Икс - иметь в виду)    отклонение = сумма2 / (п - 1)    возвращаться отклонение

Этот алгоритм численно устойчив, если п маленький.[1][4] Однако результаты обоих этих простых алгоритмов («наивный» и «двухпроходный») могут чрезмерно зависеть от порядка данных и могут давать плохие результаты для очень больших наборов данных из-за повторяющейся ошибки округления при накоплении суммы. Такие методы, как компенсированное суммирование может быть использован для борьбы с этой ошибкой в ​​определенной степени.

Онлайн алгоритм Велфорда

Часто бывает полезно вычислить дисперсию за один проход, проверяя каждое значение. только однажды; например, когда данные собираются без достаточного объема памяти для хранения всех значений или когда затраты на доступ к памяти преобладают над затратами на вычисления. Для такого онлайн алгоритм, а отношение повторения требуется между величинами, из которых можно рассчитать требуемую статистику численно стабильным образом.

Следующие формулы можно использовать для обновления иметь в виду и (оценочная) дисперсия последовательности для дополнительного элемента Иксп. Здесь, Иксп обозначает выборочное среднее первого п образцы (Икс1, ..., Иксп), s2
п
их выборочная дисперсия, и σ2
п
их дисперсия населения.

Эти формулы страдают числовой нестабильностью, поскольку они многократно вычитают небольшое число из большого числа, которое масштабируется с п. Лучшее количество для обновления - это сумма квадратов отличий от текущего среднего, , здесь обозначено :

Этот алгоритм был найден Велфордом,[5][6] и это было тщательно проанализировано.[2][7] Также принято обозначать и .[8]

Ниже приведен пример реализации алгоритма Велфорда на Python.

# Для нового значения newValue вычислить новый счетчик, новое среднее значение, новое значение M2.# mean накапливает среднее значение всего набора данных# M2 суммирует квадрат расстояния от среднего# count объединяет количество просмотренных образцовdef Обновить(existingAggregate, newValue):    (считать, иметь в виду, M2) = existingAggregate    считать += 1    дельта = newValue - иметь в виду    иметь в виду += дельта / считать    дельта2 = newValue - иметь в виду    M2 += дельта * дельта2    возвращаться (считать, иметь в виду, M2)# Получить среднее значение, дисперсию и дисперсию выборки из агрегатаdef завершить(existingAggregate):    (считать, иметь в виду, M2) = existingAggregate    если считать < 2:        возвращаться плавать("нан")    еще:        (иметь в виду, отклонение, выборочная дисперсия) = (иметь в виду, M2 / считать, M2 / (считать - 1))        возвращаться (иметь в виду, отклонение, выборочная дисперсия)

Этот алгоритм гораздо менее подвержен потере точности из-за катастрофическая отмена, но может быть не таким эффективным из-за операции деления внутри цикла. Для особенно надежного двухпроходного алгоритма вычисления дисперсии можно сначала вычислить и вычесть оценку среднего, а затем использовать этот алгоритм для остатков.

В параллельный алгоритм ниже показано, как объединить несколько наборов статистических данных, рассчитанных в режиме онлайн.

Взвешенный инкрементальный алгоритм

Алгоритм может быть расширен для обработки неравных весов выборок, заменив простой счетчик п с суммой видимых весов. Запад (1979)[9] предлагает это инкрементальный алгоритм:

def weighted_incremental_variance(data_weight_pairs):    w_sum = w_sum2 = иметь в виду = S = 0    за Икс, ш в data_weight_pairs:  # В качестве альтернативы "для x, w в zip (данные, веса):"        w_sum = w_sum + ш        w_sum2 = w_sum2 + ш * ш        mean_old = иметь в виду        иметь в виду = mean_old + (ш / w_sum) * (Икс - mean_old)        S = S + ш * (Икс - mean_old) * (Икс - иметь в виду)    Population_variance = S / w_sum    # Поправка Бесселя для взвешенных выборок    # Частотные веса    sample_frequency_variance = S / (w_sum - 1)    # Веса надежности    sample_reliability_variance = S / (w_sum - w_sum2 / w_sum)

Параллельный алгоритм

Чан и др.[10] обратите внимание, что онлайн-алгоритм Велфорда, описанный выше, является частным случаем алгоритма, который работает для объединения произвольных наборов и :

.

Это может быть полезно, когда, например, несколько блоков обработки могут быть назначены дискретным частям ввода.

Метод Чана для оценки среднего численно неустойчив, когда и оба они велики, потому что числовая ошибка в не уменьшается так, как в дело. В таких случаях предпочитайте .

def parallel_variance(н_а, avg_a, M2_a, н_б, avg_b, M2_b):    п = н_а + н_б    дельта = avg_b - avg_a    M2 = M2_a + M2_b + дельта ** 2 * н_а * н_б / п    var_ab = M2 / (п - 1)    возвращаться var_ab

Это можно обобщить, чтобы разрешить распараллеливание с AVX, с GPU, и компьютерные кластеры, и ковариантности.[3]

Пример

Предположим, что все операции с плавающей запятой используют стандартные IEEE 754 с двойной точностью арифметика. Рассмотрим выборку (4, 7, 13, 16) из бесконечной совокупности. На основе этой выборки оценочное среднее значение совокупности составляет 10, а несмещенная оценка дисперсии совокупности - 30. И наивный алгоритм, и двухпроходный алгоритм вычисляют эти значения правильно.

Далее рассмотрим образец (108 + 4, 108 + 7, 108 + 13, 108 + 16), что приводит к той же оценке дисперсии, что и в первом примере. Двухпроходный алгоритм правильно вычисляет эту оценку дисперсии, но наивный алгоритм возвращает 29,333333333333332 вместо 30.

Хотя эта потеря точности может быть терпимой и рассматриваться как незначительный недостаток наивного алгоритма, дальнейшее увеличение смещения делает ошибку катастрофической. Рассмотрим образец (109 + 4, 109 + 7, 109 + 13, 109 + 16). Опять же, оценочная дисперсия совокупности, равная 30, правильно вычисляется двухпроходным алгоритмом, но теперь простой алгоритм вычисляет ее как -170,66666666666666. Это серьезная проблема с наивным алгоритмом и связана с катастрофическая отмена при вычитании двух одинаковых чисел на заключительном этапе алгоритма.

Статистика высшего порядка

Terriberry[11] расширяет формулы Чана на вычисление третьего и четвертого центральные моменты, например, при оценке перекос и эксцесс:

Здесь снова суммы степеней отличий от среднего , давая

Для инкрементального случая (т. Е. ), это упрощает:

Сохраняя ценность , требуется только одна операция деления, и, таким образом, можно рассчитать статистику более высокого порядка с небольшими дополнительными затратами.

Пример онлайн-алгоритма эксцесса, реализованного, как описано, это:

def online_kurtosis(данные):    п = иметь в виду = M2 = M3 = M4 = 0    за Икс в данные:        n1 = п        п = п + 1        дельта = Икс - иметь в виду        delta_n = дельта / п        delta_n2 = delta_n * delta_n        термин1 = дельта * delta_n * n1        иметь в виду = иметь в виду + delta_n        M4 = M4 + термин1 * delta_n2 * (п*п - 3*п + 3) + 6 * delta_n2 * M2 - 4 * delta_n * M3        M3 = M3 + термин1 * delta_n * (п - 2) - 3 * delta_n * M2        M2 = M2 + термин1    # Обратите внимание: вы также можете рассчитать дисперсию, используя M2, и асимметрию, используя M3    эксцесс = (п * M4) / (M2 * M2) - 3    возвращаться эксцесс

Пеба́[12]далее расширяет эти результаты до произвольного порядка центральные моменты, для инкрементального и попарного случаев, а впоследствии Пеба и др.[13]для взвешенных и составных моментов. Там же можно найти аналогичные формулы для ковариация.

Чой и Свитмен[14]предлагают два альтернативных метода вычисления асимметрии и эксцесса, каждый из которых может существенно сэкономить требования к памяти компьютера и процессорного времени в определенных приложениях. Первый подход заключается в вычислении статистических моментов путем разделения данных на ячейки и последующего вычисления моментов из геометрии полученной гистограммы, которая фактически становится однопроходный алгоритм для более высоких моментов. Одно из преимуществ состоит в том, что вычисления статистического момента могут выполняться с произвольной точностью, так что вычисления могут быть настроены с точностью, например, до формата хранения данных или исходного измерительного оборудования. Относительная гистограмма случайной величины может быть построена обычным способом: диапазон потенциальных значений делится на интервалы, а количество вхождений в каждом интервале подсчитывается и строится таким образом, чтобы площадь каждого прямоугольника равнялась части значений выборки в пределах эта корзина:

куда и представляют частоту и относительную частоту в ячейке и - общая площадь гистограммы. После этой нормализации сырые моменты и центральные моменты можно рассчитать по относительной гистограмме:

где верхний индекс указывает, что моменты рассчитываются по гистограмме. Для постоянной ширины бункера эти два выражения можно упростить, используя :

Второй подход Чоя и Свитмена[14] представляет собой аналитическую методологию для объединения статистических моментов из отдельных сегментов истории времени так, чтобы результирующие общие моменты были моментами полной истории времени. Эта методология может использоваться для параллельного вычисления статистических моментов с последующей комбинацией этих моментов или для комбинации статистических моментов, вычисляемых в последовательные моменты времени.

Если известны наборы статистических моментов: за , то каждый можно выразить через эквивалент сырые моменты:

куда обычно принимается за продолжительность история времени, или количество баллов, если постоянно.

Преимущество выражения статистических моментов в терминах это то наборы могут быть объединены путем сложения, и нет верхнего предела значения .

где нижний индекс представляет собой объединенную временную историю или комбинированную . Эти комбинированные значения затем могут быть обратно преобразованы в необработанные моменты, представляющие полную объединенную временную историю

Известные отношения между необработанными моментами () и центральные моменты () затем используются для вычисления центральных моментов объединенной истории времени. Наконец, статистические моменты объединенной истории вычисляются из центральных моментов:

Ковариация

Очень похожие алгоритмы можно использовать для вычисления ковариация.

Наивный алгоритм

Наивный алгоритм:

Для приведенного выше алгоритма можно использовать следующий код Python:

def наивная ковариация(data1, данные2):    п = len(data1)    сумма12 = 0    сумма1 = сумма(data1)    сумма2 = сумма(данные2)    за i1, i2 в застегивать(data1, данные2):        сумма12 += i1 * i2    ковариация = (сумма12 - сумма1 * сумма2 / п) / п    возвращаться ковариация

С оценкой среднего

Что касается дисперсии, ковариация двух случайных величин также инвариантна относительно сдвига, поэтому при любых двух постоянных значениях и это можно написать:

и снова выбор значения внутри диапазона значений стабилизирует формулу против катастрофического отказа, а также сделает ее более устойчивой к большим суммам. Принимая первое значение каждого набора данных, алгоритм можно записать как:

def shift_data_covariance(data_x, data_y):    п = len(data_x)    если п < 2:        возвращаться 0    kx = data_x[0]    ты = data_y[0]    Бывший = Эй = Exy = 0    за ix, иу в застегивать(data_x, data_y):        Бывший += ix - kx        Эй += иу - ты        Exy += (ix - kx) * (иу - ты)    возвращаться (Exy - Бывший * Эй / п) / п

Двухходовой

Двухпроходный алгоритм сначала вычисляет выборочные средние, а затем ковариацию:

Двухпроходный алгоритм можно записать как:

def two_pass_covariance(data1, данные2):    п = len(data1)    среднее1 = сумма(data1) / п    среднее2 = сумма(данные2) / п    ковариация = 0    за i1, i2 в застегивать(data1, данные2):        а = i1 - среднее1        б = i2 - среднее2        ковариация += а * б / п    возвращаться ковариация

Немного более точная версия с компенсацией выполняет полный наивный алгоритм для остатков. Окончательные суммы и должен быть нулевым, но второй проход компенсирует любую небольшую ошибку.

В сети

Существует стабильный однопроходный алгоритм, похожий на онлайн-алгоритм для вычисления дисперсии, который вычисляет совместный момент :

Кажущаяся асимметрия в этом последнем уравнении связана с тем, что , поэтому оба условия обновления равны . Еще большей точности можно достичь, сначала вычислив средние, а затем используя устойчивый однопроходный алгоритм для остатков.

Таким образом, ковариацию можно вычислить как

def online_covariance(data1, данные2):    среднее значение = много = C = п = 0    за Икс, у в застегивать(data1, данные2):        п += 1        dx = Икс - среднее значение        среднее значение += dx / п        много += (у - много) / п        C += dx * (у - много)    Population_covar = C / п    # Поправка Бесселя на дисперсию выборки    sample_covar = C / (п - 1)

Небольшая модификация также может быть сделана для вычисления взвешенной ковариации:

def online_weighted_covariance(data1, данные2, data3):    среднее значение = много = 0    wsum = wsum2 = 0    C = 0    за Икс, у, ш в застегивать(data1, данные2, data3):        wsum += ш        wsum2 += ш * ш        dx = Икс - среднее значение        среднее значение += (ш / wsum) * dx        много += (ш / wsum) * (у - много)        C += ш * dx * (у - много)    Population_covar = C / wsum    # Поправка Бесселя на дисперсию выборки    # Частотные веса    sample_frequency_covar = C / (wsum - 1)    # Веса надежности    sample_reliability_covar = C / (wsum - wsum2 / wsum)

Точно так же есть формула для объединения ковариаций двух наборов, которую можно использовать для распараллеливания вычислений:[3]

Пакетная взвешенная версия

Также существует версия взвешенного онлайн-алгоритма с пакетным обновлением: пусть обозначим веса и напишем

Затем ковариацию можно вычислить как

Смотрите также

Рекомендации

  1. ^ а б Эйнарссон, Бо (2005). Точность и надежность научных вычислений. СИАМ. п. 47. ISBN  978-0-89871-584-2.
  2. ^ а б c Чан, Тони Ф.; Голуб, Джин Х.; Левек, Рэндалл Дж. (1983). «Алгоритмы вычисления дисперсии выборки: анализ и рекомендации» (PDF). Американский статистик. 37 (3): 242–247. Дои:10.1080/00031305.1983.10483115. JSTOR  2683386.
  3. ^ а б c Шуберт, Эрих; Герц, Майкл (9 июля 2018 г.). Численно стабильное параллельное вычисление (ко) дисперсии. ACM. п. 10. Дои:10.1145/3221269.3223036. ISBN  9781450365055. S2CID  49665540.
  4. ^ Хайэм, Николас (2002). Точность и устойчивость численных алгоритмов (2-е изд.) (Задача 1.10). СИАМ.
  5. ^ Велфорд, Б. П. (1962). «Примечание о методе расчета скорректированных сумм квадратов и произведений». Технометрика. 4 (3): 419–420. Дои:10.2307/1266577. JSTOR  1266577.
  6. ^ Дональд Э. Кнут (1998). Искусство программирования, том 2: Получисловые алгоритмы, 3-е изд., С. 232. Бостон: Аддисон-Уэсли.
  7. ^ Линг, Роберт Ф. (1974). «Сравнение нескольких алгоритмов для вычисления выборочных средних и вариантов». Журнал Американской статистической ассоциации. 69 (348): 859–866. Дои:10.2307/2286154. JSTOR  2286154.
  8. ^ http://www.johndcook.com/standard_deviation.html
  9. ^ Уэст, Д. Х. Д. (1979). «Обновление оценок среднего и дисперсии: усовершенствованный метод». Коммуникации ACM. 22 (9): 532–535. Дои:10.1145/359146.359153. S2CID  30671293.
  10. ^ Чан, Тони Ф.; Голуб, Джин Х.; Левек, Рэндалл Дж. (1979), «Обновление формул и парный алгоритм вычисления выборочных вариантов». (PDF), Технический отчет STAN-CS-79-773, Факультет компьютерных наук Стэнфордского университета.
  11. ^ Террибери, Тимоти Б. (2007), Вычисление моментов высшего порядка в Интернете, заархивировано из оригинал 23 апреля 2014 г., получено 5 мая 2008
  12. ^ Пеба, Филипп (2008), "Формулы для надежного однопроходного параллельного вычисления ковариаций и статистических моментов произвольного порядка" (PDF), Технический отчет SAND2008-6212, Сандианские национальные лаборатории
  13. ^ Пебах, Филипп; Террибери, Тимоти; Колла, Хемант; Беннетт, Джанин (2016), «Численно стабильные, масштабируемые формулы для параллельного и оперативного вычисления многомерных центральных моментов высокого порядка с произвольными весами», Вычислительная статистика, Спрингер, 31 (4): 1305–1325, Дои:10.1007 / s00180-015-0637-z, S2CID  124570169
  14. ^ а б Чой, Мёнкын; Свитман, Берт (2010), «Эффективный расчет статистических моментов для структурного мониторинга здоровья», Журнал структурного мониторинга здоровья, 9 (1): 13–24, Дои:10.1177/1475921709341014, S2CID  17534100

внешняя ссылка