Các thuật toán để tính toán trung vị đang chạy?


18

Trên kích thước cửa sổ nhỏ hơn, n log nsắp xếp có thể hoạt động. Có thuật toán nào tốt hơn để đạt được điều này?


1
Tôi nghĩ rằng đây là ứng cử viên đầu tiên được chuyển sang Stack Overflow.

Có thể, nhưng nó cần nhiều lời giải thích hơn về SO.
walkytalky

2
Hầu hết các lập trình viên đều biết "trung vị". (sort (mảng)) [length / 2] là một gợi ý đủ lớn cho những người quên. Ngoài ra, ở mức cơ bản nhất cho mỗi điểm mới, bạn chỉ cần thực hiện chia đôi / chèn vào một nửa của mảng ...
Paul

1
Mở lại cuộc thảo luận sau tại meta.stats.stackexchange.com/questions/276/iêu
Rob Hyndman

2
Quá tầm thường để có nhiều hơn một nhận xét, nhưng mã cho trung vị của 3s chỉ là a + b + c - max (a, b, c) - min (a, b. C). Điều đó hoạt động tốt ngay cả khi quan hệ có mặt. Điều đó chỉ rõ ràng đối với tôi khi tôi nghĩ về nó từ mã của người khác (tại sao anh ta (trong trường hợp này) lại thêm và trừ để lấy trung vị ???) và một vài người khác có thể có phản ứng tương tự. max () và min () thường được triển khai dưới dạng các hàm siêu nhanh. Đáng buồn là không có lừa như vậy nói chung.
Nick Cox

Câu trả lời:


11

Đó là hình thức xấu để sắp xếp một mảng để tính toán trung vị. Các trung vị (và các lượng tử khác) thường được tính toán bằng thuật toán quickselect , với độ phức tạp .O(n)

Bạn cũng có thể muốn xem câu trả lời của tôi cho một câu hỏi liên quan gần đây ở đây .


7

Đây là một bài viết mô tả một thuật toán có thể. Mã nguồn bao gồm và một ứng dụng khá nghiêm trọng (phát hiện sóng hấp dẫn dựa trên giao thoa kế laser), vì vậy bạn có thể mong đợi nó sẽ được kiểm tra tốt.


1
Liên kết bị hỏng và không có thông tin về tiêu đề hoặc tác giả, thật khó để tìm thấy bất cứ điều gì nó đề cập đến.
Kristopher Johnson


6

Nếu bạn sẵn sàng chịu đựng một xấp xỉ, có những phương pháp khác. Ví dụ: một xấp xỉ là một giá trị có thứ hạng nằm trong khoảng cách (do người dùng chỉ định) so với trung bình thực. Ví dụ: trung vị có thứ hạng (bình thường hóa) xếp hạng 0,5 và nếu bạn chỉ định một thuật ngữ lỗi là 10%, bạn muốn có một câu trả lời có thứ hạng từ 0,45 đến 0,55.

Nếu một câu trả lời như vậy là phù hợp, thì có nhiều giải pháp có thể hoạt động trên các cửa sổ trượt dữ liệu. Ý tưởng cơ bản là duy trì một mẫu dữ liệu có kích thước nhất định (khoảng 1 / thuật ngữ lỗi) và tính toán trung vị trên mẫu này. Có thể chỉ ra rằng với xác suất cao, bất kể tính chất của đầu vào, trung vị kết quả đáp ứng các tính chất tôi đã đề cập ở trên.

Vì vậy, câu hỏi chính là làm thế nào để duy trì một mẫu dữ liệu đang chạy ở một kích thước nhất định và có nhiều cách tiếp cận cho điều đó, bao gồm cả kỹ thuật được gọi là lấy mẫu hồ chứa. Ví dụ: bài viết này: http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.24.7136


4

Nếu bạn duy trì cửa sổ dữ liệu có độ dài k dưới dạng danh sách liên kết đôi được sắp xếp sau đó, bằng phương pháp tìm kiếm nhị phân (để chèn từng phần tử mới khi nó được chuyển vào cửa sổ) và một mảng con trỏ tròn (để xác định ngay các phần tử cần phải xóa), mỗi ca làm việc của cửa sổ đòi hỏi nỗ lực O (log (k)) để chèn một phần tử, chỉ nỗ lực O (1) để xóa phần tử được dịch chuyển ra khỏi cửa sổ và chỉ nỗ lực tìm O (1) trung vị (vì mỗi khi một phần tử được chèn hoặc xóa vào danh sách, bạn có thể cập nhật một con trỏ thành trung vị trong thời gian O (1)). Do đó, toàn bộ nỗ lực xử lý một mảng có độ dài N là O ((nk) log (k)) <= O (n log (k)). Điều này tốt hơn bất kỳ phương pháp nào khác được đề xuất cho đến nay và nó không phải là một xấp xỉ, nó là chính xác.


1
Bạn có thể giải thích về cách bạn đề xuất thực hiện tìm kiếm nhị phân trong danh sách liên kết đôi được sắp xếp không?
NPE

một "liên kết" cho phép bạn duyệt qua danh sách theo thứ tự được sắp xếp; cái còn lại cho phép bạn di chuyển theo thứ tự xuất hiện các phần tử. Tuy nhiên, không rõ làm thế nào bạn sẽ làm điều này với con trỏ, như câu hỏi @aix.
shabbychef

2
@aix Tôi nghĩ rằng sự thân mật của bạn là chính xác; Tôi sẽ cần một danh sách bỏ qua có thể lập chỉ mục, không chỉ là một danh sách liên kết đôi được sắp xếp. Ý tưởng là có một cấu trúc dữ liệu cho phép chèn một phần tử, xóa một phần tử và tìm trung vị trong thời gian O (log (n)) dự kiến ​​(hoặc tốt hơn).
whuber

3

Như bạn đã đề cập sắp xếp sẽ O(n·log n)dành cho một cửa sổ có chiều dài n. Làm điều này di chuyển thêm một l=vectorlengthlàm cho tổng chi phí O(l·n·log n).

Cách đơn giản nhất để thúc đẩy điều này là bằng cách giữ một danh sách có thứ tự của n phần tử cuối cùng trong bộ nhớ khi di chuyển từ cửa sổ này sang cửa sổ tiếp theo. Khi loại bỏ / chèn một phần tử từ / vào danh sách theo thứ tự, cả hai O(n)điều này sẽ dẫn đến chi phí O(l·n).

Mã giả:

l = length(input)
aidvector = sort(input(1:n))
output(i) = aid(n/2)
for i = n+1:l
    remove input(i-n) from aidvector
    sort aid(n) into aidvector
    output(i) = aid(n/2)


2

Nếu bạn có thể sống với ước tính thay vì trung bình thực, Thuật toán Remedian (PDF) là một lượt với yêu cầu lưu trữ thấp và độ chính xác được xác định rõ.

Người sửa chữa với cơ sở b tiến hành bằng cách tính toán trung vị của các nhóm quan sát b, và sau đó là trung vị của các trung vị này, cho đến khi chỉ còn một ước tính duy nhất. Phương pháp này chỉ cần k mảng có kích thước b (trong đó n = b ^ k) ...


0

Tôi đã sử dụng Thư viện C ++ RunningStats này trong một ứng dụng nhúng. Đây là thư viện thống kê chạy đơn giản nhất mà tôi đã tìm thấy.

Từ liên kết:

Mã này là một phần mở rộng của phương pháp Knuth và Welford để tính toán độ lệch chuẩn trong một lần truyền dữ liệu. Nó cũng tính toán độ lệch và kurtosis với giao diện tương tự. Ngoài việc chỉ yêu cầu một lần chuyển qua dữ liệu, thuật toán còn ổn định và chính xác về mặt số.


Trang đó có nói gì về trung vị không?
musiphil
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.