#1 楼
改编自对另一个问题的回答(如评论中所述),希望该问题不会被社区Wiki作为头号问题之一反复抛出。...线性
(时不变)系统没有脉冲响应的“翻转”。
线性时不变系统的输出是标度和时间之和。
脉冲响应的延迟版本,而不是“翻转”脉冲响应。
我们将输入信号$ x $分解为缩放后的和单位脉冲信号。系统对单位脉冲信号的响应
$ \ cdots,〜0,〜0,〜1,〜0,〜0,\ cdots $是脉冲响应或脉冲响应
$ h [0],〜h [1],\ cdots,〜h [n],\ cdots $$
,因此,通过scale属性,单个输入值$ x [0] $,
或者,如果您更喜欢
$$ x [0](\ cdots,〜0,〜0,〜1,〜0,〜0,\ cdots)
= \ cdots〜0,〜0, 〜x [0],〜0,〜0,\ cdots $$
创建响应
$$ x [0] h [0],~~ x [0] h [1],\ cdots,~~ x [0] h [n],\ cdots $$
类似地,单个输入值$ x [1] $或创建
$$ x [1]( \ cdots,〜0,〜0,〜0,〜1,〜0,\ cdots)
= \ cdots〜0,〜0,〜0,〜x [1],〜0,\ cdots $$
创建响应
$$ 0,x [1] h [0],~~ x [1] h [1],\ cdots,~~ x [1] h [n-1], x [1] h [n] \ cdots $$
注意对$ x [1] $的响应延迟。我们可以按照这种方式进一步
,但是最好切换到更加表格化的形式
,并及时显示各种输出。我们有
$$ \ begin {array} {l | l | l | l | l | l | l | l}
\ text {time} \ to&0&1&2&\ cdots&n &n + 1&\ cdots \\
\ hline
x [0]&x [0] h [0]&x [0] h [1]&x [0] h [2]&\ cdots&x [0] h [n]&x [0] h [n + 1]&\ cdots \\
\ hline
x [1]&0&x [1] h [0] &x [1] h [1]&\ cdots&x [1] h [n-1]&x [1] h [n]&\ cdots \\
\ hline
x [2]& 0&0&x [2] h [0]&\ cdots&x [2] h [n-2]&x [2] h [n-1]&\ cdots \\
\ hline
\ vdots&\ vdots&\ vdots&\ vdots&\ ddots&\\
\ hline
x [m]&0&0&0&\ cdots&x [m] h [nm]&x [m] h [n-m + 1]和\ cdots \\
\ hline
\ vdots&\ vdots&\ vdots&\ vdots&\ ddots
\ end {array} $ $
上面数组中的行恰好是脉冲响应的缩放版本和
延迟版本,它们与输入信号$ x $的响应$ y $相加。但是,如果您问一个更具体的问题,例如
时间$ n $的输出是什么?通过汇总第$ n $列以得到
$$ \ begin {align *}
y [n]&= x [0] h [n] + x [1] h [n- 1] + x [2] h [n-2] + \ cdots + x [m] h [nm] + \ cdots \\
&= \ sum_ {m = 0} ^ {\ infty} x [ m] h [nm],
\ end {align *} $$
心爱的卷积公式使世代学生迷惑。 >或时间倒退。但是,人们似乎忘记了
的是,相反,我们可以写成
$$ \ begin {align *}
y [n]&= x [n] h [0] + x [n-1] h [1] + x [n-2] h [2] + \ cdots + x [0] h [n] + \ cdots \\
&= \ sum_ {m = 0} ^ {\ infty} x [nm] h [m],
\ end {align *} $$
,因此输入似乎“翻转”或向后运行
换句话说,是人类
使用卷积公式计算时间$ n $的响应时翻转脉冲响应(或输入),但是
/>系统本身不执行任何操作。
#2 楼
这是一个C / C ++示例,该示例显示了可以进行卷积而无需反向使用脉冲响应。如果检查convolve_scatter()
函数,则任何地方都不会取反变量。这是散射卷积,其中每个输入样本使用脉冲响应给出的权重分散(求和)到内存中的多个输出样本。这很浪费,因为需要对输出样本进行多次读取和写入。通常,卷积是通过收集卷积来完成的,如
convolve_gather()
所示。在这种方法中,通过以反向脉冲响应作为权重,将每个输出样本收集(汇总)到其输入样本中,从而分别形成每个输出样本。完成后,输出样本驻留在用作累加器的处理器寄存器中。通常,这是选择的方法,因为每个过滤后的样本只有一个存储器写操作。现在,输入的内存读取次数更多,但是在散射方法中,输出的内存读取次数却很少。 br /> #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();
}
,同时使用两种卷积方法输出:
,除非过滤器是随时间变化的,否则在两种情况下这两种方法将产生不同的结果,并且一种方法可能更合适。
评论
$ \ begingroup $
有趣!那么我有兴趣看到的最后结论是什么
$ \ endgroup $
–失败的科学家
17年8月23日在15:22
$ \ begingroup $
您对架构的关注很有趣。考虑到可用的缓存,SIMD指令(SSE,AVX)和多核体系结构,分散的方法似乎更适合于并行计算?但是我还没有进行详细的分析...
$ \ endgroup $
– Fat32
17年8月23日在19:35
$ \ begingroup $
@ Fat32我也没有!您是说,在收集卷积中积累可能会成为多个内核进行乘法运算的瓶颈?通过为每个内核分配自己的累加器并在末尾求和,可以缓解这种情况。我认为,与分散卷积中的其他内存写入相比,此开销不会太大。
$ \ endgroup $
–奥利·尼米塔洛(Olli Niemitalo)
17年8月23日在21:10
$ \ begingroup $
实际上我比分散表单的瓶颈更关心分散表单的效率。我当前的C过滤代码(很可能是在收集表单中),但是当涉及到ASM代码时,我倾向于用SIMD SSE编写扩展更适合分散形式。我必须更新自己的tets,但是:-)))与寄存器累积相比,内存IO绝对是一个问题。可能我错过了重复存储IO的代价...
$ \ endgroup $
– Fat32
17年8月23日在21:32
$ \ begingroup $
有谁比散乱和聚集更好的语言?我不确定这些是否保留用于稀疏卷积内核。
$ \ endgroup $
–奥利·尼米塔洛(Olli Niemitalo)
17年8月24日在5:47
#3 楼
它只是“翻转”用于逐点计算。具有输入h(t)
和脉冲响应x[n]
的离散时间系统:您可以使用输入函数h[n]
,并对每个非零*样本x[n]
从样本x[n]
计算缩放的脉冲响应直到时移的n
消失为零(假设因果h[n]
)。这不会涉及h[n]
或x[n]
的“翻转”(或更准确地说是“时间反转”)。但是,最后,您必须为每个非零h[n]
添加/叠加脉冲响应的所有这些按比例缩放和移位的“回声”。为方便起见,您可以对与时间起点(通常为0),而不是{乘,乘,...,加,加,...},而是进行{乘,加,乘,加,...}计算。这将导致相同的输出信号,因为它将执行完全相同的乘法和加法运算。例如,考虑时间0
x[n]
处非零输入信号的输出贡献。当方程式$$ \ sum_ {k =-\ infty} ^ {\ infty} x [k] h [nk] $$的x[0]
= 0时,脉冲响应k
将只是时间反转,而不会发生偏移, h[n]
的第一个样本响应,即x[n]
。然后,将x[0]h[0]
加1会将k
移至正确的一个时间步长,这样,经过时间反转的h[n]
的第二个条目(h[n]
)现在将放在h[1]
的顶部,等待相乘。就像在以前的方法中所做的那样,这将在时间x[0]
处产生期望的贡献x[0]h[1]
。*我说的是非零
n=1
,因为$$ \ forall x [n] = 0 $$脉冲响应x[n]
被缩放为零,因此对最终输出h[n]
没有任何贡献。评论
$ \ begingroup $
“您可以使用输入函数x [n],对于每个非零*样本x [n],从样本n开始计算缩放的脉冲响应,直到时移h [n]下降到零(假设是因果h [n])”这句话中出现的五个$ n $是全部相同的数字还是不同?
$ \ endgroup $
– Dilip Sarwate
13年1月28日在4:21
$ \ begingroup $
@Dilip。除“时移h [n]”(表示“ h [nk]”外)外,所有n均相同,其中“ k”是用于将脉冲响应移至信号x [n的所需点]的常数]。即:h [n-2]用于计算对x [2]处信号的响应。
$ \ endgroup $
– abc
13年2月24日在17:41
#4 楼
在索引c [n]处,a [n]和b [n]的卷积使得:“ c [n]是所有乘积(a [k] b [ m]),这样m + k = n,“所以m = n-k或k = n-m,这意味着必须翻转序列之一。
现在为什么卷积表现首先这样吗?由于它与乘法多项式有关。
将两个多项式相乘会导致一个新的具有系数的多项式。乘积多项式的系数定义了卷积运算。现在,在信号处理中,这些多项式是传递函数-拉普拉斯变换或z变换,每个系数对应于不同的时间延迟。将乘积和被乘数的系数相匹配会导致以下事实:“一个表示形式的乘法对应于变换表示形式中的卷积”。
#5 楼
在卷积过程中,根本不需要发生脉冲响应的“翻转” ...但是,如果要防止任何相位改变,可以将信号与脉冲响应进行卷积然后反转
在脱机处理中,您可以像在第一次卷积后一样轻松地反转信号以获得相同的结论(如评论所示)。 br />
评论
$ \ begingroup $
他指的是卷积积分中脉冲响应的“时间反转”:$ y(t)= \ int _ {-\ infty} ^ {\ infty} x(\ tau)h(t- \ tau )d \ tau $。正如其他人已经指出的那样,您不必翻转脉冲响应$ h(t)$;您可以翻转任意一项(即$ x(t)* h(t)= h(t)* x(t)$)。我认为他正在试图弄清楚“翻转和滑动”动作的定性解释是什么。
$ \ endgroup $
–Jason R
2012年11月29日,0:55
$ \ begingroup $
@JasonR啊,糟糕!有时很难看到问题的根源。伊扎克,一旦您了解了所需的答案,您就会了解我的去向。现在忽略我!
$ \ endgroup $
–learnvst
2012年11月29日下午3:08
#6 楼
只需写卷积积分$$ \ int _ {-\ infty} ^ \ infty f(\ tau)g(t- \ tau)d \ tau $$而不是挥手地
$$ \ iint \ nolimits_ {t_1 + t_2 = t} f(t_1)\,g(t_2)\,dt_1 \,dt_2 $$
即将$ f $和$ g $的乘积积分到所有对$ t $。
现在,手挥形式清楚地显示了此处涉及的对称性,并且不涉及“翻转”。但是,将其转换为适当的一维积分需要将两个参数之一作为实际积分变量。要么就是找到不涉及手工挥舞的刚性对称形式。后者比较棘手。基本上,您必须重新进行归一化处理(使用Dirac delta函数/分布时),例如
$$ \ iint_ {t_1,t_2} f(t_1)\,g(t_2)\, \ delta(t-t_1-t_2)\,dt_1 \,dt_2 $$
如果以一种方式重新排列,则会得到
$$ \ int_ {t_1} f(t_1)\,dt_1 \ int_ {t_2} g(t_2)\ delta(t-t_1-t_2)\,dt_2 $$
,并从Dirac运算符的筛选属性
$$ \ int_ {t_1} f(t_1) \,dt_1 \,g(t-t_1)$$
是原始积分,需要重命名。
评论
该答案的后半部分可能会帮助您理解。除了阅读@DilipSarwate的好答案外,这是一个不错的练习,它可以通过加总时移和按比例缩放的脉冲响应来记录一张纸并以图形方式计算LTI系统的输出。
请注意,您可以翻转任一参数-结果相同。