畳み込みにおけるインパルス応答の反転


26

信号の畳み込み中に、プロセス中にインパルス応答を反転する必要があるのはなぜですか?


5
この答えの後半はあなたが理解するのに役立つかもしれません。
ディリップサルワテ

3
@DilipSarwateの素晴らしい答えを読むことに加えて、紙を取り、インパルス応答のタイムシフトおよびスケーリングされたバージョンを加算することにより、LTIシステムの出力をグラフィカルに計算することは良い練習です。
DEVE

1
どちらの引数も反転できることに注意してください-結果は同じです。
ワクジャ

回答:


29

コミュニティWikiが上位の質問の1つとしてこの質問が繰り返し表示されないことを期待して、別の質問(コメントで述べられている)への回答から改作されました。

線形(時不変)システムによるインパルス応答の「反転」はありません。線形時不変システムの出力は、「反転」インパルス応答ではなく、スケーリングされたバージョンと時間遅延されたバージョンのインパルス応答の合計です。

入力信号xをスケーリングされた単位パルス信号の合計に分解します。システムユニットパルス信号に応答し , 0, 0, 1, 0, 0,あるインパルス応答またはパルス応答

h[0], h[1],, h[n],
などによってスケーリングプロパティ単一の入力値 x[0]または、 は応答 X [ 0 ] H [ 0 ] X [ 0 ] 、H [ 1 ] x [ 0 ] h [
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 ] 0 0 0 1 0 = 0 0 0 X [ 1 ] 0 0 X [ 1 ] H [ 0 ] x [ 1 ] h [ 1 ] x[1]

x[1](, 0, 0, 0, 1, 0,)= 0, 0, 0, x[1], 0,
x [ 1 ] 時間0 1 2 n n + 1 x [ 0 ] x [ 0 ] h [ 0 ] x [ 0 ] h [ 1 ] x [ 0 ] h [
0,x[1]h[0],  x[1]h[1],,  x[1]h[n1],x[1]h[n]
x[1] YX
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]
\ ddots \ end {array} 上記の配列の行は、入力信号に対する応答を合計するインパルス応答の正確にスケーリングおよび遅延されたバージョンです。yx しかし、次のようなより具体的な質問をすると

時間での出力は何ですか?n

その後、番目の列を合計して インパルス応答が「ひっくり返る」ように見える、または時間をさかのぼって実行されるため、世代を混乱させる最愛の畳み込み式。しかし、人々が忘れているように思われるのは、代わりに これにより、入力が「反転」または時間的に逆方向に実行されるようになります。言い換えれば、それは人間ですy [ 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],
nは
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()。この方法では、重みとして逆インパルス応答を使用して、入力サンプルを収集(合計)することにより、各出力サンプルが個別に形成されます。出力サンプルは、これが行われている間、アキュムレータとして使用されるプロセッサのレジスタにあります。これは通常、選択された方法です。フィルター処理されたサンプルごとに1つのメモリ書き込みのみが行われるためです。現在、入力のメモリ読み取りが増えていますが、スキャッタリングメソッドの出力のメモリ読み取りと同数だけです。

#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

フィルターが時変でない限り、散乱法を使用している人を想像することはできません。


面白い!最終的な結論は何
失敗した科学者

あなたの建築上の関心は興味深いものです。利用可能なキャッシュ、SIMD命令(SSE、AVX)、およびマルチコアアーキテクチャを考慮すると、分散方式は並列計算により適しているように思えますか?しかし、詳細な分析は行っていません
...-Fat32

@ Fat32私も!コンボリューションの収集における蓄積が、乗算で動作する複数のコアのボトルネックになる可能性があるということですか?これは、各コアに独自のアキュムレーターを与え、最後にそれらを合計することで軽減できます。このオーバーヘッドは、散在した畳み込みでの追加のメモリ書き込みに比べてそれほど大きくないと思います。
オリニーミタロ

実際、私は収集フォームのボトルネックよりも分散フォームの効率に関心がありました。現在のCフィルタリングコードは(ほとんどの場合)収集フォームにありますが、ASMコードに関しては、SIMD SSE拡張機能で記述する傾向があります。散らばった形に適しています。テットを更新する必要がありますが、:-)))メモリIOは、レジスタの蓄積と比較して間違いなく問題です。おそらく、メモリIOを繰り返すことによるペナルティを失っています
...-Fat32

誰もがばらばらになって集まるよりも良い言葉を知っていますか?これらがまばらな畳み込みカーネル用に予約されているかどうかはわかりません。
オッリNiemitalo

3

これは、ポイントごとの計算に対してのみ「反転」されます。

@Dilipは畳み込み積分/総和が何を表すかを説明しますが、2つの入力関数の1つ(多くの場合h(t))が計算目的で反転する理由を説明するために、入力x[n]およびインパルス応答を持つ離散時間システムを考えますh[n]

  • あなたは可能性があなたの入力機能を取りx[n]、そして各非ゼロのための*サンプルx[n]試料からのインパルス応答をスケール計算nし、タイムシフトまでにh[n](因果を想定し、ゼロまでダイスh[n])。これは、どちらかのNO「反転」(またはより正確に「時間反転」)を伴わないだろうx[n]h[n]。ただし、最後に、各非ゼロのインパルス応答のこれらのスケーリングされた+シフトされた「エコー」をすべて追加/重ね合わせる必要がありますx[n]

  • x[0]k

    k=x[k]h[nk]
    h[n]x[n]、ですx[0]h[0]。次に、k1 ずつインクリメントするh[n]と、右の1つのタイムステップにシフトし、時間反転されたh[n]sの2番目のエントリ(h[1])がの上に置かれx[0]、乗算を待機します。これにより、以前の方法で行われていたのと同じようにx[0]h[1]、time n=1に目的の貢献が得られます。

x[n]

x[n]=0
h[n]y[n]

n

@Dilip。「タイムシフトされたh [n]」を除くすべてのnは同じです。「h [nk]」を意味します。「k」はインパルス応答を信号x [nの希望するポイントにシフトするために使用される定数です。 ]。すなわち、x [2]の信号に対する応答を計算するh [n-2]。
abc

3

インデックスc [n]では、a [n]とb [n]の畳み込みは次のようになります。

「c [n]はm + k = nになるようなすべての積の合計(a [k] b [m])なので、m = n-kまたはk = n-mです。裏返す必要があります。

そもそもなぜ畳み込みがこのように振る舞うのでしょうか?乗算多項式との接続のため。

2つの多項式を乗算すると、係数のある新しい多項式が生成されます。積多項式の係数は、畳み込みの動作を定義します。現在、信号処理では、伝達関数-ラプラス変換またはz変換はこれらの多項式であり、各係数は異なる時間遅延に対応しています。積と被乗数の係数を一致させると、「1つの表現の乗算は変換された表現の畳み込みに対応する」という事実が得られます。

ここに画像の説明を入力してください


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)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.