说话人识别系统 (又称声纹识别系统)
论文:
本博客是基于百度的论文Deep Speaker: an End-to-End Neural Speaker Embedding System
的理论上进行实现的: https://arxiv.org/pdf/1705.02304.pdf
另外参考了一篇Github的代码。
感谢!
效果演示:
Demo-SpeakerRecognize
1. 数据集和整体流程架构
- 数据集
数据集使用的是英雄联盟语音包, 使用了142个英雄的33113条语音作为数据集. 音频全部都是wav格式的文件, 音频大小从零点几秒到十几秒不等. 我们使用代码对数据进行预处理后, 制作成npy格式的数据后拿到神经网络训练的.
数据集地址:
链接:https://pan.baidu.com/s/1SuXQpyhGzaEKhP7Ugwf9Rg
提取码:gqay
复制这段内容后打开百度网盘手机App,操作更方便哦 - 整体架构
miniBatch: 选择合适的batchsize.
Front Processing: 预处理数据, 将音频文件转换成特征向量.
Deep architecture: 论文混合使用了Residual CNN和GRU Network的卷积网络,这样可以提高最终的训练精度。CNN可有效减少光谱变化并模拟声学特征中的频谱相关性。GRU也被证明对语音处理中应用有效。
Average sentence: 时间池化。本来数据是三维的,分别代表(时间帧数 * 每帧特征维度 * 通道数),通道数也就是经过不同方式提取的每帧特征Fbank。将时间平均,这样一段语音就对应一段特征了。而不是每一帧都对应一段特征。
Affine: 仿射,将维度2048的特征变为512维。
ln (length normalization layer): 标准化层,特征标准化之后,得到的向量来表示说话者语音。
2. 数据的预处理
-
预加重:
预加重,作用就是为了消除发生过程中,声带和嘴唇造成的效应,来补偿语音信号收到发音系统所压抑的高频部分。 -
分帧:
因为人的发生器官具有一定的惯性,所以在极短的时间(10ms至25毫秒)内,人的发声特征是非常相似的,所以我们将时间分割成25ms的间隔,以10ms为步长。将一段时长的语音分为许许多多帧。
-
快速傅里叶变换:
傅里叶变换可以将每一帧的波形特征转换成频谱,即频率和能量的关系。
将频率和能量的关系图旋转90°,将频谱映射到灰度值上, 即0~255。然后再将每帧的灰度值按顺序拼起来,就可以得到一张频谱图。
-
梅尔滤波:
Mel滤波,通过Mel滤波器组进行滤波,以得到符合人耳听觉习惯的声谱,最后通常取对数将单位转换成db。
关系式:
m e l ( f ) = 2595 × l n ( 1 + f 700 ) mel(f)=2595 \times ln(1+\frac{f}{700}) mel(f)=2595×ln(1+700f)
- 梅尔倒谱系数:
在梅尔频谱上进行倒谱分析(取对数,逆变换),获得MFCC或者Fbank,即这帧语音特征。
一整段语音中获得了该段语音的一组特征向量。
3. 神经网络
残差神经网络 Residual CNN
残差块:
残差网络:
公式:
h
=
F
(
x
,
w
i
)
+
x
,
h=F(x, w_i)+x,
h=F(x,wi)+x,
网络结构:
剪切整形线性(ReLU)函数:
σ
(
x
)
=
m
i
n
{
m
a
x
{
x
,
0
}
,
20
}
\sigma(x)=min\{max\{x, 0\}, 20\}
σ(x)=min{max{x,0},20}
门控神经网络 Gate Recurrent Unit
网络结构:
4. 说话者嵌入:
时间池化:
h
=
1
T
∑
t
=
0
T
−
1
x
(
t
)
h=\frac{1}{T}\sum^{T-1}_{t=0}x(t)
h=T1t=0∑T−1x(t)
维度变化:
5. 三联体损失:
cos
(
x
i
,
x
j
)
=
x
i
T
⋅
x
j
\cos(x_i, x_j)=x^T_i\cdot x_j
cos(xi,xj)=xiT⋅xj
s
i
a
p
−
α
>
s
i
a
n
s_{i}^{ap}-\alpha>s_i^{an}
siap−α>sian
损失函数计算:
L
=
∑
i
=
0
N
[
s
i
a
n
−
s
i
a
p
+
α
]
+
L=\sum^{N}_{i=0}[s_{i}^{an}-s_{i}^{ap}+\alpha]_{+}
L=i=0∑N[sian−siap+α]+
[
x
]
+
=
max
(
x
,
0
)
[x]_{+}=\max(x, 0)
[x]+=max(x,0)
6.0 训练和测试的结论:
- 可以很好的适应不同语种的分类识别,论文还指出,如果在普通话训练好的模型基础上在对英语语言模型训练,可以提高最终精度。
- 我们在训练的时候舍去了GRU的网络,仅仅使用CNN网络对数据进行预训练。即可达到极高的精度了。
这说明了,即使我用不完整的网络,如果使用GRU网络等再度优化网络,可以在更大的数据集也获得 - 我只花费了极短的时间(大概3~4个小时)就训练好了模型。并且可以达到非常高的精度。
- 但是代码只能在比较纯净的音频上获得良好的表现,由于我的录音设备与播放设备音质比较差,造成了录音质量的损失。使得测试精度降低了许多,(考虑可以加入噪音处理模块)。