Библиотека-аккумулятор C++ с возможностью удаления старых семплов

В Boost.Accumulator вы можете добавлять выборки в аккумулятор, а затем извлекать из него статистические величины. например:

acc(1.)
acc(2.)
acc(3.)
cout << mean; // 2

В библиотеке есть много более сложных статистических величин, таких как skewness, kurtosis или p_square_cumulative_distribution.

Я хотел бы сделать что-то вроде этого:

acc(1.)
acc(2.)
acc(3.)
std::cout << mean(acc); // 2
acc.pop() // withdraw the first value (1.)
std::cout << mean(acc); // 2.5

pop() будет работать по принципу FIFO (First In First Out). Что я пытаюсь сделать, так это рассчитать статистику по моим данным в режиме онлайн (инкрементно) в скользящем временном окне.

Аккумулятор должен будет хранить все значения внутри себя.

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


person Arthur    schedule 26.09.2012    source источник
comment
Аккумуляторы Boost не сохраняют значения точек данных. В этом весь смысл. Таким образом, вы не можете вытолкнуть одну точку данных. Представьте, что у вас есть максимум 0, 0, 0, 5: Как бы вы вытащили 5?   -  person Kerrek SB    schedule 26.09.2012
comment
@KerrekSB Я понимаю, что Boost не делает то, что я хочу, поэтому мой вопрос. Кроме того, в некоторых случаях он сохраняет значения, например. rolling_sum. Наконец, в примере со скользящей суммой, но, возможно, и во многих других случаях, вам нужно сохранить все значения, но вам не нужно использовать их все для вычисления нового количества.   -  person Arthur    schedule 26.09.2012
comment
Я знаю, что вы хотите очистить только определенные значения, но я думаю, стоит упомянуть, что вы можете очистить весь аккумулятор, используя acc = {}   -  person J'e    schedule 21.01.2021


Ответы (3)


Поскольку вы упомянули «скользящее временное окно», одним из вариантов является использование скользящего среднего (есть также скользящая сумма и скользящий счетчик), которое является средним значением последних N выборок. В зависимости от ваших потребностей вы можете создать отдельные аккумуляторы с разными размерами окна.

typedef accumulator_set<double,
                stats<tag::rolling_mean>
                > my_accumulator;

my_accumulator acc(tag::rolling_window::window_size = 3);
acc(1.);
acc(2.);
acc(3.);
std::cout << rolling_mean(acc);
// Reset accumulator and use different window size
acc = my_accumulator(tag::rolling_window::window_size = 2);
acc(2.);
acc(3.);
std::cout << rolling_mean(acc);

Кроме того, если вы посмотрите на их реализацию, они используют boost/circular_buffer.hpp.

person Jesse Good    schedule 26.09.2012

Вероятно, вы захотите хранить данные в std::deque вместо вектора, поэтому и вставка, и удаление могут иметь постоянную сложность. Если вы используете вектор, он неизбежно будет линейным.

Помимо этого, довольно просто применить алгоритм к коллекции. Странно, однако, что я не знаю набора таких алгоритмов, уже написанных и протестированных, несмотря на то, что набор доступных алгоритмов кажется довольно очевидным.

Что бы это ни стоило, довольно просто создать адаптер для подачи данных из коллекции в аккумулятор для вычисления статистических данных, о которых вы можете. В некоторых случаях аккумулятору, вероятно, приходится выполнять дополнительную работу для постепенного вычисления результатов, но я полагаю, что довольно редко теряется достаточная эффективность, чтобы о ней беспокоиться.

person Jerry Coffin    schedule 26.09.2012
comment
Необходимость кормить аккумулятор на каждой итерации будет не очень эффективной, поэтому я думаю, что сделаю свое собственное решение. По вашему более общему замечанию, было бы действительно полезно, если бы библиотека включала такой алгоритм, тем более что эта википедия page предполагает, что существуют способы эффективного вычисления моментов более высокого порядка в режиме скользящего окна в режиме онлайн. - person Arthur; 26.09.2012

Вам, вероятно, потребуется просто сохранить все свои выборки в векторе, а затем накапливать их из вектора для каждого расчета. Что-то вроде этого: https://stackoverflow.com/a/7616783/219136

person PherricOxide    schedule 26.09.2012