赞
踩
代码:https://github.com/DURUII/Course-Voiceprint-Repo-1.0
时延神经网络(TDNNs)常用于声纹识别领域,例如著名的X-VECTOR基础结构就是TDNNs;它可以视作一维卷积神经网络1(1-d CNNs),甚至有人认为TDNNs是CNNs/LeNet-5的早期版本。
计算机视觉盛行的如今,数字图像处理中二维卷积(空域滤波/模版运算/互相关运算2)对于我们而言也不再陌生,无非就是中心数值等于按元素相乘后再相加嘛。
可是,到底如何理解一维卷积?它和二维卷积又有什么联系?
不妨通过实验,一探究竟。
首先,我们暂时忽略通道。假定输入为
[
1
,
2
,
−
1
,
1
,
−
3
]
[1, 2, -1, 1, -3]
[1,2,−1,1,−3],核函数为
[
1
,
0
,
−
1
]
[1, 0, -1]
[1,0,−1](卷积核是一维的,移动方向也自然是一维的),如果卷积核在输入向量上移动,请问结果是多少呢?可以看看我有没有算错。
顺带一提,这里输入是一行五列的矩阵。不过换一个角度,我们也可以认为每次输入的是3帧信息,并按照某种权重加和汇入1个新帧。
这里的3是卷积核尺寸( k e r n e l s i z e kernel\ size kernel size),从共享参数的全连接输入的角度说,3也是上下文所涵盖的范围, ( n − 1 , n + 1 ) o r { n − 1 , n , n + 1 } (n-1,n+1) \ or \ \{n-1, n, n+1\} (n−1,n+1) or {n−1,n,n+1}。
# 输入 import torch.nn as nn from torch.nn import Parameter import torch.nn.functional as F import torch import numpy as np import math input = torch.tensor([ [[1, 2, -1, 1, -3], ] ], dtype=torch.float) conv1d = nn.Conv1d(in_channels=1, out_channels=1, kernel_size=3, stride=1, padding=0, dilation=1, bias=False, padding_mode='zeros') # 卷积核 conv1d.weight = nn.Parameter(torch.tensor([ [[1., 0, -1], ] ])) # 输出 conv1d(input)
tensor([[[2., 1., 2.]]], grad_fn=<ConvolutionBackward0>)
但是,一般说来,TDNNs输入的声学特征并不是一个向量,而是一个矩阵,横轴(宽度)与时间有关【不固定】,纵轴(高度)和频率相关【固定】,所以它有时也被称为时频谱图(Spectrogram)。
图片来自MathWorks。
你还可以在 CHROME MUSIC LAB:SPECTROGRAM 上,亲自动手玩玩可视化自己的或自然的声音。
当然,上文所指的广义的时频谱也分很多种(常见的有MFCC、MFBank、MelSpec等),对应各种不同的处理方式(例如,模拟人耳对频率、声强的非线性,平稳信号等),不过它们一般都要经历短时傅里叶变换(分帧、加窗、离散傅里叶变换)。
我们暂时忽略输出通道。从一维卷积的视角说,[频率,时间] 应当被视作 [通道数,输入长度],即每个通道各有一个卷积核或一组共享权重,每个通道独立计算再把各个通道的结果相加3。
假定输入为双通道(例如表示高频和低频) [ [ 1 , 2 , − 1 , 1 , − 3 ] , [ 3 , 1 , 0 , − 1 , 2 ] ] [[1, 2, -1, 1, -3],[3, 1, 0, -1, 2]] [[1,2,−1,1,−3],[3,1,0,−1,2]]各通道上的核函数分别为 [ 1 , 0 , − 1 ] [1, 0, -1] [1,0,−1]和 [ 0.5 , 0 , 0.5 ] [0.5, 0, 0.5] [0.5,0,0.5],请问这次结果又是多少呢?相信你肯定比我算的快。
# 输入 input = torch.tensor([ [[1, 2, -1, 1, -3], [3, 1, 0, -1, 2]] ], dtype=torch.float) conv1d = nn.Conv1d(in_channels=2, out_channels=1, kernel_size=3, stride=1, padding=0, dilation=1, bias=False, padding_mode='zeros') # 卷积核 conv1d.weight = nn.Parameter(torch.tensor([ [[1., 0, -1], [0.5, 0, 0.5]], ])) # 输出 conv1d(input)
tensor([[[3.5000, 1.0000, 3.0000]]], grad_fn=<ConvolutionBackward0>)
最后,该如何理解输出通道呢?其实无非就是把单输出通道的那一份卷积核,扩增几倍而已。例如,仍然假定输入为双通道 [ [ 1 , 2 , − 1 , 1 , − 3 ] , [ 3 , 1 , 0 , − 1 , 2 ] ] [[1, 2, -1, 1, -3],[3, 1, 0, -1, 2]] [[1,2,−1,1,−3],[3,1,0,−1,2]]不过此时我们考虑简化的双输出通道的情况:
第一份输出:各输入通道上的核函数分别为 [ 1 , 0 , − 1 ] [1, 0, -1] [1,0,−1]和 [ 0.5 , 0 , 0.5 ] [0.5, 0, 0.5] [0.5,0,0.5];
第二份输出:各输入通道上的核函数仍然是 [ 1 , 0 , − 1 ] [1, 0, -1] [1,0,−1]和 [ 0.5 , 0 , 0.5 ] [0.5, 0, 0.5] [0.5,0,0.5]。
那么,我们就可以得到双倍的输出。
# 输入 input = torch.tensor([ [[1, 2, -1, 1, -3], [3, 1, 0, -1, 2]] ], dtype=torch.float) conv1d = nn.Conv1d(in_channels=2, out_channels=2, kernel_size=3, stride=1, padding=0, dilation=1, bias=False, padding_mode='zeros') # 卷积核 conv1d.weight = nn.Parameter(torch.tensor([ [[1., 0, -1], [0.5, 0, 0.5]], [[1., 0, -1], [0.5, 0, 0.5]], ])) # 输出 conv1d(input)
tensor([[[3.5000, 1.0000, 3.0000],
[3.5000, 1.0000, 3.0000]]], grad_fn=<ConvolutionBackward0>)
其实,如果将各个通道的一维卷积核拼接起来:所谓的一维卷积在各通道上的加和,完全可以用二维卷积核
[
c
h
a
n
n
e
l
s
,
k
e
r
n
e
l
_
s
i
z
e
]
[channels, kernel\_ size]
[channels,kernel_size]按元素相乘后再相加理解。
所以,许多博主所认为的一维卷积不代表卷积核是一维的,只代表卷积核的移动方向是一维的这种说法,从某种角度说,也有一定的道理。
不过值得注意的是,Pytorch中Conv1d和Conv2d输入维度不一样。
例如,
一维卷积
[
b
a
t
c
h
,
c
h
a
n
n
e
l
s
,
l
e
n
g
t
h
]
[batch, channels, length]
[batch,channels,length],
二维卷积
[
b
a
t
c
h
,
c
h
a
n
n
e
l
s
,
h
e
i
g
h
t
,
w
i
d
t
h
]
[batch, channels, height, width]
[batch,channels,height,width]。
# 输入 input = torch.tensor([ [[1, 2, -1, 1, -3], [3, 1, 0, -1, 2]] ], dtype=torch.float) input=input.unsqueeze(dim=1) conv2d = nn.Conv2d(in_channels=1, out_channels=2, kernel_size=(input.shape[2],3), stride=1, padding=0, dilation=1, bias=False, padding_mode='zeros') # 卷积核 conv2d.weight = nn.Parameter(torch.tensor([ [[[1., 0, -1], [0.5, 0, 0.5]]], [[[1., 0, -1], [0.5, 0, 0.5]]], ])) # 输出 conv2d(input)
tensor([[[[3.5000, 1.0000, 3.0000]],
[[3.5000, 1.0000, 3.0000]]]], grad_fn=<ConvolutionBackward0>)
Daniel Povey et al. “Semi-Orthogonal Low-Rank Matrix Factorization for Deep Neural Networks…” conference of the international speech communication association(2018): n. pag. ↩︎
http://zh.d2l.ai/chapter_convolutional-neural-networks/conv-layer.html ↩︎
http://zh.d2l.ai/chapter_convolutional-neural-networks/channels.html#id2 ↩︎
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。