Переключение импульсной реакции в свертке

26

Во время свертки на сигнале, почему мы должны перевернуть импульсную реакцию во время процесса?

winuall
источник
5
Вторая половина этого ответа может помочь вам понять.
Дилип Сарвате
3
В дополнение к чтению отличного ответа @ DilipSarwate, это хорошее упражнение - взять лист бумаги и графически рассчитать выход системы LTI, добавив сдвинутые по времени и масштабированные версии импульсного отклика.
Дев
1
Обратите внимание, что вы можете перебросить любой аргумент - результат тот же.
Вакья

Ответы:

29

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

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

Разобьем входной сигнал x на сумму масштабированных единичных импульсных сигналов. Отклик системы на единичный импульсный сигнал , 0, 0, 1, 0, 0, является импульсным откликом или импульсным откликом

h[0], h[1],, h[n],
и т. Д. свойство масштабирования единственного входного значения x[0]или, если вы предпочитаете
x[0](, 0, 0, 1, 0, 0,)= 0, 0, x[0], 0, 0,
создает ответ
x[0]h[0],  x[0]h[1],,  x[0]h[n],

x[1]

x[1](, 0, 0, 0, 1, 0,)= 0, 0, 0, x[1], 0,
0,x[1]h[0],  x[1]h[1],,  x[1]h[n1],x[1]h[n]
x[1]
time012nn+1x[0]x[0]h[0]x[0]h[1]x[0]h[2]x[0]h[n]x[0]h[n+1]x[1]0x[1]h[0]x[1]h[1]x[1]h[n1]x[1]h[n]x[2]00x[2]h[0]x[2]h[n2]x[2]h[n1]x[m]000x[m]h[nm]x[m]h[nm+1]
yx

n

n

y[n]=x[0]h[n]+x[1]h[n1]+x[2]h[n2]++x[m]h[nm]+=m=0x[m]h[nm],
y[n]=x[n]h[0]+x[n1]h[1]+x[n2]h[2]++x[0]h[n]+=m=0x[nm]h[m],
n
Дилип Сарватэ
источник
4

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

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

#include <stdio.h>

const int Nx = 5; 
const int x[Nx] = {1, 0, 0, 0, 2};
const int Ny = 3; 
const int y[Ny] = {1, 2, 3};
const int Nz = Nx+Ny-1;
int z[Nz];

void convolve_scatter() { // z = x conv y
  for (int k = 0; k < Nz; k++) {
    z[k] = 0;
  }
  for (int n = 0; n < Nx; n++) {
    for (int m = 0; m < Ny; m++) {
      z[n+m] += x[n]*y[m]; // No IR reversal
    }
  }
}

void convolve_gather() { // z = x conv y
  for (int k = 0; k < Nz; k++) {
    int accu = 0;
    for (int m = 0; m < Ny; m++) {
      int n = k+m - Ny + 1;
      if (n >= 0 && n < Nx) {
        accu += x[n]*y[Ny-m-1]; // IR reversed here
      }
    }
    z[k] = accu;
  }
}

void print() {
  for (int k = 0; k < Nz; k++) {
    printf("%d ", z[k]);
  }
  printf("\n");
}

int main() {
  convolve_scatter();
  print();
  convolve_gather();
  print();
}

Это свертывает последовательности:

1 0 0 0 2
1 2 3

и используя оба метода свертки:

1 2 3 0 2 4 6

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

Олли Нимитало
источник
Интересный! Так какой же окончательный вывод мне интересно посмотреть
Failed Scientist
Ваш архитектурный интерес интересен. Учитывая имеющиеся кэша, инструкции SIMD (SSE, AVX) и многоядерные архитектуры, то рассеянный метод кажется более подходящими для параллельных вычислений? Но я не провел детальный анализ, хотя ...
Fat32
@ Fat32 я тоже! Вы имеете в виду, что накопление в сборе свертки может стать узким местом с несколькими ядрами, работающими на умножения? Этого можно избежать, предоставив каждому ядру свой собственный аккумулятор и суммируя их в конце. Я думаю, что эти издержки не будут сильно сравниваться с дополнительной записью памяти в разбросанной свертке.
Олли Нимитало,
На самом деле меня больше беспокоит эффективность разбросанной формы, чем узкое место форм сбора. Мои текущие коды C-фильтрации (скорее всего) находятся в форме сбора, но когда речь идет о кодах ASM, я склонен записывать их в расширениях SIMD SSE, которые более подходит для рассеянного вида. Однако я должен обновить свои теты :-))) Оперативный ввод-вывод, безусловно, является проблемой по сравнению с накоплением регистров. И, наверное, мне не хватает штрафа за повторную память IO ...
Fat32
Кто-нибудь знает лучшие слова, чем рассеяние и сбор? Я не уверен, зарезервированы ли они для редких ядер свертки.
Олли Нимитало
3

Это только «перевернуто» для точечных вычислений.

@Dilip объясняет, что представляет собой интеграл / суммирование свертки, но чтобы объяснить, почему одна из двух входных функций (часто h(t)) переключается для целей вычисления, рассмотрим систему с дискретным временем с входным x[n]и импульсным откликом h[n]:

  • Вы можете взять свою входную функцию x[n]и для каждой ненулевой выборки * x[n]рассчитать масштабированный импульсный отклик от выборки nи далее до тех пор, пока сдвиг по времени не h[n]уменьшится до нуля (предполагая причинность h[n]). Это не будет включать в себя не «листать» (точнее «обращения времени») : либо x[n]или h[n]. Тем не менее, в конце вы должны добавить / наложить все эти масштабированные + смещенные «эхо» импульсной характеристики для каждого ненулевого значения x[n].

  • x[0]k

    k=x[k]h[nk]
    h[n]x[n], который есть x[0]h[0]. Затем увеличение kна единицу сместится h[n]на один шаг вправо, так что h[n]вторая запись ( h[1]) с обращенной по времени теперь будет лежать поверх x[0], ожидая умножения. Это даст желаемый вклад x[0]h[1]во времени n=1, так же, как это было бы сделано в предыдущем методе.

x[n]

x[n]=0
h[n]y[n]
азбука
источник
n
@Dilip. Все n одинаковы, за исключением «сдвинутого по времени h [n]», что подразумевает «h [nk]», где «k» - это константа, используемая для сдвига импульсной характеристики в нужную точку сигнала x [n ]. то есть: h [n-2] для расчета отклика на сигнал в точке x [2].
а
3

При индексе c [n] свертка a [n] и b [n] такова, что:

«c [n] является суммой всех произведений (a [k] b [m]), таких что m + k = n», поэтому m = n - k или k = n - m, что означает, что одна из последовательностей должен быть перевернут.

Теперь, почему свертка ведет себя так в первую очередь? Из-за его связи с умножением многочленов.

Умножение двух полиномов приводит к новому полиному с коэффициентами. Коэффициенты полинома произведения определяют операцию свертки. Теперь при обработке сигналов передаточные функции - преобразования Лапласа или z-преобразования - являются этими полиномами, причем каждый коэффициент соответствует разной временной задержке. Сопоставление коэффициентов произведения и мультипликатов приводит к тому, что «умножение в одном представлении соответствует свертке в преобразованном представлении».

введите описание изображения здесь

Махеш Шастри
источник
0

Во время свертки не должно происходить никакого «переворота» импульсного отклика ...

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

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

learnvst
источник
3
y(t)=x(τ)h(tτ)dτh(t)x(t)h(t)=h(t)x(t)
@JasonR Ах, блин! Иногда трудно понять, к чему идет этот вопрос. Ижак, как только ты поймешь ответ, который искал, ты поймешь, куда я шел. Игнорируйте меня сейчас!
Learnvst
0

f(τ)g(tτ)dτ
t1+t2=tf(t1)g(t2)dt1dt2
fgt

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

t1,t2f(t1)g(t2)δ(tt1t2)dt1dt2
t1f(t1)dt1t2g(t2)δ(tt1t2)dt2
t1f(t1)dt1g(tt1)
который является оригинальным интегралом с небольшим переименованием.

источник