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


26

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


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

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

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

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


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)
который является оригинальным интегралом с небольшим переименованием.
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.