#математика #javascript
Здравствуйте! Есть одномерный массив (размерностью в несколько тысяч элементов) вещественных числе. Если построить график по этим значениям, то видно что есть некоторая флюктуация (разброс) значений (с немногочисленными резкими пиками). Пример (для наглядности, интервалы замеров равномерны): Показания температуры Уровень освещенности Заряд батареи Уровня жидкости и т.д. исх. 10 12 15 40 17 16 12 10 22 12 14 15 14 10 12 сглаж.~ 10 13 15 16 16 14 12 16 14 13 14 14 13 11 12 Нужно не увеличивая число точек сгладить показания: (примерный набросок: "сглаженная линия" - показания без резких скачков) Понятное дело, что для этого нужна аппроксимация данных, но я уже несколько дней затрудняюсь привести найденный алгоритм аппроксимации кривой Безье к требуемому виду: p1 = f(t) = p0 * (1-t)^2 + 2 * p2 * t * (1 - t) + p1 * t^2; где, p1 сглаживаемое промежуточное значение между двумя своими соседями, t=0.5 (по идеи именно при 0.5 должна браться именно промежуточное значение). Потом Нашел алгоритм здесь, а сам он выложен тут. Но данный алгоритм не подходит потому что работаем максимум на 32 точках, да и с факториалами он слишком долго на JS будет выполняться, если вообще будет. А записать алгоритм без факториалов (это вроде возможно, если верить формулам из Википедии) у меня не получается. Ещё можно использовать приведенную мной формулу и пройтись ею по ряду, но не думаю что это хорошая идея... Если бы можно было использовать за раз больше 32 точек (хотя бы 100), то дело было бы веселее. Но я просто не знаю как это записать формулой по которой уже писать алгоритм... Кто-нибудь знает как в числовом ряду сгладит "шум" и "пики" ? Бьюсь уже не один день но что-то получается определиться с алгоритмом. Я в математике не очень, поэтому не могу продраться через теорию к формуле... Надеюсь кто-нибудь мне с этим поможет ? Пробовал использовать "скользящее среднее" (по совету @lampa), но данные сильно искажаются. Вот код (вроде не накосячил, но кто его знает): a=[40,40,40,40,37,40,36,39,36,39,34,39,35,38,33,37,35,34,36,35,34,33,33,33,32,33,32,33,32,33,31,32,29,31,29,31,28,33,27,30,25,29,24,28,28]; for (var i=n, l=a.length; i=m; j--) s += a[j]; r[i] = s/n } Но в результате все равно остановился на исходном варианте - сглаживании Безье (квадратичной кривой): for (var j=0, m=4; j Ответы
Ответ 1
Если это требуется только для графика — библиотека D3js прекрасно справляется с этой задачей, даже можно динамически менять уровень сглаживания. Я недавно делал маленький проект, где как раз реализовал эту фишку (пример). Если же интересует именно математика, то, возможно, подойдёт «скользящее среднее» (simple moving average) из статистики: вместо значения в каждой точке, берите для графика среднее арифметическое от нее и N соседних точек ряда. Если провести параллель со звуком, вам нужно срезать верхние частоты, Low Pass фильтр : )Ответ 2
Короч смотри, что я тут придумал: Берем http://mourner.github.io/simplify-js/ , т.е. урезаем твои 10 тыщ точек до 170. Дальше я портанул из http://habrahabr.ru/post/130873/ библиотечку, сглаживающую шумы: https://github.com/lampaa/Bezier.js А дальше как хочешь, можешь сглаживать, можешь нет, вот тут есть дельный коммент: http://www.gamedev.ru/code/forum/?id=124256&page=5#m64Ответ 3
а уменьшить количество точек нельзя? Взять 5 диапазонов по три точки и каждый диапазон привести к средней Может конечно я ошибаюсьОтвет 4
Обычно лучшее решение для нахождения тренда в реальных условиях - медианное сглаживание в скользящем окне. Основания к его применению следующие: Являясь непараметрическим методом, он не накладывает ограничений на модель тренда. Метод не искажает монотонные последовательности данных и тем самым вносит минимальные искажения в выборку. Метод сглаживает кратковременные колебания выборки. Метод оптимален по отношению к кратковременным интенсивным выбросам данных.Ответ 5
По идее, можно использовать метод наименьших квадратов со скользящим окном, т.е. на n-м количестве точек выборки, последовательно сдвигая их по выборке.
Комментариев нет:
Отправить комментарий