![](https://habrastorage.org/files/30b/26e/f8d/30b26ef8d5094390bd40d5bb624b7eba.png)
Для таких целей подойдет оценка медианы. То есть такая статистика, что половина значений выборки меньше, а половина больше. Более формально: упорядочим значения выборки
![](https://habrastorage.org/files/6e1/b19/216/6e1b192165d6484ea00d64a37810c325.png)
Для конкретной же выборки, мы всегда можем упорядочить данные и взять из них средний элемент, но беда заключается в том, что для этого нам нужны все значения выборки, при этом одноврЕмЕнно. В работе Munro, Patterson (1980) заявлена теорема, которая говорит, что ничего лучше придумать нельзя и можно расходиться.
![](https://habrastorage.org/files/d2b/f03/022/d2bf030222fc499fb6896f94f805da01.jpeg)
Но что же делать, если мы не можем позволить себе хранить сто тысяч миллионов значений. С одной стороны можно заняться задачей как отсортировать миллион int-ов в 2 мб оперативки. С другой, в упомянутой выше статье приводится простое решение, которое при некоторых допущениях с некоторой вероятностью приводит к правильному решению. А именно предлагается следующий алгоритм.
Метод Манро-Патерсона
Пусть имеется поток данных длины
Алгоритм очень прост: хранятся два счетчика
Так, что после тысячи случайных чисел при
![](https://habrastorage.org/files/cf0/b94/97d/cf0b9497d49b4d469abe3b320b34f034.png)
Если внимательно присмотреться к реализации, становится понятен смысл отсылки к “повезет, не повезет”. Медиана должна попасть в интервал значений хранимых в памяти. В статье приводятся оценки, что это будет происходить довольно часто, если
Данный алгоритм хорош как первое приближение, так как не очень понятно что же делать, если подсчет не удался и еще не понятно как его распараллеливать.
Дальнейшие исследования пошли в сторону приближенного вычисления медианы и идея приближения очень простая:
![](https://habrastorage.org/files/440/bb4/971/440bb497192e457eb1b1bf63b6c83c81.png)
Приближенный метод Канна-Гринвальда
Данный метод заимствует идею использования
Данные собираются в декартово дерево (которые замечательно описаны с цикле статей), которое при достижении придельного объема отфильтровывает значения, так чтобы сохранялась заявленная точность приближения, за счет создания агрегированных узлов.
Узлом дерева является тройка: значение исходной последовательности, количество сгруппированных данных, поколение появления этого значения в исходной выборке. Так же если мы говорим о декартовой дереве мы должны определить функцию ключа и приоритета: ключом является само значение, а приоритетом количество агрегированных данных в данном узле (с примесью небольшой случайности, чтобы узлы с одинаковым числом агрегированных значений распределялись более равномерно по поддеревьям).
Для такого дерева можно определить следующие важные операции:
- Добавление нового значения за
;
- Вычисления медианы и, как легко заметить, произвольного квантиля за линейное по
время;
- Объединение деревьев при одинаковом опять же за линейное по
время.
В статье приводится (без доказательства) теорема, о том что на случайном наборе данных количество узлов дерева будет расти пропорционально
Примеры
В качестве небольшого примера рассмотрим какое-нибудь симметричное и не симметричное распределения с известной медианой. Чтобы далеко не ходить, нормальное и лог-нормальное распределения нам должны подойти. Рассмотрим следующие оценки медианы для выборки в миллион значений:
- Упорядочивание значений
- Методом Манро-Патерсона, с параметром равным
- Методом Канна-Гринвальда c параметром
Все оценки для каждого из распределений делаются на одних наборах данных и повторяются 100 раз.
![](https://habrastorage.org/files/a0d/d81/44b/a0dd8144b8b54883a8491827bd4cd322.png)
В случае нормального распределения среднее и медиана совпадают, в случае лог-нормального распределения они достаточно сильно различаются и использовать одно для оценки другого не имеет смысла (А лучше, так никогда не делать). По парным картинкам видно, что метод полной сортировки очень часто дает совпадение результатов с методом Манро-Патерсона и это правильно, но все-таки есть достаточно много около 8%, как и утверждается в статье, случаев, когда результат Манро-Патерсона отличается от истинного. Метод Канна-Гринвальда дает не плохой, но все же приближенный результат. Ниже видно, что разброс всех методов от истинного значения приблизительно одинаков.
![](https://habrastorage.org/files/a9e/6b9/0f1/a9e6b90f1c7b4956951a7ea5a76fadff.png)
Метод Канна-Гринвальда должен быть достаточно экономичным как по памяти так и по скорости работы, а именно в дереве храниться число элементов пропорциональное логарифму длины входной последовательности и обратно пропорциональное ошибке
ПС
Примеры реализации можно найти по ссылке на bitbucket, но это не самая оптимальная реализация.
Уже подготавливая текст я обнаружил, что именно эти статьи и методы упоминаются в курсе алгоритмы обработки потоковых данных в ПОМИ.
Спасибо parpalak за редактор.
Комментарии (6)
vanxant
18.08.2015 22:39+1На практике часто случается, что наши данные есть поток каких-то показаний с датчика, причем разрядность датчика часто довольно небольшая (8, 16, 24, пусть даже 32 бита). В этом случае можно посчитать медиану поточно за счет памяти. Просто создаем массив счетчиков, сколько раз встретился 0, сколько 1 и т.д. до maxval, тупо counter[sample]++. По сути строим гистограмму, найти по которой медиану вообще не проблема. При этом гистограмма сама по себе очень полезна в плане статистики, посмотреть распределение, посчитать отклонения, всякие колмогоровы-смирновы, вот это все.
kokorins
18.08.2015 22:43+1В тексте есть ссылка на этот подход. И да, практически все пакеты предлагают именно гистограммный подход, например (раз уж я тут пишу на скале), он предлагается в mllib spark-а и breeze (scala backend) для spark. Тут я описываю метод, когда мы хотим обойтись минимальнымы предположениями о структуре входных данных, то есть мы не знаем min/max, не знаем разброс, да и вообще почти ничего не знаем. =)
dedZahar
19.08.2015 12:00+1Надо среднюю зарплату так считать
kokorins
19.08.2015 12:13Как раз с этого заметка и возникла. На одном радио был опрос сколько человек получают больше среднего, среди позвонивших было всего 15% таковых. Надеюсь из заметки стало понятнее почему постановка опроса не корректная.
SeptiM
Интересно, что Канн-Гринвальд детерминированный и всегда дает ответ с нужной погрешностью. Но он мне в свое время показался очень сложным, особенно в смысле понимания, почему работает.
-квантиля есть очень простое вероятностное решение через сэмплирование. Берем из всего набора случайно
элементов, сортируем. Теперь, если хотим посчитать
-квантиль, нужно просто вернуть
-ый элемент. С константной вероятностью ответ будет на расстоянии не более
от правильного. Если нужна вероятность ошибки
, берем соответсвенно
элементов.
У задачи поиска медианы и произвольного
Гарантия доказывается довольно просто через неравенство Чернова.
P.S. Предлагаю на подобные вещи ставить тэг data streaming.
kokorins
Надо было упомянуть сэмплирование, но очень хотелось описать алгоритм в котором N не известно заранее. В подходе с сэмплированием описание алгоритма перехода от N к N+1 c объяснением того, что «обновленная» выборка обладает всеми необходимыми свойствами занимает больше места.
Тег добавил.