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

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

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

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

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

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

Ответы [ 5 ]

57 голосов
/ 21 сентября 2010

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

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

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

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

Вот график гика для иллюстрации:

graph comparison

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

37 голосов
/ 21 сентября 2010

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

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

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

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

6 голосов
/ 21 сентября 2010

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

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

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

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

2 голосов
/ 21 сентября 2010

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

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

1 голос
/ 30 апреля 2016

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

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

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