Подтвердить что ты не робот

Сглаживание значений с течением времени: скользящее среднее или что-то лучше?

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

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

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

Я, однако, один из тех ужасных программистов-самоучек, не имеющих формального образования ни в чем, даже смутно связанных с CompSci или Math. Чтение немного говорит о том, что это может быть фильтр с высоким или низким пропусканием, но я не могу найти ничего, что объясняет в терминах, приемлемых для взлома, как я, что эффект этих алгоритмов будет на массив значений, не говоря уже о том, как математика работает. Ответ, приведенный здесь, например, технически отвечает на мой вопрос, но только в терминах, понятных тем, кто, вероятно, уже знает, как решить проблему.

Было бы очень симпатичным и умным человеком, который мог бы объяснить, как это проблема, и как работают решения, с точки зрения понятных для выпускников искусств.

4b9b3361

Ответ 1

Если ваше скользящее среднее должно быть длинным для достижения требуемого сглаживания, и вам действительно не нужна какая-либо конкретная форма ядра, тогда вам будет лучше, если вы используете экспоненциально затухающую скользящую среднюю:

a(i+1) = tiny*data(i+1) + (1.0-tiny)*a(i)

где вы выбираете tiny как подходящую константу (например, если вы выберете tiny = 1- 1/N, она будет иметь такое же усреднение, как и окно размера N, но распределено по-разному по более старым точкам).

В любом случае, поскольку следующее значение скользящего среднего зависит только от предыдущего и ваших данных, вам не нужно держать очередь или что-то еще. И вы можете думать об этом как о чем-то вроде: "Ну, у меня есть новый момент, но я на это не верю, поэтому я собираюсь сохранить 80% моей старой оценки измерения и только доверяйте этой новой точке данных 20%". Это в значительной степени то же самое, что сказать: "Ну, я доверяю только этой новой точке 20%, и я буду использовать 4 других пункта, которым я доверяю ту же сумму", за исключением того, что вместо явного принятия 4 других очков вы предполагая, что усреднение, которое вы делали в прошлый раз, было разумным, поэтому вы можете использовать свою предыдущую работу.

Ответ 2

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

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

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

if (abs(thisValue - averageOfLast10Values) > someThreshold)
{
    thisValue = averageOfLast10Values;
}

Вот график гиков, чтобы проиллюстрировать:

graph comparison

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

Ответ 3

Скользящее среднее я могу спуститься с... но мне кажется, что это возможно довольно неэффективен.

Нет причин, по которым скользящее среднее должно быть неэффективным. Вы сохраняете количество требуемых точек данных в некотором буфере (например, круглая очередь). В каждой новой точке данных вы выставляете самое старое значение и вычитаете из суммы, а затем нажимаете новейшую и добавляете ее в сумму. Таким образом, каждая новая точка данных действительно влечет за собой только pop/push, добавление и вычитание. Ваша скользящая средняя всегда равна этой смещаемой сумме, деленной на количество значений в вашем буфере.

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

О, а также: ужасные программисты-самоучки объединяются!;)

Ответ 4

Экспоненциально убывающая скользящая средняя может быть рассчитана "вручную" только с трендами, если вы используете правильные значения. См. http://www.fourmilab.ch/hackdiet/e4/ за идею о том, как это сделать быстро с помощью ручки и бумаги, если вы ищете "экспоненциально сглаженное скользящее среднее с 10 % сглаживания". Но поскольку у вас есть компьютер, вы, вероятно, захотите выполнять двоичное смещение, а не десятичное смещение;)

Таким образом, все, что вам нужно, это переменная для вашего текущего значения и одна для среднего. Затем можно вычислить следующее среднее значение.

Ответ 5

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

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