Perkiraan kuartil online tanpa menyimpan pengamatan

13

Saya perlu menghitung kuartil (Q1, median dan Q3) secara real-time pada set besar data tanpa menyimpan pengamatan. Saya pertama kali mencoba algoritma P square (Jain / Chlamtac) tapi saya tidak puas dengan itu (penggunaan cpu terlalu banyak dan tidak yakin dengan presisi setidaknya pada dataset saya).

Saya menggunakan sekarang algoritma FAME ( Feldman / Shavitt ) untuk memperkirakan median dengan cepat dan mencoba untuk menurunkan algoritma untuk menghitung juga Q1 dan Q3:

M = Q1 = Q3 = first data value 
step =step_Q1 = step_Q3 = a small value
for each new data :
        # update median M 
        if M > data:
            M = M - step
        elif M < data:
            M = M + step
        if abs(data-M) < step:
            step = step /2

        # estimate Q1 using M
        if data < M:
            if Q1 > data:
                Q1 = Q1 - step_Q1
            elif Q1 < data:
                Q1 = Q1 + step_Q1
            if abs(data - Q1) < step_Q1:
                step_Q1 = step_Q1/2
        # estimate Q3 using M
        elif data > M:
            if Q3 > data:
                Q3 = Q3 - step_Q3
            elif Q3 < data:
                Q3 = Q3 + step_Q3
            if abs(data-Q3) < step_Q3:
                step_Q3 = step_Q3 /2

Untuk melanjutkan, itu hanya menggunakan median M yang diperoleh dengan cepat untuk membagi kumpulan data menjadi dua dan kemudian menggunakan kembali algoritma yang sama untuk Q1 dan Q3.

Ini tampaknya berfungsi entah bagaimana tetapi saya tidak dapat menunjukkan (saya bukan ahli matematika). Apakah itu cacat? Saya akan sangat menghargai saran atau teknik lain yang sesuai dengan masalah.

Terima kasih banyak atas bantuan Anda !

==== EDIT =====

Bagi mereka yang tertarik dengan pertanyaan seperti itu, setelah beberapa minggu, saya akhirnya berakhir hanya dengan menggunakan Reservoir Sampling dengan daftar nilai 100 dan itu memberikan hasil yang sangat memuaskan (bagi saya).

Louis Hugues
sumber
Apakah Anda mencari bukti bahwa Q1 dan Q2 menyatu dengan kuantil sebenarnya ketika jumlah contoh bertambah dengan cara yang mirip dengan analisis rantai markov dalam slide yang Anda tautkan? Dalam hal implementasi, algoritma di atas tampaknya tidak cacat (saya menguji hampir sama dengan standar normal dalam R dan algoritma berfungsi dengan baik).
Theja
1
@Theja terima kasih, saya tidak mencari bukti (terlalu banyak pekerjaan) tetapi hanya saran dan komentar, Masalah utama yang saya lihat adalah mendasarkan perhitungan pada menjalankan estimasi median, seperti yang ditunjukkan oleh Whuber.
Louis Hugues

Jawaban:

3

Median adalah titik di mana 1/2 pengamatan jatuh di bawah dan 1/2 di atas. Demikian pula, perecentile ke-25 adalah median untuk data antara min dan median, dan persentil ke-75 adalah median antara median dan maks, jadi ya, saya pikir Anda berada di tanah padat menerapkan algoritma median apa pun yang Anda gunakan pertama pada seluruh data diatur untuk mempartisi itu, dan kemudian pada dua bagian yang dihasilkan.

Perbarui :

Pertanyaan tentang stackoverflow ini mengarah ke makalah ini: Raj Jain, Imrich Chlamtac: Algoritma P² untuk Perhitungan Dinamis Kuantil dan Histogram Tanpa Menyimpan Pengamatan. Komunal. ACM 28 (10): 1076-1085 (1985) yang abstraknya menunjukkan itu mungkin sangat menarik bagi Anda:

Algoritma heuristik diusulkan untuk perhitungan dinamis jika median dan kuantil lainnya. Estimasi tersebut dihasilkan secara dinamis saat pengamatan dihasilkan. Pengamatan tidak disimpan; oleh karena itu, algoritma ini memiliki persyaratan penyimpanan yang sangat kecil dan tetap terlepas dari jumlah pengamatan. Ini membuatnya ideal untuk diimplementasikan dalam chip kuantil yang dapat digunakan dalam pengontrol dan perekam industri. Algoritma selanjutnya diperluas ke plot histogram. Keakuratan algoritma dianalisis.

Avraham
sumber
4
Balasan ini mengabaikan dua poin halus, satu tidak penting tetapi yang lain mungkin sangat penting. Yang tidak penting adalah bahwa teknik pemisahan ganda menghitung engsel atas dan bawah yang dapat sedikit berbeda dari median, tergantung pada ukuran sampel. Yang penting adalah bahwa pemisahan ganda tampaknya didasarkan pada perkiraan median. Setiap variasi antara perkiraan ini dan median aktual akan menyebabkan engselnya juga bervariasi. Secara intuitif, ini seharusnya tidak menjadi masalah karena jumlah data tumbuh lebih besar, tetapi ini adalah masalah yang perlu beberapa analisis.
whuber
Tidakkah secara langsung memperkirakan kuartil akan mengalami masalah serupa? Estimasi langsung akan mempartisi titik data menjadi rasio . Ini membagi elemen menjadi dan kemudian mengambil salah satu dari "2" itu dan membaginya menjadi . Saya bukan ahli teori, benar, tetapi, secara umum, bukankah perbedaan antara keduanya akan berbeda paling banyak satu tempat ke kiri atau ke kanan dan akan bertemu ketika bertambah? Ya, distribusi patologis dapat dibuat, tetapi itu akan menderita dari estimasi median langsung juga. Tentunya, menyimpan semua nilai lebih baik, tentu saja. 1 : 3 2 : 2 1 : 1 nn1:32:21:1n
Avraham
2
@ Avraham, terima kasih telah menunjukkan makalahnya, seperti yang saya sebutkan saya sudah mencoba algoritma P-square dari Chain dan Chlamtac. pada data saya atur algo yang saya decribed memberikan hasil yang lebih baik (MSE) dan lebih cepat. Jadi saya bertanya-tanya apakah itu dapat memiliki beberapa masalah. Seperti whuber mengatakan fakta bahwa itu menggunakan estimasi berjalan adalah masalah potensial; tapi saya tidak tahu apakah ini benar-benar penting atau tidak.
Louis Hugues
Ups, lihat itu dan lupakan. Permintaan maaf saya.
Avraham
0

Perubahan yang sangat kecil pada metode yang Anda posting dan Anda dapat menghitung persentil sewenang-wenang, tanpa harus menghitung semua kuantil. Berikut kode Python:

class RunningPercentile:
    def __init__(self, percentile=0.5, step=0.1):
        self.step = step
        self.step_up = 1.0 - percentile
        self.step_down = percentile
        self.x = None

    def push(self, observation):
        if self.x is None:
            self.x = observation
            return

        if self.x > observation:
            self.x -= self.step * self.step_up
        elif self.x < observation:
            self.x += self.step * self.step_down
        if abs(observation - self.x) < self.step:
            self.step /= 2.0

dan sebuah contoh:

import numpy as np
import matplotlib.pyplot as plt

distribution = np.random.normal
running_percentile = RunningPercentile(0.841)
observations = []
for _ in range(1000000):
    observation = distribution()
    running_percentile.push(observation)
    observations.append(observation)

plt.figure(figsize=(10, 3))
plt.hist(observations, bins=100)
plt.axvline(running_percentile.x, c='k')
plt.show()

Distribusi Normal dengan 1 STD persentil

Parrowdice
sumber