У меня есть небольшая проблема, которая заставляет меня волноваться. Я должен написать процедуру для онлайн-процесса приобретения многомерного временного ряда. На каждом временном интервале (например, 1 секунда) я получаю новую выборку, которая в основном представляет собой вектор с плавающей запятой размера N. Операция, которую мне нужно сделать, немного сложнее:
Для каждого нового образца я вычисляю проценты для этого образца (нормализуя вектор так, чтобы элементы суммировались в 1).
Я рассчитываю средний процент вектора таким же образом, но с использованием прошлых значений.
Для каждого прошедшего значения я вычисляю абсолютное отклонение вектора процентов, относящегося к этой выборке, с вектором глобального среднего процента, вычисленным на шаге 2. Таким образом, абсолютное отклонение всегда равно 0 (когда вектор равен среднему вектор) и 2 (когда он полностью отличается).
Используя среднее значение отклонений для всех предыдущих выборок, я вычисляю среднее абсолютное отклонение, которое снова является числом от 0 до 2.
Я использую среднее абсолютное отклонение, чтобы определить, совместим ли новый образец с другими образцами (сравнивая его абсолютное отклонение со средним абсолютным отклонением всего набора, вычисленным на шаге 4).
Так как каждый раз, когда собирается новая выборка, глобальные средние изменения (и, следовательно, также изменяется и среднее абсолютное отклонение), есть ли способ вычислить это значение, не сканируя весь набор данных несколько раз? (один раз для вычисления средних глобальных процентов и один раз для сбора абсолютных отклонений). Хорошо, я знаю, что вычислить глобальные средние значения очень просто, не сканируя весь набор, поскольку мне просто нужно использовать временный вектор для хранения суммы каждого измерения, но как насчет среднего абсолютного отклонения? В его расчет входит abs()
оператор, поэтому мне нужен доступ ко всем прошлым данным!
Спасибо за вашу помощь.
источник
В прошлом я использовал следующий подход для умеренно эффективного вычисления отклонения отпущения грехов (обратите внимание, что это подход программистов, а не статистиков, так что, несомненно, могут быть хитрые уловки, такие как шаббыче, которые могут быть более эффективными).
ВНИМАНИЕ: Это не онлайн алгоритм. Это требует
O(n)
памяти. Кроме того, он имеет худшую производительностьO(n)
, например, для наборов данных[1, -2, 4, -8, 16, -32, ...]
(т. Е. Такой же, как и полный пересчет). [1]Тем не менее, поскольку он по-прежнему хорошо работает во многих случаях, его стоит опубликовать здесь. Например, чтобы рассчитать абсолютное отклонение 10000 случайных чисел от -100 до 100 при поступлении каждого элемента, мой алгоритм занимает менее одной секунды, в то время как полный пересчет занимает более 17 секунд (на моем компьютере будет зависеть от машины и согласно входным данным). Однако вам необходимо сохранить весь вектор в памяти, что может быть ограничением для некоторых применений. Схема алгоритма следующая:
O(n)
операций перемещения, для многих случаев это не так.Пример кода на Python приведен ниже. Обратите внимание, что он позволяет только элементы, которые будут добавлены в список, но не удалены. Это можно легко добавить, но в то время, когда я писал это, мне это не нужно. Вместо того, чтобы реализовывать очереди приоритетов самостоятельно, я использовал отсортированный список из превосходного пакета blist Даниэля Штутцбаха , который использует B + Tree для внутреннего использования.
Рассмотрим этот код под лицензией MIT . Он не был значительно оптимизирован или отшлифован, но работал для меня в прошлом. Новые версии будут доступны здесь . Дайте мне знать, если у вас есть какие-либо вопросы, или найдите какие-либо ошибки.
[1] Если симптомы не проходят, обратитесь к врачу.
источник
O(n)
памяти, и в худшем случае занимает O (n) время для каждого добавленного элемента. В нормально распределенных данных (и, возможно, в других дистрибутивах) это работает довольно эффективно.Существует также параметрический подход. Игнорируя векторную природу ваших данных и рассматривая только маргиналы, достаточно решить проблему: найти онлайновый алгоритм для вычисления среднего абсолютного отклонения скаляраИкс , Если (и это большое «если» здесь) вы думали, чтоИкс Следуя некоторому распределению вероятности с неизвестными параметрами, вы можете оценить параметры, используя некоторый онлайн-алгоритм, а затем вычислить среднее абсолютное отклонение на основе этого параметризованного распределения. Например, если вы думали, чтоИкс было (приблизительно) нормально распределено, вы можете оценить его стандартное отклонение, как s и среднее абсолютное отклонение будет оцениваться как с 2 / π---√ (см. Половинное нормальное распределение ).
источник
MAD (x) - это всего лишь два одновременных вычисления медианы, каждое из которых может быть выполнено в режиме онлайн с помощью binmedian алгоритма .
Вы можете найти соответствующую статью, а также код C и FORTRAN онлайн здесь .
(это всего лишь использование хитрого трюка поверх хитрого трюка Шаббишефа, чтобы сэкономить память).
Приложение:
Существует множество старых многопроходных методов для вычисления квантилей. Популярный подход заключается в поддержании / обновлении детерминированного размера резервуара наблюдений, случайно выбранных из потока, и рекурсивного вычисления квантилей (см. Этот обзор) для этого резервуара. Этот (и связанный) подход заменен предложенным выше.
источник
Нижеследующее обеспечивает неточное приближение, хотя неточность будет зависеть от распределения входных данных. Это онлайн-алгоритм, но он только приближает абсолютное отклонение. Он основан на хорошо известном алгоритме для расчета дисперсии онлайн, описанном Уэлфордом в 1960-х годах. Его алгоритм, переведенный в R, выглядит так:
Он работает очень похоже на встроенную функцию дисперсии R:
Модификация алгоритма для вычисления абсолютного отклонения просто включает дополнительный
sqrt
вызов. Тем не менее,sqrt
вводит неточности, которые отражаются в результате:Ошибки, рассчитанные, как указано выше, намного больше, чем для расчета дисперсии:
Однако, в зависимости от вашего варианта использования, эта величина ошибки может быть приемлемой.
источник
n
становится большим, тоerror/n
становится невероятно маленьким, на удивление быстро.sqrt
неточности. Это потому, что он использует оценку среднего значения. Чтобы увидеть, когда это сломается, попробуйтеxs <- sort(rnorm(n.testitems))
Когда я попробую это с вашим кодом (после исправления его возвратаa.dev / n
), я получу относительные ошибки порядка 9% -16%. Так что этот метод не является инвариантом перестановки, что может привести к хаосу ...