system: [SYSTEM]

user: 3. 基于LSTM神经网络的说话人识别研究 3.1. 长短时记忆网络LSTM 近年来，循环神经网络越多地被应用到语音信号处理领域。随着应用地不断深入，循环神经网络的弊端开始显现。由于长时间学习而导致的梯度弥散或者梯度爆炸问题被越来越多的学者所揭示。为了解决循环神经网络出现的问题，有学者提出了长短时记忆网络 [ 12 ] (Long short-term memory， LSTM)。在循环神经网络的基础上，长短时记忆网络改进了循环神经网络权值的计算规则。与普通的循环神经网络相比，LSTM能够学习长期依赖信息。 标准的循环神经网络具有一个单一的、完全相同的神经网络层。常见的是单tanh层，如图3所示。 图3. 一种简单的循环神经网络模式图 而对于LSTM来说，情况则大不相同。这里不再是单一的tanh层，而是有四个不同的结构，分别是1个tanh层和3个sigmoid层，如图4所示。 图4. 一种简单的长短时记忆网络模式图 通过引入一种控制结构，神经网络可以学会如何控制信息去除或者增加到细胞(cell)中。也就是说，神经网络可以让信息有选择地通过。这种结构包含了一个sigmoid神经网络层和一个乘法操作，如图5所示。 图5. LSTM中的控制结构 Sigmoid神经网络层会输出0到1之间的数字，0意味着禁止信息通过，1意味着允许所有信息通过。一个LSTM神经网络中有三个类似的控制结构，来控制神经网络中细胞的状态(state)。 对图4所示的神经网络计算过程如下： 第一步，从细胞状态中丢弃旧信息。此行为通过一个被称作是忘记门层的控制结构来完成。忘记门层会读取 h t − 1 和 x t ，计算公式为 f t = σ ( W f × [ h t − 1 ， x t ] + b f ) (8) 如图6所示，可以得到一个在0到1之间的数值，此时的神经网络状态记为 C t − 1 。 图6. LSTM神经网络第一步运算 第二步，存新信息到细胞状态中。控制结构的一部分是sigmoid层，该层决定什么值需要更新。另一部分的结构是tanh层。当信息通过tanh层时会得到一个新的向量，记为 C ˜ t ，被记入到细胞状态中。细胞会根据这两个值进行更新，如图7所示。这两部分的计算公式为： i t = σ ( W f × [ h t − 1 ， x t ] + b f ) (9) C ˜ t = tanh ( W c × [ h t − 1 ， x t ] + b c ) (10) 图7. LSTM神经网络第二步运算 第三步，更新细胞状态。将旧的细胞状态与 f t 相乘，丢弃掉决定要丢弃的信息，再加上 i t × C ˜ t ，这就是新的细胞状态，如图8所示。计算公式为： C t = f t × C t − 1 + i t × C ˜ t (11) 图8. LSTM神经网络第三步运算 第四步，计算细胞输出。输出来自于新的细胞状态，如图9所示。计算公式为： o t = σ ( W o × [ h t − 1 ， x t ] + b o ) (12) h t = o t × tanh ( C t ) (13) 图9. LSTM神经网络第四步运算 至此，一层简单的LSTM神经网络创建完成。实验中通过Python语言的Pytorch工具包中的torch.nn.LSTM()函数即可快速构建LSTM神经网络，如图10所示。 图10. 使用nn.LSTM函数快速创建LSTM神经网络 3.2. 基于三元组的端对端损失函数的声纹识别系统 参考文献 [ 13 ] 中介绍了一种基于三元组的端到端损失函数(the end-to-end loss function based on triples， TE2E)声纹识别系统。 作者将评价话语 X j ~ 和M个注册话语 X k m ( m = 1 ， 2 ， ⋯ ， M ) 作为一个元组送入LSTM神经网络。其中，X是从定长段语音信号中提取的梅尔频谱系数，j和k代表话语的说话者。两者相等的关系不确定。若两者相等，则说明来自同一个说话者，认为该元组是正元组(positive)；反之，认为该元组是负元组(negative)。 对于每个输入的元组，作者计算了LSTM神经网络的L2正则(the L2 normalized)： { e j ~ ， ( e k 1 ， ⋯ ， e k M ) } 。这里的每一个e是固定维度的嵌入矢量(d-vector)。它的维度由LSTM神经网络的投影层大小决定。元组的中心表示从M个话语构建的声纹(voiceprint)，计算过程如下： c k = E m [ e k m ] = 1 M ∑ m = 1 M e k m (14) 使用余弦相似度函数定义两者之间的相似度： s = w ⋅ cos ( e j ~ ， c k ) + b (15) 其中w和b分别是神经网络可以学习的权值和偏置。最终损失函数被定义为： L T ( e j ~ ， c k ) = δ ( j ， k ) σ ( s ) + ( 1 − δ ( j ， k ) ) ( 1 − σ ( s ) ) (16) 其中 σ ( x ) = 1 / ( 1 + e − x ) 是标准的sigmoid函数。若 j = k ，则 δ ( j ， k ) = 1 ，反之， δ ( j ， k ) = 0 。当 j = k 时，TE2E损失函数会使相似度s越来越大；当 j ≠ k 时，TE2E损失函数会使相似度越来越小。这两种元组的更新方式和在FaceNet [ 14 ] 中使用的正负元组非常类似。 3.3. 改进后的端对端损失函数的声纹识别系统 在本章中，介绍了TE2E损失函数的一种改进后的形式(a generalization of our TE2E architecture)。我们称其为GE2E损失函数。这种改进后的算法以一种更加有效的方式生成嵌入矢量，这方式显著提高了与文本无关的说话人验证(TI-SV)的性能和训练速度。 此次提出的模型是基于批量处理的语音信号，此举大大节省了运算时间。模型训练时的每个批次(batch)包含N个说话者，平均每个说话者包含M个话语，如图11所示。 图11. 声纹识别系统概述 3.3.1. 广义的端到端模型 模型采取大小的话语来构造一个批次(batch)。每个说话者都有M个不同的话语，共计有N个不同的说话者。这些构成了 N × M 的矩阵。记特征向量为 X j i ，其中j和i的范围分别是 1 ≤ j ≤ N 和 1 ≤ i ≤ M 。每一个特征向量说明了特征来自第j个说话者的第i个的话语。 将特征向量送入LSTM神经网络。LSTM神经网络的最后一层连接了一个线性层，用来降低特征向量的维度。将公式 f ( X j i ; W ) 定义为神经网络的输出，其中神经网络中所有可以学习的参数被记为W，包括LSTM层和线性层的参数。由网络输出的L2正则形式可以得到嵌入矢量(d-vector)，嵌入矢量的计算公式为： e j i = f ( X j i ; W ) ‖ f ( X j i ; W ) ‖ 2 (17) 这里的 e j i 代表着第j个说话者的第i个话语的嵌入矢量。定于所有嵌入矢量的中心为该说话者的声纹。记 c j 为第j个说话者的声纹，计算公式为： c j = c k = E m [ e k m ] = 1 M ∑ m = 1 M e k m (18) 定义每个嵌入矢量 e j i 和嵌入矢量的中心 c k 之间的余弦相似度为相似度矩阵 S j i ， k ，计算公式为： S j i ， k = w ⋅ cos ( e j i ， c k ) + b (19) 其中w和b分别是神经网络可以学习的权值和偏置。为了余弦相似度越大时，相似度矩阵也越大，我们限定 w > 0 。与改进之前的损失函数相比，TE2E和GE2E损失函数的主要区别如下： 1、由公式17可知，TE2E的相似度是一个标量值。它定义了嵌入矢量和单个元组中心的相似度。 2、由公式19可知，GE2E的相似度是矩阵形式。它定义了嵌入矢量和所有元组中心之间的相似度。 图1展示了整个过程，包括来自不同说话人的特征、嵌入矢量以及相似度评分，并用不同的颜色表示。 训练过程中，我们希望每个话语的嵌入矢量与该说话者的所有话语的中心尽可能地靠近，同时尽可能地远离其他说话者的中心。图12的相似性矩阵说明了这个问题。我们希望主对角线上的相似值越大越好，而其他部分的相似值越小越好。图13以另一种形式说明了这个问题。我们希望蓝色嵌入矢量尽可能的靠近它自己说话者嵌入矢量的中心，即蓝色三角形；同时尽可能的远离其他说话者的中心，即紫色和红色三角形。尤其是需要远离距离它最近的红色三角形。如图12所示，给定一个嵌入矢量 e j i ，所有的说话者嵌入矢量的中心即说话者的声纹 c k ，以及所有的相似度矩阵 S j i ， k ，有两种损失函数可以实现这种要求。 图12. 嵌入矢量与真假说话者声纹的示意图 1) Softmax.在相似度矩阵上设置一个交叉熵损失函数，其中 k = 1 ， 2 ， ⋯ ， N 。若 j = k ，则输出等于1，否则输出等于0。因此，每个嵌入矢量 e j i 上的损失可定义为： L ( e j i ) = − S j i ， i + log ∑ k = 1 N exp ( S j i ， k ) (20) 这个损失函数使得每个嵌入矢量距离说话人中心越来越近，并远离其他说话人的中心。 2) Contrast.在正元组和距离最远的负元组之间定义一个对比度损失函数： L ( e j i ) = 1 − σ ( S j i ， j ) + max 1 ≤ k ≤ N k ≠ j ( S j i ， k ) (21) 其中 σ ( x ) = 1 / ( 1 + e − x ) 是sigmoid函数。对于每一个话语，有两部分组成了损失。这两部分分别是： 1、一个正项，它与嵌入矢量和它的真说话人声纹之间的正匹配呈现相关关系。 2、一个权重较大的负项，它与嵌入矢量和在所有假说话者中相似性最高的说话人声纹之间的负匹配呈现相关关系。 在图13中，正项对应于使嵌入矢量靠近真说话人的声纹。因为与相比更靠近嵌入矢量，所以负项对应于使嵌入矢量远离所有假说话者中相似性最高的假说话人的声纹。因此，对比度损失函数使得嵌入矢量和假说话人的声纹之间的相似度得到重点关注。 在此次实验中，我们发现使用softmax损失函数在与文本无关的说话人识别问题中表现更好。 此外，我们还观察到，在计算真正说话者的声纹时，一种简单的方案是去掉 e j i 。这样会使得模型更容易收敛。因此，我们在计算负相似性 ( k ≠ j ) 时仍然使用公式16；当 k = j 时，我们使用公式22： c j ( − i ) = 1 M − 1 ∑ m = 1 m ≠ i M e j m (22) S j i ， k = { w ⋅ cos ( e j i ， c j ( − i ) ) + b               k = j w ⋅ cos ( e j i ， c k ) + b               otherwise (23) 结合公式17，20，21和22，最终的GE2E损失 L G 是相似矩阵上所有损失的总和： L G ( x ; w ) = L G ( S ) = ∑ j ， i L ( e j i ) (24) 其中 1 ≤ j ≤ N ， 1 ≤ i ≤ M 。 3.3.2. GE2E和TE2E的比较 考虑GE2E的单个批次的损失更新：每个批次有N个说话人，每个说话人有M个话语。每一步更新都会是所有的大小为 N × M 的嵌入向量尽可能地靠近它们自己说话者的中心，并使其尽可能地远离其他说话者的中心。这反映了TE2E损失函数 [ 13 ] 中每个 X j i 的所有可能元组的情况。假设我们随机选择P个话语： 1、正元组：记为 { X j i ， ( X j ， i 1 ， ⋯ ， X j ， i P ) } ，其中 1 ≤ i p ≤ M ， p = 1 ， ⋯ ， P 。一共有 ( M P ) 个这样的元组。 2、负元组：记为 { X j i ， ( X k ， i 1 ， ⋯ ， X k ， i P ) } ，其中 k ≠ j ， 1 ≤ i p ≤ M ， p = 1 ， ⋯ ， P 。对于每一个 X j i ，我们与其他所有的 N − 1 个中心进行比较。其中，每一组比较都包含 ( M P ) 个这样的元组。 3、一个正元组对应一个负元组，所以元组的总数是正元组和负元组的最大数目的2倍。因此TE2E损失的元组总数： 2 × max ( ( M P ) ， ( N − 1 ) ( M P ) ) ≥ 2 ( N − 1 ) (25) 当 P = M 时，公式25出现最小值。因此GE2E中每次更新 X j i 等价于TE2E中至少更新 2 ( N − 1 ) 次。 上述分析说明了为什么GE2E模型要优于TE2E模型。 3.4. 实验结果及分析 本实验使用的数据集为TIMIT语音数据集，它是由美国德州仪器公司、麻省理工学院和SRI国际公司构建的语音库。其中全部语音信号的采样频率都是16 kHz，一共包含6300个句子。实验采用了完整的TIMIT数据集。 实验中特征提取过程与 [ 15 ] 一致。首先将音频信号转换为帧长为25，帧移为10的帧。然后提取40维度的梅尔频率倒谱系数作为每个帧的特征。对每个话语进行语音活动检测，然后选择每个话语的前180帧和后180帧，提取MPCC特征，然后送入神经网络。 使用带有投影层(projection) [ 16 ] 的三层LSTM神经网络，嵌入矢量的维度和投影层的维度相同。对于此次文本无关的声纹识别，隐藏层大小被设置为768，投影层大小被设置为256。训练时每批次包含 N = 4 个说话者， M = 5 个话语。训练方法采用随机梯度下降法，训练的学习率被设置为0.01。同时，将梯度的L2范数裁剪 [ 17 ] 为3。对于权值 ( W ， b ) ，我们还观察到一个较小的初值是 ( W ， b ) = ( 10 ， − 5 ) 。较小的梯度有助于平滑收敛。如图13所示，可以看到，训练一共迭代到133，929次，损失下降到一个较低水平。 图13. 训练日志结果 测试时每批次包含 N = 4 个说话者， M = 6 个话语。如图14所示，从测试日志中可以看到等错误率(ERR)始终维持在一个较低水平，模型训练效果较好。 图14. 测试日志结果