损失函数 L ( y i , y ^ i ) L(y_i,\hat{y}_i) L(yi,y^i)用来描述神经网络的输出 y ^ i \hat{y}_i y^i和基本事实(Ground Truth,GT) y i y_i yi的差异
对于回归问题,常用均方误差(Mean Square Error,MSE)损失函数 L ( y i , y ^ i ) = ∥ y i − y ^ i ∥ 2 2 L(y_i,\hat{y}_i)=\left \| y_i-\hat{y}_i \right \|_2^2 L(yi,y^i)=∥yi−y^i∥22
神经网络的训练过程就是寻找一组参数 θ \theta θ,使得神经网络在一个batch的训练上,损失函数的和最小 θ = arg min θ ∑ i = 1 N L ( y i , y ^ i ) \theta=\arg\min_{\theta}\sum_{i=1}^{N}L(y_i,\hat{y}_i) θ=argθmini=1∑NL(yi,y^i)
得到概率分布后,使用交叉熵(Cross Entropy,CE)损失函数,计算预测的概率分布,与真实的概率分布之间的差距,假设概率分布的向量维度为K H ( p , q ) = − ∑ i = 1 K p i ⋅ ln q i H(p,q)=-\sum_{i=1}^{K}p_i\cdot\ln q_i H(p,q)=−i=1∑Kpi⋅lnqi 其中,
p p p是真实的概率分布,采用独热向量(One-hot Vector),即只有真实说话人对应的值为1,其他的值都为0
q q q是预测的概率分布,经过Softmax激活函数之后,最大值接近1,所有值求和等于1
由于 p p p为独热向量,所以损失函数简化为 H ( p , q ) = − ln q j H(p,q)=-\ln q_j H(p,q)=−lnqj, q j q_j qj指预测的概率分布中,真实说话人对应的概率
H ( p , q ) H(p,q) H(p,q)的值越小,代表两个分布越接近
训练时:在训练数据上,最小化 H ( p , q ) H(p,q) H(p,q)来优化参数
运行时:直接使用嵌入码,用于说话人识别(可用余弦相似度、欧氏距离等)
这种方法的缺点
用于计算概率分布的MLP,其参数会随着训练数据说话人数量线性增加
例如嵌入码的维度是1280,训练数据有1000人,那么MLP的参数矩阵 W S o f t m a x ∈ R 1000 × 1280 W_{Softmax} \in R^{1000 \times 1280} WSoftmax∈R1000×1280,光是MLP的参数量就达到了128万
训练集中,部分说话人的数据量较少,这意味着 W S o f t m a x W_{Softmax} WSoftmax中,有部分参数极少发挥作用,但是前向传播时每次都需要计算整个矩阵,这导致训练过程中,花费了大量的资源用于优化几乎没有用的参数
W S o f t m a x W_{Softmax} WSoftmax只在训练时发挥作用,与运行时的相似度计算不完全一致,这会导致网络难以泛化到训练集中未出现过的说话人
将 W S o f t m a x W_{Softmax} WSoftmax中的每个行向量 w r w_r wr都限制为单位长度的向量,设嵌入码为 e e e,那么 w r ⋅ e = ∣ ∣ e ∣ ∣ cos θ i w_r \cdot e=||e|| \cos \theta_i wr⋅e=∣∣e∣∣cosθi
W S o f t m a x ⋅ e W_{Softmax} \cdot e WSoftmax⋅e的运算结果,就是 e e e的范数,乘以一个余弦值,此时的优化过程,会与运行时的相似度计算更加一致
注意,关于Softmax的计算,如果幂的值很大,取指数会导致溢出(即便是Python也要考虑这个问题),此时需要令输入向量中的每一个值,都减去向量中的最大值,然后再进行标准的Softmax运算,这不影响运算结果,但是保证了数值计算的稳定,原因如下 y i = e x p ( x i − x m a x ) ∑ j = i K e x p ( x j − x m a x ) = e x p ( x i ) / e x p ( x m a x ) ∑ j = i K [ e x p ( x j ) / e x p ( x m a x ) ] = e x p ( x i ) ∑ j = i K e x p ( x j ) \begin{aligned} y_i&=\frac{exp(x_i-x_{max})}{\sum_{j=i}^{K}exp(x_j-x_{max})} \\ &=\frac{exp(x_i)/exp(x_{max})}{\sum_{j=i}^{K}[exp(x_j)/exp(x_{max})]} \\ &=\frac{exp(x_i)}{\sum_{j=i}^{K}exp(x_j)} \\ \end{aligned} yi=∑j=iKexp(xj−xmax)exp(xi−xmax)=∑j=iK[exp(xj)/exp(xmax)]exp(xi)/exp(xmax)=∑j=iKexp(xj)exp(xi)
二值决策
针对多说话人分类方法,训练和运行时,目标不匹配的问题,研究人员提出二值决策方法
给定两个话语,网络对这两个话语进行二值决策:
0,表示两个话语来自不同的说话人
1,表示两个话语来自同一个说话人
损失函数必须基于,由至少两个话语组成的样本,来定义
Pairwise Loss
假设有两个输入 x i x_i xi和 x j x_j xj,它们都进入同一个网络,得到两个嵌入码,两个嵌入码的余弦相似度是 s i j s_{ij} sij,假设GT表示为: y i j = { 0 , 若 x i 和 x j 来自不同的说话人 1 , 若 x i 和 x j 来自同一个说话人 y_{ij}= \left\{\begin{matrix} 0,若x_i和x_j来自不同的说话人\\ 1,若x_i和x_j来自同一个说话人 \end{matrix}\right. yij={
0,若xi和xj来自不同的说话人1,若xi和xj来自同一个说话人
对应的损失函数为 L ( s i j , y i j ) L(s_{ij},y_{ij}) L(sij,yij)
可以将这个问题视为二分类问题,使用二元交叉熵(Binary Cross Entropy,BCE)损失函数 L B C E ( s , y ) = − y ln s − ( 1 − y ) ln ( 1 − s ) L_{BCE}(s,y)=-y\ln s- (1-y)\ln (1-s) LBCE(s,y)=−ylns−(1−y)ln(1−s)
由于要对余弦相似度取对数,而余弦相似度可能为负数,所需需要将 s s s变换为正数,常见做法: s ′ = σ ( w s + b ) = 1 1 + e x p ( − ( w s + b ) ) s'=\sigma (ws+b)=\frac{1}{1+exp(-(ws+b))} s′=σ(ws+b)=1+exp(−(ws+b))1 其中, w w w和 b b b都是可学习参数, w > 0 w>0 w>0, σ ( ⋅ ) \sigma(\cdot) σ(⋅)是Sigmoid函数。从而,损失函数变为 L B C E ( s ′ , y ) L_{BCE}(s',y) LBCE(s′,y),这就是基于样本对的损失函数Pairwise Loss
缺点:由于网络参数随训练过程变化,所以难以平衡正样本和负样本在训练过程中的数量平衡
Triplet Loss
针对Pairwise Loss的缺点,研究人员提出了基于三元组的损失函数Triplet Loss
先思考:在设计损失函数时,我们希望给网络的监督信息的效果是什么?
对于同一个说话人的嵌入码,我们希望这两个嵌入码在嵌入码空间中越接近越好
对于不同的说话人的嵌入码,我们希望这两个嵌入码在嵌入码空间中越远离越好
针对上述思考,Triplet Loss需要挑选三个话语:
锚样本(Anchor) x a x^a xa
正样本(Positive) x p x^p xp,和锚样本来自同一个说话人
负样本(Negative) x n x^n xn,和锚样本来自不同的说话人
那么,这三个话语的嵌入码,经过参数更新后效果如下图所示:
数学形式 L = [ ∥ f ( x a ) − f ( x p ) ∥ 2 2 − ∥ f ( x a ) − f ( x n ) ∥ 2 2 + α ] + L=[\left \| f(x^a)-f(x^p) \right \|_2^2-\left \| f(x^a)-f(x^n) \right \|_2^2 +\alpha]_+ L=[∥f(xa)−f(xp)∥22−∥f(xa)−f(xn)∥22+α]+ 其中,
[ x ] + [x]_+ [x]+表示函数 m a x ( x , 0 ) max(x,0) max(x,0)
∥ ∥ 2 2 \left \| \right \|_2^2 ∥∥22表示欧氏距离的平方
上述形式的Triplet Loss常用于人脸识别,对于说话人识别,会将欧氏距离改为余弦相似度: L = [ cos ( f ( x a ) , f ( x n ) ) − cos ( f ( x a ) , f ( x p ) ) + α ] + L=[\cos (f(x^a),f(x^n)) - \cos (f(x^a),f(x^p)) +\alpha]_+ L=[cos(f(xa),f(xn))−cos(f(xa),f(xp))+α]+
这 N + 1 N+1 N+1个话语,经过同一个神经网络,其中来自真实说话人的 N N N个话语的嵌入码,被聚合(通常是取平均),成为说话人模型
另外一个嵌入码,与说话人模型计算余弦相似度
余弦相似度经过变换成为正数,然后计算二元交叉熵损失 s ′ = σ ( w s + b ) = 1 1 + e x p ( − ( w s + b ) ) L B C E ( s ′ , y ) = − y ln s ′ − ( 1 − y ) ln ( 1 − s ′ ) \begin{aligned} s'&=\sigma (ws+b)=\frac{1}{1+exp(-(ws+b))} \\ L_{BCE}(s',y)&=-y\ln s'- (1-y)\ln (1-s') \end{aligned} s′LBCE(s′,y)=σ(ws+b)=1+exp(−(ws+b))1=−ylns′−(1−y)ln(1−s′)
最后的损失函数计算过程,非常类似Pairwise Loss,只不过端到端系统的输入是 N + 1 N+1 N+1个话语,而不是两个话语
x-vector系统采用的是类似上述的端到端损失函数,不过将余弦相似度,替换成了另一种相似性度量: L ( e 1 , e 2 ) = e 1 T e 2 − e 1 T S e 1 − e 2 T S e 2 + b L(e_1,e_2)=e_1^Te_2-e_1^TSe_1-e_2^TSe_2+b L(e1,e2)=e1Te2−e1TSe1−e2TSe2+b 其中,
矩阵 S S S和标量 b b b都是可学习参数
这是基于PLDA所衍生出来的一种相似性度量
关键点
关于 N N N的选定,可以按照运行时的情况来决定,如果不确定运行时会有几个注册话语,则取平均值或者中间值
如何平衡正负样本比例?这是常见的问题,通常负样本数远远多于正样本数,常见的做法是:在负样本的损失函数上,乘以一个常数 K , 0 < K < 1 K,0<K<1 K,0<K<1
将嵌入码记为 e j i e_{ji} eji, j j j表示说话人, i i i表示属于第 j j j个说话人的第 i i i个话语;某个说话人的嵌入码中心记为 c j c_j cj
基本思想,具体而言:
对于每一个 e j i e_{ji} eji而言,我们希望它与 c j c_j cj靠近,与其他的 c k 、 c k ′ c_k、c_{k'} ck、ck′远离
在一个batch内,对于一个 e j i e_{ji} eji而言,会出现多个其他说话人的中心点,如 c k 、 c k ′ c_k、c_{k'} ck、ck′
根据最大间隔原理,只关注距离该 e j i e_{ji} eji最接近的其他说话人的中心,从图中来看,则是只关注 c k c_k ck,不关注 c k ′ c_{k'} ck′
对神经网络而言, c k c_k ck是区分 e j i e_{ji} eji属于 c j c_j cj,最困难的一个其他说话人。也就是说,对于 e j i e_{ji} eji而言, c k c_k ck是支持说话人(Support Speaker)
计算损失函数前的准备工作
假设,一个batch的维度为 N × M N \times M N×M, N N N表示该batch包含的说话人个数, M M M表示该batch中每个说话人的话语数
该batch的数据,经过神经网络后,每个话语都向量化,得到嵌入码 e j i e_{ji} eji,从而: c j = 1 M ∑ i = 1 M e j i c_j=\frac{1}{M}\sum_{i=1}^{M}e_{ji} cj=M1i=1∑Meji
对整个batch,计算相似度矩阵,维度为 N M × N NM \times N NM×N: S j i , k = w ⋅ cos ( e j i , c k ) + b S_{ji,k}=w\cdot \cos (e_{ji},c_k)+b Sji,k=w⋅cos(eji,ck)+b 其中,
w > 0 , w 、 b w>0,w、b w>0,w、b都是可学习参数
相似度矩阵,表示batch中的每一个嵌入码 e j i e_{ji} eji,与batch内所有说话人的中心点 c k c_k ck,计算相似度,然后进行线性变换,因此维度是 N M × N NM \times N NM×N
损失函数的定义:有两种方法实现最大间隔原理
基于对比的方法:对于每一个 e j i e_{ji} eji而言,损失函数为 L ( e j i ) = 1 − σ ( S j i , j ) + max 1 ≤ k ≤ N , k ≠ j σ ( S j i , k ) L(e_{ji})=1-\sigma(S_{ji,j})+\max_{1\le k \le N,k \ne j} \sigma(S_{ji,k}) L(eji)=1−σ(Sji,j)+1≤k≤N,k=jmaxσ(Sji,k) 其中,
1 − σ ( S j i , j ) 1-\sigma(S_{ji,j}) 1−σ(Sji,j)表示正样本对的余弦相似度越接近1越好
max 1 ≤ k ≤ N , k ≠ j σ ( S j i , k ) \max_{1\le k \le N,k \ne j} \sigma(S_{ji,k}) max1≤k≤N,k=jσ(Sji,k)表示最困难负样本对的余弦相似度越小越好
这种同时考虑正样本对和负样本对的思想,与Triplet Loss类似,不同之处在于:
使用中心点,模拟运行时的说话人嵌入码
负样本对的优化,只针对支持说话人
缺点:使用了 max ( ⋅ ) \max(\cdot) max(⋅),这是不可导的函数
基于Softmax的方法,针对方法1的缺点,采用 max ( ⋅ ) \max(\cdot) max(⋅)的可微分版本——Softmax来改进 L ( e j i ) = − S j i , j + ln ∑ k = 1 N exp ( S j i , k ) = − ln ( exp ( S j i , j ) ) + ln ∑ k = 1 N exp ( S j i , k ) = ln ∑ k = 1 N exp ( S j i , k ) exp ( S j i , j ) = − ln exp ( S j i , j ) ∑ k = 1 N exp ( S j i , k ) \begin{aligned} L(e_{ji})&=-S_{ji,j}+\ln \sum_{k=1}^{N} \exp(S_{ji,k}) \\ &=-\ln(\exp(S_{ji,j}))+\ln \sum_{k=1}^{N} \exp(S_{ji,k}) \\ &=\ln \frac{\sum_{k=1}^{N} \exp(S_{ji,k})}{\exp(S_{ji,j})} \\ &=- \ln \frac{\exp(S_{ji,j})}{\sum_{k=1}^{N} \exp(S_{ji,k})} \end{aligned} L(eji)=−Sji,j+lnk=1∑Nexp(Sji,k)=−ln(exp(Sji,j))+lnk=1∑Nexp(Sji,k)=lnexp(Sji,j)∑k=1Nexp(Sji,k)=−ln∑k=1Nexp(Sji,k)exp(Sji,j) 这个损失函数,将每个嵌入码推到其对应说话人中心点附近,并将其拉离所有其他说话人中心点
为了避免平凡解,一个重要的技巧是:在计算 e j i e_{ji} eji的损失函数时,对于 c j c_j cj的计算,不要将 e j i e_{ji} eji本身加进去,新的 c j c_j cj表达式如下,式中的 ( − i ) (-i) (−i)表示排除 i i i c j ( − i ) = 1 M − 1 ∑ m = 1 , m ≠ i M e j m c_j^{(-i)}=\frac{1}{M-1}\sum_{m=1,m \ne i}^{M}e_{jm} cj(−i)=M−11m=1,m=i∑Mejm
原型损失来自于图像分类任务中的少样本学习,少样本学习描述的是这样一个问题:N-way K-shot,意思是说对于N个类别,每个类别K+1个样本,一共会有 N × ( K + 1 ) N \times (K+1) N×(K+1)个样本,就利用这些样本,对神经网络进行一个batch的训练,其中 N ∗ K N*K N∗K个样本被称为支持集, N ∗ 1 N*1 N∗1个样本被称为查询集。训练集通常来自对巨型数据集的采样
测试时,测试集也是按照 N × ( K + 1 ) N \times (K+1) N×(K+1)这样来组织,但是每个N的K会很少,比如5-way 1-shot,就是先给神经网络“看到”5个类各1张图片,然后再另外给出5个类各1张图片,神经网络将另外给出的图片分类到5个类中,注意,这5个类是训练集中不曾出现的
原型损失基本思想:测试时,对于给出的 N × K N \times K N×K支持集,利用神经网络提取出嵌入码,再利用每个类别的K个嵌入码,计算每个类别的“原型”,然后将待测样本的嵌入码,与各类别的原型分别计算距离,取距离最接近的一个类别,作为该待测样本的分类结果。这里所说的“距离最近”,要和所用的距离函数相关,比如:欧氏距离是值越小,越接近;余弦距离是值越大,越接近
数学形式
训练集 D = { ( x 1 , y 1 ) , . . . , ( x N , y N ) } D=\left \{ (x_1,y_1),...,(x_N,y_N) \right \} D={
(x1,y1),...,(xN,yN)},其中 y i ∈ { 1 , . . . , K } y_i \in \left \{ 1,...,K \right \} yi∈{
1,...,K}, D k D_k Dk表示 D D D中属于类别 k k k的样本
从训练集中,采样 N C N_C NC个类别, N C ≤ K N_C \le K NC≤K,并为 N C N_C NC中的每个类别 k k k,采样 N S N_S NS个样本作为支持集 S k S_k Sk,采样 N Q N_Q NQ个样本作为查询集 Q k Q_k Qk( N Q N_Q NQ通常取1), S k S_k Sk和 Q k Q_k Qk无重叠样本。总的支持集 S = ∑ k = 1 N C S k S=\sum_{k=1}^{N_C}S_k S=∑k=1NCSk和总的查询集 Q = ∑ k = 1 N C Q k Q=\sum_{k=1}^{N_C}Q_k Q=∑k=1NCQk,构成一个batch
对batch中的每一个样本,经过神经网络,得到对应的嵌入码 f ( x i ) f(x_i) f(xi),然后根据每个 S k S_k Sk,计算每个类别的“原型” c k = 1 ∣ S k ∣ ∑ ( x i , y i ) ∈ S k f ( x i ) c_k=\frac{1}{\left | S_k \right | } \sum_{(x_i,y_i) \in S_k} f(x_i) ck=∣Sk∣1(xi,yi)∈Sk∑f(xi) 其中, ∣ S k ∣ \left | S_k \right | ∣Sk∣表示 S k S_k Sk的 l 1 l_1 l1范数,即 S k S_k Sk所含样本个数
将查询集 Q Q Q中的每个样本的嵌入码,与 N C N_C NC个原型,计算距离 d ( f ( x i ) , c k ) d(f(x_i),c_k) d(f(xi),ck),然后计算Softmax Loss L ( x i , y i ) = − ln e x p ( − d ( f ( x i ) , c y i ) ) ∑ k = 1 N C e x p ( − d ( f ( x i ) , c k ) ) L(x_i,y_i)=- \ln \frac{exp(-d(f(x_i),c_{y_i}))}{\sum_{k=1}^{N_C} exp(-d(f(x_i),c_k))} L(xi,yi)=−ln∑k=1NCexp(−d(f(xi),ck))exp(−d(f(xi),cyi)) 其中, y i y_i yi是嵌入码 f ( x i ) f(x_i) f(xi)所属的GT类别, d ( f ( x i ) , c k ) d(f(x_i),c_k) d(f(xi),ck)是欧氏距离,值越小,越接近,所以要取负号,如果换成余弦距离,值越大,越接近,则不需要取负号
将查询集 Q Q Q中的每个样本的 L x i L_{x_i} Lxi加起来,求均值,即得到这个batch的总损失 J = 1 N C × N Q ∑ ( x i , y i ) ∈ Q L ( x i , y i ) J=\frac{1}{N_C \times N_Q} \sum_{(x_i,y_i) \in Q} L(x_i,y_i) J=NC×NQ1(xi,yi)∈Q∑L(xi,yi)
关键点
距离 d ( f ( x i ) , c k ) d(f(x_i),c_k) d(f(xi),ck)经过原论文的实验,发现欧氏距离优于余弦距离(对于图像分类任务)
如果在测试时是N-way K-shot的,那么训练时的 N C N_C NC要大于N,比如测试时5-way,则训练时采取20-way,shot取值相同即可。原因可以理解为,训练时,要求网络更高的细粒度分类能力