Алгоритм P2 - приємна знахідка. Це працює, роблячи кілька оцінок квантила, періодично оновлюючи їх, і використовуючи квадратичну (не лінійну, не кубічну) інтерполяцію для оцінки квантиля. Автори стверджують, що квадратична інтерполяція працює краще в хвостах, ніж лінійна інтерполяція, і кубічна буде надто метушливою і складною.
Ви не констатуєте, як саме цей підхід не підходить для ваших "важкохвостих" даних, але легко здогадатися: оцінки екстремальних квантилів для важкохвостих розподілів будуть нестабільними, поки не буде зібрано велику кількість даних. Але це буде проблемою (в меншій мірі) навіть якщо ви зберігали б усі дані, тому не чекайте чудес!
У будь-якому випадку, чому б не встановити допоміжні маркери - давайте назвемо їх і x 6 - за якими ви впевнені, що квантил буде лежати, і зберігати всі дані, що лежать між x 0 і x 6 ? Коли ваш буфер заповнюється, вам доведеться оновлювати ці маркери, завжди зберігаючи x 0 ≤ x 6 . Простий алгоритм зробити це можна з комбінації (a) поточної оцінки P2 кількісного числа і (b) збережених підрахунків кількості даних менше x 0 та кількості даних, що перевищує x 6x0x6x0x6x0≤x6x0x6. Таким чином, ви можете з високою визначеністю оцінити кількісний показник так само добре, як якщо б у вас був весь доступний набір даних завжди, але вам потрібен лише порівняно невеликий буфер.
Зокрема, я пропоную структуру даних для підтримки часткової інформації про послідовність n значень даних x 1 , x 2 , … , x n . Тут y - пов'язаний список(k,y,n)nx1,x2,…,xny
y=(x(n)[k+1]≤x(n)[k+2]≤⋯≤x(n)[k+m]).
У цьому позначенні позначає i- е найменше з прочитаних досі значень n x . m - постійна, розмір буфера y .x(n)[i]ithn xmy
Алгоритм починається з заповнення першими зібраними значеннями m і розміщення їх у відсортованому порядку, найменший до найбільший. Нехай q - квантил, який слід оцінити; наприклад, q = 0,99. Після читання x n + 1 можливі три дії:ymqqxn+1
Якщо , приріст k .xn+1<x(n)[k+1]k
Якщо , нічого не робіть.xn+1>x(n)[k+m]
В іншому випадку вставте в y .xn+1y
У будь-якому випадку приріст .n
У вставках процедура ставить в у в відсортованому порядку , і потім усуває одне зі значень крайніх в у :xn+1yy
Якщо , то видаліть x ( n ) [ k + 1 ] з y та приріст k ;k+m/2<nqx(n)[k+1]yk
В іншому випадку видаліть з y .x(n)[k+m]y
За умови, що достатньо велика, ця процедура з високою ймовірністю скопить справжній квантил розподілу. На будь-якому етапі n його можна оцінити звичайним способом через x ( n ) [ ⌊ q n ⌋ ] і x ( n ) [ ⌈ q n ⌉ ] , що, ймовірно, лежить в y . (Я вважаю, що m має масштабувати лише як квадратний корінь максимальної кількості даних ( Nmnx(n)[⌊qn⌋]x(n)[⌈qn⌉]ymN), але я не провів жорсткого аналізу, щоб довести це.) У будь-якому випадку алгоритм виявить, чи вдався він (порівнявши та ( k + m ) / n до q ).k/n(k+m)/nq
Тестування зі значенням до 100 000, використовуючи іq=.5(найскладніший випадок) вказує, що цей алгоритм має 99,5% успішності в отриманні правильного значення x ( n ) [ ⌊ q n ⌋ ] . Для потоку зN=10 12 значень, що потребував би буфера усього два мільйони (але кращий вибір - три чи чотири мільйони). Для використання відсортованого подвійно пов'язаного списку для буфера потрібноO(log( √)m=2N−−√q=.5x(n)[⌊qn⌋]N=1012=O(log(N))зусилля під час виявлення та видалення max або min єопераціямиO(1). Відносно дороге вставлення зазвичай потрібно робити лишеO( √O(log(N−−√))O(log(N))O(1)разів. Таким чином, обчислювальні витрати цього алгоритму становлятьO(N+ √O(N−−√)у часі таO( √O(N+N−−√log(N))=O(N)на зберігання.O(N−−√)