Лучший способ сгладить / отфильтровать поток данных - PullRequest
0 голосов
/ 01 января 2019

У меня есть поток целочисленных данных (поступающих со временем), который выглядит примерно так.

[46, 46, 46, 47, 47, 47, 47, 47, 47, 46, 47, 47, 47, 47, 47, 47, 46, 47, 47, 47, 47, 47, 47, 47, 46, 47, 46, 46, 46, 46, 46, 46, 46, 100, 100, 100, 70, 100, 100]

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

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

Небольшая задержка в порядке.Я хотел бы избежать усреднения данных, поскольку, если число перепрыгивает с 40 на 100, я бы хотел, чтобы оно не совпадало с 100 (т. Е. 40, 60, 80, 100) и вместо этого становилось равным 100, как только оно считаетсяшум.

Каков наилучший метод сглаживания / фильтрации данных этого типа?

1 Ответ

0 голосов
/ 02 января 2019

Прежде всего, я не эксперт по обработке сигналов, но у меня есть некоторый базовый опыт (давайте назовем это так).Кроме того, я видел ваши другие (возможно, связанные) вопросы, и вы говорили о настройках и музыкальных нотах.Предполагая, что это связано с этой проблемой (?).

Краткий ответ:


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

Длинный ответ:


В статистике есть нечто, называемое MODE помимо стандартных AVERAGE и MEDIAN :

Врегистр всего массива из 39 значений, который вы привели в качестве примера в своем вопросе:

main_array_values_by_occurrence = [46 => 13 раз, 47 => 20 раз, 70 => 1 раз, 100 => 5 раз]

average = 54.05 => 54 rounded
median  = 47
mode    = 47

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

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

Медиана звучит привлекательно в качестве основного кандидата для алгоритма сравнения, но что вы должны использовать?Медиана или Мод?Это действительно зависит от типа данных, с которыми вы работаете, и их распространения.Например, если, скажем, мы определяем высоту звука инструмента (музыкальные ноты) и у нас есть приличная точность нашего детектора, метод режима звучит как хороший выбор, потому что медиана может вводить в заблуждение.Если наш тюнер обнаружил 60% ноты времени А4 и 40% времени других нот, в среднем он обнаружил А4, потому что этот тон был доминирующим в нашем потоке данных.Подробнее о случаях использования режима также по вышеуказанной ссылке здесь .


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

array_1 = [46 (first in) 46 46 47 47 (last in)]

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

array_1_occur = [46 => 3 47 => 2]

Затем вы можете использовать простой сравнительный алгоритм для последовательного определения относительной разницы между ними;Вы можете хранить эти значения и разницу +/- в отдельном массиве.

array_1_diff = [0 0 0 +1 +1]

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

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

array_2 = [46 46 90 47 47]

array_2_min = 46
array_2_max = 90
array_2_avg = (46+46+90+47+47) : 5 = 55.2
array_2_local_avg_ref = round(55.2) = 55 ( <-- useless in this case because median() value 47 is VERY DIFFERENT from average value! => thus we DISCARD it from analysis and mark value of 90 as a major SUSPECT )

В случае с массивом array_1, например:

array_1_avg = 46
array_1_med = 47 (you order values from lowest to largest and take the middle one as median)
array_1_mod = 46 (not sure 100% about bi-modal or multi-modal cases at least in Excel a value of 46 is returned possibly as the lowest integer with highest occurrence in the ordered list. You can customize that in the event of multi-mode or no mode distribution algorithm fallback to median)

Затем вы должны решить, собираетесь ли вы бросить его или оставить его.

Как?Что ж, если в массиве из 5 значений все ваши значения примерно одинаковы (с точки зрения допуска), за исключением этой единственной точки данных, это явно зашумленный кандидат.Это можно определить из сравнения медианы или значения режима.В худшем случае будет, если группа содержит все 5 различных значений.В этом случае значение, наиболее близкое к значению предыдущей захваченной группы, будет установлено в качестве контрольной точки.Но что, если следующий массив из 5 содержит все значения в том же диапазоне, что и зашумленный кандидат?Поэтому по этой причине мы должны хранить его до тех пор, пока не будут получены следующие 5 значений для сравнения и анализа.Если кандидат все еще далек от «нормы», мы можем подтвердить, что это шум или единичное случайное событие (незначительное).Если, с другой стороны, мы найдем хотя бы одно значение, которое находится рядом с ним (запомните порог или шаг), мы сохраняем его.

У вас будет задержка в выходном потоке, по крайней мере, N x buffer_length dataточки (образцы): для базового N = 2 (прошлое + настоящее) или N = 3 (прошлое + настоящее + будущее) или даже больше.


Несколько простых наблюдений: если шаг просто + /- 1, то любое значение, выпадающее из «нормы», будет рассматриваться как шум.Проблема здесь в том, что, если значения начинают сильно колебаться, скажем, каждая последующая выборка равна +/- 1 соответственно (событие осцилляции)?В этом случае у вас будет проблема с определением «нормы», потому что вы работаете только с целыми числами.Эту проблему можно решить, сохранив среднее значение, скажем, последних 15-50-100 выборок данных и получив последнее стабильное значение в этом случае (без изменений).

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

На самом деле, вам не нужно 3 (или N)буферы.Один буфер хорош, но вы можете внутренне разделить его на разделы (скажем, буфер из 15 выборок, разделенных на 3 раздела), что значительно упростит обработку (эта часть может быть неочевидной, поэтому я упомянул об этом).

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

Конечно, при использовании некоторых условий, таких как проверка расстояния между текущей выборкой иЗначение медианы / режима и удаление зашумленных образцов - это обман, потому что это не «настоящий» алгоритм NR, как свертка или что-то в этом роде.Это особый случай, если учесть этот конкретный случай.

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

...