TDNN本质上是1维卷积,而且常常是1维膨胀卷积,这样的一种结构非常注重context,也就是上下文信息,具体而言,是在frame-level的变换中,更多地利用相邻frame的信息,甚至跳过
t
−
1
,
t
+
1
t-1,t+1
t−1,t+1的frame,而去对
t
−
2
,
t
+
2
t-2,t+2
t−2,t+2的frame进行连接
在ECAPA-TDNN中,更是进一步利用了膨胀卷积,出现了
d
i
l
a
t
i
o
n
=
2
,
3
,
4
dilation=2,3,4
dilation=2,3,4的情况。此外,还引入了Res2Net,从而获得了多尺度的context,所谓多尺度,指的是各种大小的感受野
经典的ResNet结构如下左图所示,先用
k
e
r
n
e
l
-
s
i
z
e
=
1
×
1
kernel \text{-} size=1 \times 1
kernel-size=1×1的卷积运算,相当于只针对每个像素点的特征通道进行变换,而不关注该像素点的任何邻近像素,并且是降低特征通道的,所以也被叫做Bottleneck,就好像将可乐从瓶口倒出来,如果是增加特征通道,那么就叫Inverted Bottleneck
1
×
1
1\times1
1×1卷积后,会经过
3
×
3
3\times3
3×3卷积,通常不改变特征通道,如果不需要在最后加上残差连接,那么
s
t
r
i
d
e
=
2
stride=2
stride=2,特征图的分辨率会被下采样,如果需要在最后加上残差连接,那么
s
t
r
i
d
e
=
1
stride=1
stride=1,保持特征图分辨率不变
而Res2Net则是在中间的
3
×
3
3\times3
3×3卷积进行的微创新,首先将
1
×
1
1\times1
1×1卷积后的特征图,按照特征通道数进行平分,得到
s
c
a
l
e
scale
scale个相同的特征图(这里的
s
c
a
l
e
scale
scale是“尺度”的意思,Res2Net的作用就是多尺度特征,一语双关)
卷积中有一个概念叫感受野,是指当前特征图上的像素点,由之前某一个特征图在多大的分辨率下进行卷积得到的。如下图所示,
d
i
l
a
t
i
o
n
=
1
dilation=1
dilation=1的
3
×
3
3\times3
3×3卷积,其输出特征图的每一个像素点的感受野都是
3
×
3
3\times3
3×3,再进行
d
i
l
a
t
i
o
n
=
1
dilation=1
dilation=1的
3
×
3
3\times3
3×3卷积,其输出特征图的每一个像素点的感受野都是
5
×
5
5\times5
5×5
在ECAPA-TDNN中所用的Res2Net,是上述结构中的2维卷积全部换成1维卷积,采用的中间
k
=
3
k=3
k=3卷积(1维卷积,不能用
3
×
3
3\times3
3×3表示,以下都用
k
=
3
k=3
k=3代替)为膨胀卷积,并且随着网络深度增加,
d
i
l
a
t
i
o
n
dilation
dilation分别为
2
,
3
,
4
2,3,4
2,3,4。ECAPA-TDNN的结构图如下,SE-Res2Block后面括号内的参数,指的是Res2Block的中间
k
=
3
k=3
k=3卷积的参数
SE-Res2Block的内部,如下图所示,夹着Res2的两个CRB(Conv1D+ReLU+BN)结构的参数为
(
k
=
1
,
d
=
1
)
(k=1,d=1)
(k=1,d=1),中间的Res2,
s
c
a
l
e
=
8
scale=8
scale=8,之后的运算与上述Res2Net一致,不过每个
k
=
3
k=3
k=3卷积都是膨胀卷积,并且都会接ReLU和BN,从而形成Res2 Dilated Conv1D+ReLU+BN的结构
ECAPA-TDNN中对ASP进行了改进,首先将之前3个SE-Res2Block的输出,按照特征维度进行串联,假设frame-level变换中的特征维度是512,由于3个SE-Res2Block的输出维度都是
(
b
s
,
512
,
T
)
(bs,512,T)
(bs,512,T),所以串联之后是
(
b
s
,
512
∗
3
,
T
)
(bs,512*3,T)
(bs,512∗3,T),之后经过一个CRB结构,输出维度固定为
(
b
s
,
1536
,
T
)
(bs,1536,T)
(bs,1536,T),即便frame-level的特征维度是1024,该CRB的输出维度也不变。如下图所示
对特征图
(
b
s
,
1536
,
T
)
(bs,1536,T)
(bs,1536,T),记为h,按照T维度计算每个特征维度的均值和标准差,如上图的TSTP公式所示(符号
⊙
\odot
⊙表示哈达玛积,即对应项相乘,两个因子的维度必须相同,从而结果的维度与因子的维度也相同),从而T维度消失,得到的均值和标准差维度均为
(
b
s
,
1536
)
(bs,1536)
(bs,1536)
之后的操作很神奇,将均值在T维度重复堆叠T次,维度恢复为
(
b
s
,
1536
,
T
)
(bs,1536,T)
(bs,1536,T),对标准差也是堆叠,维度恢复为
(
b
s
,
1536
,
T
)
(bs,1536,T)
(bs,1536,T),接着将特征图、均值和标准差在特征维度进行串联,得到的特征图维度为
(
b
s
,
1536
∗
3
,
T
)
(bs,1536*3,T)
(bs,1536∗3,T),记为H
对H进行1维卷积,等价于上图的
W
×
H
+
b
W\times H+b
W×H+b,目的是将每个frame的特征从1536*3维降维映射到F维,F可取128,然后经过tanh激活函数,得到特征图a,维度为
(
b
s
,
F
,
T
)
(bs,F,T)
(bs,F,T)
对a进行1维卷积,等价于上图的
V
×
a
+
k
V\times a+k
V×a+k,目的是将每个frame的特征从F维恢复映射到与h相同的维度,即1536,然后在T维度,进行softmax激活,得到特征图a,维度为
(
b
s
,
1536
,
T
)
(bs,1536,T)
(bs,1536,T)
基于Attention的均值和标准差,维度都为
(
b
s
,
1536
)
(bs,1536)
(bs,1536),再将它们按照特征维度进行串联,得到ASP最终的输出,维度为
(
b
s
,
1536
∗
2
)
(bs,1536*2)
(bs,1536∗2),在ECAPA-TDNN中,ASP之后还会接一个BN
BN
这一节是讲BN(Batch Normalization)的,可能观众会感觉我太啰嗦了,怎么连BN都要讲,主要是ECAPA-TDNN是一个完全的TDNN结构,连BN都是1维的,所以怕大家一下子转不过来弯,下面主要讲解1维BN,自认对BN滚瓜烂熟的观众,可跳过本节
t
o
r
c
h
.
n
n
.
B
a
t
c
h
N
o
r
m
1
d
(
n
u
m
-
f
e
a
t
u
r
e
s
,
e
p
s
=
1
e
−
05
,
m
o
m
e
n
t
u
m
=
0.1
,
a
f
f
i
n
e
=
T
r
u
e
,
t
r
a
c
k
-
r
u
n
n
i
n
g
-
s
t
a
t
s
=
T
r
u
e
,
d
e
v
i
c
e
=
N
o
n
e
,
d
t
y
p
e
=
N
o
n
e
)
torch.nn.BatchNorm1d(num \text{-} features, eps=1e-05, momentum=0.1, affine=True, track \text{-} running \text{-} stats=True, device=None, dtype=None)
torch.nn.BatchNorm1d(num-features,eps=1e−05,momentum=0.1,affine=True,track-running-stats=True,device=None,dtype=None)
BN中的
n
u
m
-
f
e
a
t
u
r
e
s
num \text{-} features
num-features是理解BN的关键,对于图像任务,
n
u
m
-
f
e
a
t
u
r
e
s
num \text{-} features
num-features要等于输入特征图的通道数,而对于音频任务,
n
u
m
-
f
e
a
t
u
r
e
s
num \text{-} features
num-features要等于
(
b
s
,
F
,
T
)
(bs,F,T)
(bs,F,T)中的F
也就是说,BN必然是作用于图像的特征图通道,或者音频中frame的每个特征的,
n
u
m
-
f
e
a
t
u
r
e
s
num \text{-} features
num-features是告诉BN,均值和标准差,这两个向量的长度
BN计算均值和标准差的操作,与上述ASP的第一步,计算h_mean和h_std是类似的,不过计算的范围是在一个batch中
μ
B
=
1
b
s
∗
T
∑
t
b
s
∗
T
h
t
σ
B
2
=
1
b
s
∗
T
∑
t
b
s
∗
T
(
h
t
−
μ
)
2
\begin{aligned} \mu_B &= \frac{1}{bs*T} \sum_{t}^{bs*T} h_t \\ \sigma_B^2 &= \frac{1}{bs*T} \sum_{t}^{bs*T} (h_t - \mu)^2 \end{aligned}
μBσB2=bs∗T1t∑bs∗Tht=bs∗T1t∑bs∗T(ht−μ)2
得到一个batch的统计量后,BN的输出也就确定了,不过需要先将
μ
B
\mu_B
μB和
σ
B
2
\sigma_B^2
σB2重复堆叠成
(
b
s
,
F
,
T
)
(bs,F,T)
(bs,F,T)的大小,与输入BN的特征图H的维度相同,才能让其与H进行运算。在训练时,BN的输出
y
t
r
a
i
n
i
n
g
=
γ
∗
H
−
μ
B
σ
B
2
+
ϵ
+
β
y_{training}=\gamma * \frac{H-\mu_B}{\sqrt{\sigma_B^2+\epsilon}} +\beta
ytraining=γ∗σB2+ϵH−μB+β
此外,BN内部还有两个用于估计全局统计量的均值和标准差向量,在训练时,这两个向量根据每个batch的统计量进行更新,在测试时,BN会采用全局统计量对特征图进行规范化
μ
s
a
m
p
l
e
=
μ
B
σ
s
a
m
p
l
e
2
=
b
s
∗
T
b
s
∗
T
−
1
σ
B
2
μ
r
u
n
n
i
n
g
=
(
1
−
m
o
m
e
n
t
u
m
)
∗
μ
r
u
n
n
i
n
g
+
m
o
m
e
n
t
u
m
∗
μ
s
a
m
p
l
e
σ
r
u
n
n
i
n
g
2
=
(
1
−
m
o
m
e
n
t
u
m
)
∗
σ
r
u
n
n
i
n
g
2
+
m
o
m
e
n
t
u
m
∗
σ
s
a
m
p
l
e
2
y
e
v
a
l
u
a
t
i
n
g
=
γ
∗
H
−
μ
r
u
n
n
i
n
g
σ
r
u
n
n
i
n
g
2
+
ϵ
+
β
\begin{aligned} \mu_{sample}&=\mu_B \\ \sigma_{sample}^2&=\frac{bs*T}{bs*T-1} \sigma_B^2 \\ \mu_{running}&=(1-momentum)*\mu_{running}+momentum*\mu_{sample} \\ \sigma_{running}^2&=(1-momentum)*\sigma_{running}^2+momentum*\sigma_{sample}^2 \\ y_{evaluating}&=\gamma * \frac{H-\mu_{running}}{\sqrt{\sigma_{running}^2+\epsilon}} +\beta \end{aligned}
μsampleσsample2μrunningσrunning2yevaluating=μB=bs∗T−1bs∗TσB2=(1−momentum)∗μrunning+momentum∗μsample=(1−momentum)∗σrunning2+momentum∗σsample2=γ∗σrunning2+ϵH−μrunning+β
其中
下标
r
u
n
n
i
n
g
running
running表示采用移动平均(running average)的方法对全局统计量进行估计
系数
m
o
m
e
n
t
u
m
momentum
momentum是对当前batch的统计量的权重,可取
0.1
0.1
0.1