Rolling rata-rata algoritma dalam C
Saat ini saya bekerja pada sebuah algoritma untuk melaksanakan rolling median filter (analog dengan rolling mean filter) di C. Dari pencarian saya dari sastra, tampaknya ada dua cukup efisien cara untuk melakukannya. Yang pertama adalah untuk memilah-jendela awal dari nilai-nilai, kemudian melakukan pencarian biner untuk menyisipkan nilai-nilai baru dan menghapus yang sudah ada pada setiap iterasi.
Kedua (dari Hardle dan Steiger, 1995, JRSS-C, Algoritma 296) membangun double-berakhir tumpukan struktur, dengan maxheap pada salah satu ujung, minheap pada yang lain, dan median di tengah. Ini menghasilkan linear-waktu algoritma bukan salah satu yang adalah O(n log n).
Berikut ini adalah masalah saya: pelaksana mantan bisa dilakukan, tapi saya harus menjalankan ini jutaan kali seri, sehingga efisiensi banyak hal. Yang terakhir ini terbukti sangat sulit untuk diterapkan. Saya menemukan kode di Trunmed.c file kode untuk statistik paket R, tapi itu lebih terbaca.
Apakah ada yang tahu dari yang ditulis dengan baik C implementasi linear waktu bergulir rata-rata algoritma?
Edit: Link ke Trunmed.kode c http://google.com/codesearch/p?hl=en&sa=N&cd=1&ct=rc#mYw3h_Lb_e0/R-2.2.0/src/library/stats/src/Trunmed.c
Saya telah melihat R's
src/perpustakaan/statistik/src/Trunmed.c
beberapa kali aku ingin sesuatu yang serupa juga di mandiri kelas C++ / C subrutin. Perhatikan bahwa ini adalah benar-benar dua implementasi dalam satu, melihatsrc/perpustakaan/statistik/pria/runmed.Rd
(sumber file help) yang mengatakanSaya tidak't menemukan yang modern pelaksanaan c++ struktur data dengan order-statistic sehingga akhirnya menerapkan ide-ide di atas coders link yang disarankan oleh MAK ( Pertandingan Editorial: gulir ke bawah untuk FloatingMedian).
Dua multisets
Ide pertama partisi data ke dalam dua struktur data (tumpukan, multisets dll) dengan O(ln N) per menyisipkan/menghapus tidak memungkinkan kuantil untuk diubah secara dinamis tanpa biaya besar. I. e. kita dapat memiliki rolling rata-rata, atau rolling 75% tetapi tidak keduanya pada saat yang sama.
Segmen pohon
Kedua ide menggunakan segmen pohon adalah O(ln N) untuk menyisipkan/penghapusan/pertanyaan tapi lebih fleksibel. Terbaik dari semua "N" adalah ukuran dari data range. Jadi jika anda bergulir rata-rata memiliki jendela dari satu juta item, tapi data anda bervariasi dari 1..65536, maka hanya 16 operasi yang diperlukan per gerakan rolling jendela dari 1 juta!!
C++ kode ini mirip dengan apa Denis diposting di atas ("di Sini's algoritma sederhana untuk terkuantisasi data")
GNU Statistik Orde Pohon
Sebelum menyerah, saya menemukan bahwa stdlibc++ berisi statistik orde pohon!!!
Ini memiliki dua operasi penting:
Lihat sebuah berkas++ manual policy_based_data_structures_test (cari "membagi dan bergabung").
Saya telah dibungkus pohon untuk digunakan dalam fasilitas header untuk compiler yang mendukung c++0x/c++11 gaya parsial typedefs:
I've dilakukan [implementasi C][1][ di sini][2]. Beberapa rincian lebih lanjut dalam pertanyaan ini: https://stackoverflow.com/questions/5527437/rolling-median-in-c-turlach-implementation.
Contoh penggunaan:
Saya menggunakan tambahan ini rata-rata estimator:
yang memiliki bentuk yang sama seperti yang lebih umum berarti estimator:
Di sini eta kecil belajar menilai parameter (misalnya
0.001
), dansgn()
adalah signum fungsi yang mengembalikan salah satu dari{-1, 0, 1}
. (Penggunaan konstaneta
seperti ini jika data non-stasioner dan anda ingin melacak perubahan dari waktu ke waktu; jika tidak, untuk sumber stasioner menggunakan sesuatu sepertieta = 1 / n
untuk berkumpul, di manan
adalah jumlah sampel yang dilihat sejauh ini.)Juga, aku dimodifikasi rata-rata estimator untuk membuatnya bekerja untuk sewenang-wenang quantiles. Secara umum, kuantil fungsi memberitahu anda nilai yang membagi data menjadi dua fraksi:
p
dan1 - p
. Berikut perkiraan nilai ini secara bertahap:Nilai
p
harus berada[0, 1]
. Ini pada dasarnya menggesersgn()
fungsi's simetris output{-1, 0, 1}
untuk bersandar ke satu sisi, partisi data sampel ke dalam dua merata berukuran sampah (fraksip
dan1 - p
dari data yang kurang dari/lebih besar dari kuantil perkiraan, masing-masing). Perhatikan bahwa untukp = 0.5
, hal ini akan mengurangi rata-rata estimator.Berikut ini's algoritma sederhana untuk terkuantisasi data (bulan):
Rolling rata-rata dapat ditemukan dengan mempertahankan dua partisi angka.
Untuk menjaga partisi menggunakan Min Heap dan Max Heap.
Max Heap akan berisi angka-angka yang lebih kecil dari sama dengan median.
Min Heap akan berisi angka lebih besar dari sama dengan median.
Menyeimbangkan Kendala: jika total jumlah elemen yang bahkan kemudian kedua tumpukan harus memiliki elemen yang sama.
jika jumlah dari unsur-unsur yang aneh kemudian Max Heap akan memiliki satu lagi elemen dari Min Heap.
Rata-rata Elemen: Jika Kedua partisi memiliki jumlah yang sama dari unsur-unsur maka rata-rata akan menjadi setengah dari jumlah maksimal elemen dari partisi pertama dan menit elemen dari partisi kedua.
Jika rata-rata akan menjadi max elemen dari partisi pertama.
Hal ini mungkin menunjukkan bahwa ada kasus khusus yang memiliki sederhana solusi yang tepat: ketika semua nilai-nilai dalam aliran adalah bilangan bulat dalam sejumlah (relatif) kecil kisaran yang ditetapkan. Misalnya, menganggap mereka semua harus berada di antara 0 dan 1023. Dalam hal ini hanya mendefinisikan sebuah array 1024 elemen dan menghitung, dan yang jelas semua nilai-nilai ini. Untuk masing-masing nilai dalam aliran kenaikan yang sesuai bin dan menghitung. Setelah aliran berakhir menemukan tempat sampah yang berisi hitungan/2 nilai tertinggi - dengan mudah dicapai dengan menambahkan berturut-turut sampah mulai dari 0. Menggunakan metode yang sama nilai sewenang-wenang urutan peringkat dapat ditemukan. (Ada minor komplikasi jika mendeteksi bin saturasi dan "upgrade" ukuran dari tempat penyimpanan untuk jenis yang lebih besar saat berlari akan dibutuhkan.)
Kasus khusus ini mungkin tampak buatan, tetapi dalam praktek hal ini sangat umum. Hal ini juga dapat diterapkan sebagai pendekatan untuk bilangan real jika mereka berbohong dalam jarak dan "cukup baik" tingkat presisi yang diketahui. Ini akan tahan selama cukup banyak setiap set pengukuran pada kelompok "dunia nyata" benda-benda. Misalnya, ketinggian atau bobot dari sekelompok orang. Tidak cukup besar set? Itu akan bekerja sama dengan baik untuk panjang atau bobot dari semua (individu) bakteri di planet - asumsi seseorang bisa memasok data!
Sepertinya aku salah membaca asli - yang sepertinya ingin jendela geser rata-rata bukan hanya rata-rata dari panjang sungai. Pendekatan ini masih bekerja untuk itu. Beban pertama N aliran nilai-nilai untuk jendela awal, maka untuk N+1th streaming nilai kenaikan yang sesuai bin sambil mengurangi sampah yang sesuai dengan 0th aliran nilai. Hal ini diperlukan dalam hal ini untuk mempertahankan N terakhir nilai untuk memungkinkan pengurangan, yang dapat dilakukan secara efisien oleh siklis pengalamatan array dari ukuran N. Karena posisi rata-rata hanya bisa berubah dengan -2,-1,0,1,2 pada setiap langkah dari jendela geser, isn't perlu untuk jumlah semua sampah hingga rata-rata pada setiap langkah, hanya menyesuaikan "rata-rata pointer" tergantung pada sisi mana(s) sampah yang dimodifikasi. Misalnya, jika kedua nilai baru dan salah satu yang dihapus jatuh di bawah rata-rata saat ini maka itu doesn't perubahan (offset = 0). Metode yang rusak ketika N menjadi terlalu besar untuk menahan terletak dalam memori.
Untuk mereka yang ingin berjalan rata-rata di Jawa...PriorityQueue adalah teman anda. O(log N) masukkan, O(1) rata-rata saat ini, dan O(N) hapus. Jika anda mengetahui distribusi data anda, anda dapat melakukan banyak hal lebih baik dari ini.
Jika anda memiliki kemampuan untuk referensi nilai-nilai sebagai fungsi dari titik-titik dalam waktu, anda bisa nilai sampel dengan penggantian, menerapkan bootstrapping untuk menghasilkan dinyalakan rata-rata nilai dalam interval kepercayaan. Ini akan membiarkan anda menghitung diperkirakan rata-rata dengan efisiensi yang lebih besar daripada terus-menerus pemilahan nilai-nilai yang masuk ke dalam struktur data.
Berikut ini adalah salah satu yang dapat digunakan ketika output yang tepat adalah tidak penting (untuk keperluan display dll.) Anda perlu totalcount dan lastmedian, ditambah newvalue.
Menghasilkan cukup hasil yang tepat untuk hal-hal seperti page_display_time.
Aturan: input stream harus halus pada urutan halaman yang menampilkan waktu dalam hitungan (>30 dll), dan memiliki non-nol rata-rata.
Contoh: page load time, 800 item, 10 ms...3000ms, rata-rata 90ms, median nyata:11ms
Setelah 30 input, median kesalahan ini umumnya <=20% (9ms..12ms), dan akan kurang dan kurang. Setelah 800 input, kesalahan adalah +-2%.
Lain pemikir dengan solusi yang sama di sini: https://stackoverflow.com/questions/11482529/median-filter-super-efficient-implementation/15150968#15150968
Berikut ini adalah implementasi java
Jika anda hanya memerlukan merapikan rata-rata cepat/cara mudah adalah dengan mengalikan terbaru dengan nilai x dan nilai rata-rata sebesar (1-x) maka tambah mereka. Hal ini kemudian menjadi rata-rata baru.
edit: Bukan apa yang pengguna meminta dan tidak valid secara statistik, tetapi cukup baik untuk banyak kegunaan. I'll meninggalkannya di sini (terlepas dari downvotes) untuk pencarian!