произвольно взвешенное скользящее среднее (фильтры низких и высоких частот) - PullRequest
0 голосов
/ 29 января 2019

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

/ this is not q
y[3] = -3*x[0] - x[1] + x[2] + 3*x[3]
y[4] = -3*x[1] - x[2] + x[3] + 3*x[4]
. . .

Я стремлюсь к переменной длине окна ивесовые коэффициенты.Как я могу сделать это в д?Я знаю о mavg и обработке сигналов в q и скользящей сумме qidiom

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

Ответы [ 3 ]

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

Если ваш входной список не большой, вы можете использовать метод, упомянутый здесь: https://code.kx.com/q/cookbook/programming-idioms/#how-do-i-apply-a-function-to-a-sequence-sliding-window

Использует наречие 'scan'.Поскольку этот процесс создает несколько списков, которые могут быть неэффективными для больших списков.

Другое решение, использующее сканирование:

 q)f:{sum y*next\[z;x]} / x-input list, y-weights, z-window size-1
 q)f[x;-3 -1 1 3;3]

Эта функция также создает несколько списков, поэтому, опять же, может быть не очень эффективна для большихlists.

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

 q) f:{[l;w;i]sum w*l i+til 4} / w- weight, l- input list, i-current index
 q) f[x;-3 -1 1 3]@'til count x

Это очень простая функция.Вы можете добавить больше переменных в соответствии с вашими требованиями.

0 голосов
/ 26 июля 2019

Возможно, это немного устарело, но я подумал, что смогу взвесить. В прошлом году я написал статью об обработке сигналов, которая может иметь определенную ценность.Работая исключительно в KDB, в зависимости от используемых вами размеров сигналов, вы увидите гораздо лучшую производительность благодаря свертке на основе FFT между ядром / окном и сигналом.

Однако я написал только простое БПФ для radix-2, хотя в моем репозитории github у меня есть непроверенная работа для более гибкого алгоритма Блюштейна, который позволит использовать переменную длину сигнала.https://github.com/callumjbiggs/q-signals/blob/master/signal.q

Если вы хотите пойти по пути выполнения полной ручной свертки с помощью скользящей суммы, то лучшим способом будет разбить ее на блоки, равные размеру ядра / окна (который былосновываясь на какой-то работе, которую Артур У сделал много лет назад)

q)vec:10000?100.0
q)weights:30?1.0
q)wsize:count weights
q)(weights$(((wsize-1)#0.0),vec)til[wsize]+) each til count v
32.5931 75.54583 100.4159 124.0514 105.3138 117.532 179.2236 200.5387 232.168.

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

Примерно так будет работать для параметризуемых коэффициентов:

q)x:10+sums -1+1000?2f
q)f:{sum x*til[count x]xprev\:y}
q)f[3 1 -1 -3] x
0n 0n 0n -2.385585 1.423811 2.771659 2.065391 -0.951051 -1.323334 -0.8614857 ..

Отдельные случаи можно сделать немного быстрее (запуск 0 xprev не самая лучшая вещь)

q)g:{prev[deltas x]+3*x-3 xprev x}
q)g[x]~f[3 1 -1 -3]x
1b
q)\t:100000 f[3 1 1 -3] x
4612
q)\t:100000 g x
1791

Естьkx белая бумага обработки сигналов в q, если эта область вас интересует: https://code.kx.com/q/wp/signal-processing/

...