«Он-лайн» (ітератор) алгоритми для оцінки статистичної медіани, режиму, перекосу, ексцентричності?


86

Чи існує алгоритм для оцінки медіани, режиму, перекосу та / або ексцентричності набору значень, але який НЕ вимагає зберігання всіх значень відразу в пам'яті?

Я хотів би розрахувати основні статистичні дані:

  • середнє: середнє арифметичне
  • дисперсія: середнє значення квадратичних відхилень від середнього
  • стандартне відхилення: квадратний корінь з дисперсії
  • медіана: значення, яке відокремлює більшу половину чисел від меншої половини
  • режим: найчастіше знайдене значення в наборі
  • перекос: tl; лікар
  • куртоз: tl; лікар

Основними формулами для обчислення будь-якої з них є арифметика середньої школи, і я їх знаю. Є також багато бібліотек статистики, які їх реалізують.

Моя проблема полягає у великій кількості (мільярди) значень у наборах, якими я обробляю: Працюючи в Python, я не можу просто скласти список або хеш з мільярдами елементів. Навіть якщо я писав це на мові C, масиви з мільярдами елементів не надто практичні.

Дані не сортуються. Це виробляється випадковим чином, на льоту, за допомогою інших процесів. Розмір кожного набору дуже мінливий, і розміри не будуть відомі заздалегідь.

Я вже зрозумів, як досить добре обробляти середнє значення та відхилення, перебираючи кожне значення в наборі в будь-якому порядку. (Насправді, у моєму випадку я беру їх у тому порядку, в якому вони генеруються.) Ось алгоритм, який я використовую, люб'язно http://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#On-line_algorithm :

  • Ініціалізуйте три змінні: count, sum і sum_of_squares
  • Для кожного значення:
    • Кількість приростів.
    • Додайте значення до суми.
    • Додайте квадрат значення до sum_of_squares.
  • Поділіть суму на рахунок, зберігаючи як середнє значення змінної.
  • Поділіть суму_квадратів на кількість, зберігаючи як змінну середнє_квадратиків.
  • Середнє значення квадрата, зберігання як квадрат_значення.
  • Відніміть квадрат_значень із середніх квадратів, зберігаючи як дисперсію.
  • Вихідне середнє та дисперсія.

Цей "он-лайн" алгоритм має слабкі сторони (наприклад, проблеми з точністю, оскільки sum_of_squares швидко збільшується, ніж цілий діапазон або точність плаваючої функції), але в основному він дає мені те, що мені потрібно, без необхідності зберігати кожне значення в кожному наборі.

Але я не знаю, чи існують подібні методи для оцінки додаткової статистики (медіана, режим, перекос, ексцентричність). Я міг би жити з упередженим оцінювачем або навіть з методом, який певною мірою порушує точність, якщо пам’ять, необхідна для обробки значень N, значно менша за O (N).

Вказівка ​​на існуючу бібліотеку статистики також допоможе, якщо бібліотека має функції для обчислення однієї або декількох з цих операцій "в режимі он-лайн".


чи дані будуть передані відсортованими, і чи будете ви заздалегідь знати кількість входів?
chillysapien

Корисна існуюча посилання на StackOverflow: stackoverflow.com/questions/895929 / ...
dmckee --- екс-сповільнювач кошеня

Це цілочисельні дані або плаваючі дані? Ви маєте максимальне або мінімальне значення?
Стефан

dmckee: Я фактично використовую метод Велфорда для стандартного відхилення. Але я не бачу в цьому посиланні нічого про режим, медіану, ексцентричність чи перекос ... Я чогось пропускаю?
Райан Б. Лінч,

Стефан: Деякі набори даних - цілі числа, інші - плаваючі. Розподіл сукупності досить близький до нормального (гауссового), тому ми можемо встановити довірчий інтервал, але жорсткої межі діапазону немає (крім x> 0, в деяких випадках).
Райан Б. Лінч,

Відповіді:


53

Скевотність і Куртоз

Про он-лайн алгоритми для асиметрії та куртозу (за дисперсійною лінією), див. На тій самій вікі-сторінці тут паралельні алгоритми для статистики вищих моментів.

Медіана

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

Медіана та режим з підрахунком частоти

Якщо це цілі числа, я б підрахував частоти , мабуть, відсікаючи найвищі та найнижчі значення, які перевищують якесь значення, де я впевнений, що це вже не актуально. Для плаваючих значень (або занадто великої кількості цілих чисел) я, ймовірно, створював сегменти / інтервали, а потім використовував той самий підхід, що і для цілих чисел. Режим (приблизний) та медіана обчислення, ніж стає легким, на основі таблиці частот.

Звичайно розподілені випадкові змінні

Якщо воно зазвичай розподіляється, я б використовував середнє значення вибірки сукупності , дисперсію , перекос та ексцесивність як оцінювач максимальної ймовірності для невеликої підмножини. (Он-лайн) алгоритми для їх обчислення ви вже зараз. Наприклад, прочитайте пару сотень тисяч або мільйонів точок даних, поки ваша помилка оцінки не стане достатньо малою. Просто переконайтеся, що ви вибрали випадково зі свого набору (наприклад, щоб ви не вводили упередження, вибравши перші 100000 значень). Той самий підхід також може бути використаний для оцінки режиму та медіани для нормального випадку (для обох середнє значення вибірки є оцінювачем).

Подальші коментарі

Усі вищезазначені алгоритми можна запускати паралельно (включаючи багато алгоритмів сортування та вибору, наприклад, QuickSort та QuickSelect), якщо це допомагає.

Я завжди припускав (за винятком розділу про нормальний розподіл), що ми говоримо про вибіркові моменти, медіану та режим, а не про оцінки для теоретичних моментів із відомим розподілом.

Загалом, вибірка даних (тобто лише перегляд підмножини) має бути досить успішною, враховуючи обсяг даних, до тих пір, поки всі спостереження є реалізаціями однієї і тієї ж випадкової величини (мають однакові розподіли) та моменти, режим і медіана насправді існує для цього розподілу. Останнє застереження не є нешкідливим. Наприклад, середнє значення (і всі вищі моменти) для розподілу Коші не існує. У цьому випадку середнє значення вибірки для "малого" підмножини може бути суттєво відхилене від середнього значення вибірки для всієї вибірки.


57

Я використовую ці інкрементальні / рекурсивні середні та середні оцінки, які обидва використовують постійне зберігання:

mean += eta * (sample - mean)
median += eta * sgn(sample - median)

де eta - це малий параметр швидкості навчання (наприклад, 0,001), а sgn () - функція signum, яка повертає один із {-1, 0, 1}. (Використовуйте константу eta, якщо дані нестаціонарні, і ви хочете відстежувати зміни з часом; в іншому випадку для стаціонарних джерел ви можете використовувати щось на зразок eta = 1 / n для середнього оцінювача, де n - кількість зразків, побачених так далеко ... на жаль, це, здається, не працює для медіанного оцінювача.)

Здається, цей тип додаткового середнього оцінювача використовується повсюдно, наприклад, у правилах навчання нейронних мереж без нагляду, але медіанна версія здається набагато рідше, незважаючи на свої переваги (стійкість до вибіжних показників). Здається, медіанну версію можна використовувати як заміну середнього оцінювача у багатьох додатках.

Я хотів би бачити інкрементальний оцінювач режиму подібної форми ...

ОНОВЛЕННЯ

Я щойно змінив інкрементальний медіанний оцінювач для оцінки довільних квантилів. Загалом, квантильна функція ( http://en.wikipedia.org/wiki/Quantile_function ) повідомляє вам значення, яке ділить дані на дві частки: p та 1-p. Наступне оцінює це значення поступово:

quantile += eta * (sgn(sample - quantile) + 2.0 * p - 1.0)

Значення p має бути в межах [0,1]. Це, по суті, зміщує симетричний вивід функції sgn () {-1,0,1} нахилом в одну сторону, розділяючи зразки даних на два бункери нерівномірного розміру (частки p та 1-p даних менше / більше, ніж квантильна оцінка відповідно). Зверніть увагу, що для p = 0,5 це зменшується до медіанної оцінки.


3
Ця середня оцінка чудова. Чи знаєте ви, чи існують подібні оцінки для 0,25 / 0,75 квантилів?
Гачек

1
@Gacek, впевнений: розділіть вхідний потік на медіану Lohalf <медіана та Hihalf> і використовуйте медіану запуску на кожну половину.
denis

2
@Gacek: Я щойно оновив свою відповідь поступовим методом для оцінки будь-якої квантилі, де ви можете встановити p на 0,25, 0,75 або будь-яке значення в межах [0,1].
Тайлер Стрітер,

10
Це чудово працює для середніх показників, але я не бачу, як це дає щось, віддалене від медіани. Візьмемо, наприклад, послідовність міліметрових позначок часу: [1328083200000, 981014400000, -628444800000, 318240000000, 949392000000]які мають медіану 318240000000. Це рівняння зміщує попередню медіану на +/-, etaяке було рекомендованим значенням 0.001. Це не буде робити нічого для великих чисел, таких як ці, і це може бути занадто великим для дійсно малих чисел. Як би ви вибрали такий, etaякий насправді дав вам правильну відповідь, не знаючи відповіді апріорі?
mckamey

9
Уявіть, що цифри мають одиниці виміру, наприклад, міліметри. Тоді зрозуміло, що ета (для оцінки медіани) повинна мати ті самі одиниці виміру, що і вимірювання, і тому загальне значення, таке як 0,001, просто не має сенсу. На перший погляд кращим підходом є встановлення ета з поточної оцінки абсолютного відхилення: для кожного нового значення sampleоновіть cumadev += abs(sample-median). Потім встановіть eta = 1.5*cumadev/(k*k), де k- кількість зразків, побачених на даний момент.
толі

12

Я реалізував алгоритм P-Square для динамічного обчислення квантилів і гістограм без збереження спостережень в акуратному модулі Python, який я написав, під назвою LiveStats . Це має вирішити вашу проблему досить ефективно. Бібліотека підтримує всі згадані вами статистичні дані, крім режиму. Я ще не знайшов задовільного рішення для оцінки режиму.


FYI: р-квадрат алгоритм в наддуву C ++: <boost/accumulators/statistics/weighted_p_square_cumul_dist.hpp>.
Neil G

7

Райане, я боюся, ти не правильно зробив середнє та відхилення ... Це з’явилося кілька тижнів тому тут . І одним із сильних сторін онлайн-версії (яка насправді називається методом Велфорда) є той факт, що вона є особливо точною та стабільною, див. Обговорення тут . Одним із сильних моментів є той факт, що вам не потрібно зберігати загальну суму або загальну суму квадратів ...

Я не можу придумати жодного підходу до режиму та медіани в режимі он-лайн, який, здається, вимагає розгляду всього списку відразу. Але цілком може бути, що подібний підхід, ніж той, що стосується дисперсії та середнього значення, спрацює також для перекосів та ексцесу ...


re: skewness and kurtosisТак. Дивіться цю статтю: johndcook.com/blog/skewness_kurtosis
Джессі Чисхолм

3

Стаття Вікіпедії, наведена у запитанні, містить формули для обчислення перекосів та ексцесій в режимі он-лайн.

Для режиму - я вважаю - це ніяк не можна зробити в режимі он-лайн. Чому? Припустимо, що всі значення вашого введення різні, крім останнього, що дублює попереднє. У цьому випадку вам доведеться запам'ятати всі значення, вже побачені у вхідних даних, щоб виявити, що останнє значення дублює значення, побачене раніше, і робить його найбільш частим.

Для медіани вона майже однакова - до останнього введення ви не знаєте, яке значення стане медіаною, якщо всі вхідні значення різні, оскільки це може бути до або після поточної медіани. Якщо ви знаєте довжину вводу, ви можете знайти медіану, не зберігаючи всі значення в пам'яті, але вам все одно доведеться зберігати багато з них (я думаю, приблизно половину), оскільки неправильна вхідна послідовність може сильно змістити медіану в друга половина, можливо, робить будь-яке значення з першої половини медіаною.

(Зверніть увагу, що я маю на увазі лише точний розрахунок.)


2

Якщо у вас мільярди точок даних, то навряд чи вам потрібні точні відповіді, а не тісні відповіді. Як правило, якщо у вас є мільярди точок даних, основний процес, який їх генерує, швидше за все, підпорядковується якійсь статистичній властивості стаціонарності / ергодичності / змішування. Також може мати значення, чи очікуєте ви, що розподіл буде досить тривалим чи ні.

За цих обставин існують алгоритми он-лайн, низької пам’яті, оцінки квантилів (медіана є окремим випадком 0,5 квантиля), а також режими, якщо вам не потрібні точні відповіді. Це активне поле статистики.

приклад оцінки квантилів: http://www.computer.org/portal/web/csdl/doi/10.1109/WSC.2006.323014

приклад оцінки режиму: Bickel DR. Надійні оцінювачі режиму та перекосу безперервних даних. Обчислювальна статистика та аналіз даних. 2002; 39: 153–163. doi: 10.1016 / S0167-9473 (01) 00057-3.

Це активні поля обчислювальної статистики. Ви потрапляєте в ті сфери, де не існує жодного найкращого точного алгоритму, а їх різноманітність (по суті, статистичні оцінки), які мають різні властивості, припущення та ефективність. Це експериментальна математика. На цю тему є, мабуть, сотні до тисяч статей.

Останнє питання полягає в тому, чи дійсно вам потрібні перекоси та ексцентрики самі по собі, або, швидше за все, деякі інші параметри, які можуть бути більш надійними при характеристиці розподілу ймовірностей (за умови, що у вас є розподіл ймовірності!). Ви очікуєте Гауса?

Чи є у вас способи очищення / попередньої обробки даних, щоб зробити їх переважно гауссовими? (наприклад, суми фінансових операцій часто є дещо гауссовими після прийняття логарифмів). Ви очікуєте скінченних стандартних відхилень? Ви очікуєте жирних хвостів? Ці кількості, про які ви піклуєтесь, є в хвостах чи в основному?


2

Всі постійно повторюють, що не можна робити режим в Інтернеті, але це просто неправда. Ось стаття, що описує алгоритм вирішення саме цієї проблеми, винайденої в 1982 році Майклом Е. Фішером та Стівеном Л. Зальцбергом з Єльського університету. Зі статті:

Алгоритм пошуку більшості використовує один зі своїх регістрів для тимчасового зберігання одного елемента з потоку; цей пункт є поточним кандидатом у члени мажоритарного елементу. Другий регістр - це лічильник, ініціалізований 0. Для кожного елемента потоку ми просимо алгоритм виконати наступну процедуру. Якщо лічильник читає 0, встановіть поточний елемент потоку як нового кандидата для більшості (витіснивши будь-який інший елемент, який вже міг бути в реєстрі). Потім, якщо поточний елемент відповідає більшості кандидатів, збільште лічильник; в іншому випадку зменшіть лічильник. На цьому етапі циклу, якщо частина потоку, що бачиться до цього часу, має більшості елементів, цей елемент знаходиться в реєстрі кандидатів, і лічильник має значення більше 0. Що робити, якщо немає елемента більшості? Без повторного проходження даних - що неможливо в потоковому середовищі - алгоритм не завжди може дати однозначну відповідь за цих обставин. Він просто обіцяє правильно визначити більшість елементів, якщо він є.

Його також можна розширити для пошуку верхнього N з більшою кількістю пам'яті, але це повинно вирішити це для режиму.


4
Це цікавий алгоритм, але якщо я чогось не пропустив, тоді як всі мажоритарні значення будуть режимами, не всі режими будуть мажоритарними значеннями.
jkebinger

Посилання загинуло, тому я радий, що опис включено. АЛЕ, як описано, лічильник збільшується лише в тому випадку, якщо 2-й випадок кандидата більшості сусідять з 1-м входом. Який ВИЗНАЧАЄ відсортовані дані. Що НЕ гарантується у випадку онлайн (потокового) передавання даних. Для випадково впорядкованих даних це навряд чи може знайти будь-які режими.
Джессі Чисхолм,

1

Зрештою, якщо у вас немає апріорних параметричних знань про розподіл, я думаю, вам доведеться зберігати всі значення.

Тим не менш, якщо ви не маєте справу з якоюсь патологічною ситуацією, засіб (Rousseuw and Bassett 1990) цілком може бути достатнім для ваших цілей.

Дуже просто це передбачає обчислення медіани партій медіан.


0

медіана та режим не можуть бути обчислені в Інтернеті, використовуючи лише постійний доступний простір. Однак, оскільки медіана та режим у будь-якому випадку є більш "описовими", ніж "кількісними", ви можете оцінити їх, наприклад, відібравши набір даних.

Якщо дані нормально розподіляються в довгостроковій перспективі, ви можете просто використати середнє значення для оцінки медіани.

Ви також можете оцінити медіану, використовуючи наступний прийом: встановіть медіану оцінки M [i] для кожного, скажімо, 1 000 000 записів у потоці даних, так що M [0] є медіаною першого мільйона записів, M [1] медіана другого мільйона записів тощо. Потім використовуйте медіану M [0] ... M [k] як медіану оцінки. Це, звичайно, економить простір, і ви можете контролювати, скільки ви хочете використовувати простір, "налаштувавши" параметр 1000000. Це також можна узагальнити рекурсивно.


0

Добре чувак, спробуй наступне:

для c ++:

double skew(double* v, unsigned long n){
    double sigma = pow(svar(v, n), 0.5);
    double mu = avg(v, n);

    double* t;
    t = new double[n];

    for(unsigned long i = 0; i < n; ++i){
        t[i] = pow((v[i] - mu)/sigma, 3);
    }

    double ret = avg(t, n);

    delete [] t;
    return ret;
}

double kurt(double* v, double n){
    double sigma = pow(svar(v, n), 0.5);
    double mu = avg(v, n);

    double* t;
    t = new double[n];

    for(unsigned long i = 0; i < n; ++i){
        t[i] = pow( ((v[i] - mu[i]) / sigma) , 4) - 3;
    }

    double ret = avg(t, n);

    delete [] t;
    return ret;
}

де ви говорите, що вже можете розрахувати дисперсію вибірки (svar) і середню (avg), ви вказуєте їх на свої функції для цього.

Крім того, погляньте на приближення Пірсона. на такому великому наборі даних це було б досить схоже. 3 (середнє - медіана) / стандартне відхилення ви маєте медіану як max - min / 2

для плаваючого режиму значення не має. зазвичай їх можна було б заклеїти в сміттєві контейнери (наприклад, 1/100 * (макс. - хв.))



-1

Я, як правило, використовую відра, які можуть бути адаптивними. Розмір відра повинен відповідати точності, яка вам потрібна. Потім, коли кожна точка даних надходить, ви додаєте одну до відповідної кількості сегментів. Вони повинні дати вам прості наближення до медіани та ексцесу, підраховуючи кожне відро як його значення, зважене за його підрахунком.

Однією з проблем може бути втрата роздільної здатності з плаваючою комою після мільярдів операцій, тобто додавання такої вже не змінює значення! Щоб обійти це, якщо максимальний розмір сегмента перевищує деяку межу, ви можете зняти велику кількість з усіх підрахунків.


-1
for j in range (1,M):
    y=np.zeros(M) # build the vector y
    y[0]=y0

    #generate the white noise
    eps=npr.randn(M-1)*np.sqrt(var)

    #increment the y vector
    for k in range(1,T):
        y[k]=corr*y[k-1]+eps[k-1]

    yy[j]=y

list.append(y)

Я міг би використати якесь пояснення, щоб краще прив’язати це до вихідного питання.
Еріка
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.