这本是近三个月间零零散散看到的知识点,今记录于此。
韵律预测
口语句子的韵律结构是指某些词似乎自然地结合在一起,而某些词似乎有明显间隔或彼此分开。如:
I want to go London, but could only get tickets for France.
包含两个语调短语,边界即是逗号处。
在第一个短语中,似乎还有更小的韵律边界,通常称为中间短语,把单词做如下分割:
I wanted/to go/to London.
从一个语调短语的开始到结尾,(F_0)往往会有一个轻微的下降,然后在一个新的韵律短语开始的时候,(F_0)又会复位。可以将短语边界的预测看成是一个二元分类问题,对于一个给定的单词,判定在它后面是否存在一个韵律边界。边界预测的简单模型是基于确定性规则的。现行精确度最高的规则:
- 在标点符号之后都插入一个韵律边界;
- 在实词之后如果有一个虚词,则在虚词之前插入一个韵律边界
如果将韵律预测作为一个机器学习问题,在该问题中通常最有效的特征有:
- 长度特征
- 话语中单词和音节总数;句子开始至句子结尾的距离;单词离最后一个标点符号的距离
- 相邻词类和标点:前两个单词词类与后两个单词词类;后面一个标点符号的类型
语音情感
情感语音数据库分为离散情感数据库和维度情感数据库。其中离散情感问题是分类问题;而维度情感是打分连续值,是回归问题。
语音情感特征提取:
- 韵律学特征
- 基于谱的相关特征
- 音质特征
这些特征常常以帧为单位进行提取,但是以全局特征统计值的形式参与情感的识别。
韵律学特征
韵律是指语音中凌驾于语义符号之外的音高、音长、快慢和轻重方面的变化。常用的韵律特征有时长、基频、能量等。基频均值、能量均值、基频方差,基础对数的动态范围。
基于谱的相关特征
线性谱特征一般有:LPC
,OSALPC
,LFPC
倒谱特征一般有:LPCC
,OSALPCC
,MFCC
声学质量特征
对语音质量产生影响的声学表现有:喘息、颤音、哽咽等
因此,声音质量的声学特征一般有:共振峰频率及其带宽,频率微扰和振幅
分类器
-
离散语音情感分类器
- 线性
- 朴素贝叶斯
- Linear ANN(Artificial Neural Network)
- Linear SVM
- 非线性
- 决策树
- KNN
- 非线性ANN
- 非线性SVM
- GMM
- HMM
使用最广泛的有HMM,GMM,ANN和SVM
- 线性
-
维度语音情感预测器
- Linear Regression
- KNN
- ANN
- SVR
Triplet Loss
triplet loss是深度学习中的一种损失函数,用于训练差异性较小的样本,送入的数据包括锚正例(anchor)
、正例(positive)
和负例(negative)
。通过优化锚正例与正例距离小于锚正例与负例距离,实现样本相似度计算。
其中,(f(x^a),f(x^p),f(x^n))分别为锚正例、正例和负例;(alpha)为距离常数,超参数。
tf.gradients()
及tf.stop_gradient()
-
Tensorflow中有一个计算梯度的函数
tf.gradients(xs,ys)
,注意:xs
和ys
必须相关,不相关则会报错。import tensorflow as tf w1=tf.Variable([[1,2]]) w2=tf.Variable([[3,4]]) # 定义了两个变量w1,w2,但result只和w1相关。否则报错:Fetch argument None has invalid type res=tf.matmul(w1,[[2],[1]]) grads=tf.gradients(res,[w1,w2]) with tf.Session() as sess: tf.global_variables_initializer() # 将报错,因为res只和w1相关。TypeError: Fetch argument None has invalid type <class 'NoneType'> re=sess.run(grads)
-
tf.stop_gradients()
:阻挡节点BP的梯度import tensorflow as tf w1=tf.Variable([[2.]]) a=tf.matmul(w1,[[3.]]) a_stopped=tf.stop_gradient(a) w2=tf.Variable(2.) b=tf.multiply(a_stopped,w2) # b=w1*3.*w2 gradients=tf.gradients(b,xs=[w1,w2]) print(gradients) ''' 输出: [None, <tf.Tensor 'gradients/Mul_grad/Reshape_1:0' shape=() dtype=float32>] '''
可见,一个节点被stop之后,这个节点上的梯度就无法在向前BP了。由于w1变量的梯度只能来自于a节点,所以其对应的节点计算梯度返回的是None.
对应的,
a=tf.Variable(1.) b=tf.Variable(1.) c=tf.add(a,b) c_stopped=tf.stop_gradient(c) d=tf.add(a,b) e=tf.add(c_stopped,d) gradients=tf.gradients(e,xs=[a,b]) with tf.Session() as sess: tf.global_variables_initializer().run() # 输出[1.,1.] print(sess.run(gradients))
虽然c节点被stop了,但是a、b还有从d传回的梯度,因此还是可以输出梯度的。
另外一个例子:
w1=tf.Variable(2.) a_stopped=tf.stop_gradient(a) # b=w1*3.*w2 w2=tf.Variable(2.) opt=tf.train.GradientDescentOptimizer(0.1) # 注意:tf.trainable_variables(): w1&w2 gradients=tf.gradients(b,xs=tf.trainable_variables()) # 输出:[None,Tensor] print(gradients)
-
高阶导数
Tensorflow求高阶导数可以用
tf.gradients()
实现with tf.Session() as sess,tf.device('/cpu:0'): a=tf.constant(2.) b=tf.pow(a,2) # b=a^2 grad=tf.gradients(ys=b,xs=a) # 一阶导数, 4. grad_2=tf.gradients(ys=grad[0],xs=a) # 二阶导数, 2. grad_3=tf.gradients(ys=grad_2[0],xs=a) # 三阶导数, 0. print(sess.run([grad,grad_2,grad_3]))
注意:有些op,Tensorflow没有实现其对应的高阶导计算,如
tf.add()
如果计算了一个没有实现高阶导的op的高阶导数,tf.gradients()
会返回None.
注意力机制
注意力机制可以理解为一种文本聚集方法,基本思想是对文本分配注意力权重,把注意力集中在相关的文本内容上,增加这部分的贡献。
-
注意力形式
- 计算区域
- soft attention: 最为常见的Attention形式,对所有key求权重概率,每个key都有一个对应的权重,是一种全局的计算方式(也可以叫做Global Attention)。这种方式比较理性,参考了所有key的内容,再进行加权,但计算量大。
- hard attention: 这种方式直接精准定位到某个key,其余key全部忽略。即这个key的权重为1,其余key的权重为0。这种对齐方式要求很高,如果没有正确对齐,会带来很大影响。另一方面,因为不可导,一般需要用强化学习的方法进行训练。
- local attention: 上述两者的折中,对一个窗口区域进行计算,先用hard方式定位到某个地方,以该点为中心可以得到一个窗口区域,在这个窗口区域使用soft形式计算attention。
- 计算区域
-
所用信息:假设对一段原文计算Attention,所用信息包括内部信息和外部信息。内部信息是原文本身的信息,而外部信息指原文之外的信息。
-
General attention:这种方式利用了外部信息,常用于构建两个文本之间的关系,query一般包含了额外信息,根据外部query对原文进行对齐。
比如在阅读理解任务中,需要构建问题和文章的关联,先要对问题计算出一个问题向量(q),把这个(q)和文章所有词向量拼接起来,输入到LSTM进行建模。在这个模型中,文章所有词向量共享同一个问题向量,这里问题属于原文,文章词向量就属于外部信息。
-
Local Attention:只使用内部信息,key、value和query只和输入原文有关,在self attention中,key=value=query。既然没有外部信息,那么在原文中每个词都可以和句子中的每个词进行Attention计算,相当于求序列内部的联系。
I love China [0.5,0.7] [0.3,0.1] [0.3,0.5] [alignment=egin{bmatrix} 0.5 & 0.7 \ 0.3 & 0.1\ 0.3 & 0.5 end{bmatrix}_{3 imes 2} egin{bmatrix} 0.5 & 0.3 & 0.3 \ 0.7 & 0.1 & 0.5 end{bmatrix}_{2 imes 3} ]
-
-
结构层次
-
单层Attention:普遍做法,用一个query对一段原文进行一次attention
-
多层Attention:一般用于文本具有层次关系的模型,假设将一个文章划分为多个句子,在第一层对一个句子使用attention,计算出一个句子向量(也即是单层attention),在第二层对所有句子向量再做一次attention,计算一个文章向量(也是单层attention),最后用这个文章向量进行下游任务。
-
多头Attention:重复h头次数:先对query、key和value乘参数矩阵,然后做attention。
[head_i=Attention(q^i,k^i,v^i) ]再拼接起来:
[MultiHead(k,v)=concat(head_1,head_2,...,head_h)W^c ]
-
-
注意力中求query和key相似度的方法有很多,如:
-
点乘
[s(q,k)=q^Tk ] -
矩阵相乘
[s(q,k)=q^Twk ] -
cos相似度
[s(q,k)=frac{q^Tk}{||q||cdot ||k||} ] -
串联方式
[s(q,k)=w[q;k] ] -
MLP
[s(q,k)=v_a^Tmathop{tanh}(wq+uk) ]
-
生成模型
- GAN
- VAEs
- 自回归模型
- RNNs
- 普通RNN
- 门:LSTM、GRU,双向RNN
- 自回归模型
- RNNs
常见的生成模型:
- RNNs
- 普通RNN
- 门:LSTM,GRU,双向
- seq2seq+attention
- 带洞卷积
- WaveNet
- ByteNet
- PixelRNN
- PixelCNN
音频表示
-
原始波形
无压缩,一维,幅度-时间
-
线性谱
二维,频率桶(frequency bins)-时间(1025 bins)
梅尔谱
易于训练神经网络,有损,需要压缩但也保持充足的特征。
能量集中在线性谱的小部分自己bins
梅尔频谱特征:
-
低频更重要:低频排布紧密的滤波器
-
高频不重要
[M=1125mathop{ln}(1+frac{f}{700}) ]低频部分,bins排布更紧密
-
-
幅度谱
二维,指数压缩表示(80bins)
自编码器
自编码器由encoder和decoder两部分组成。encoder将输入进行编码,得到隐表达(latent representation)(z),然后decoder对(z)进行解码得到输入(x),即重建(x)。
通常中间潜在表达的维度比输入小,中间层要对输入(x)进行压缩,提取输入(x)的主要信息,然后利用得到的(z)进行重建,得到原来的(x)。在重建过程中,从低维到高维势必产生一定的误差,这样可以保证重建数据和输入数据不完全相像。
如果抹去encoder,剩下的decoder就是一个生成器,可以输入(z)得到想生成的数据。
变分自编码器(VAE)
VAE不像标准的auto-encoder中encoder产生一个单一数值来描述潜在表达(z)的分布,而是用概率来表达产生的数值。
VAE的encoder会将图片编码成一个个概率分布,然后decoder会从这个分布中随机采样作为decoder的输入。
不同时刻的输出都是从潜在表达的概率分布中生成的,因此希望生成的输出尽可能相似。
在贝叶斯公式中,
其中,(p(x))并不一定好算,(p(x)=int p(x|z)p(z)dz),如果(z)是一个高维的,就会出现多次积分。一个替代方法就是用变分推断(varitational inference)来估计这一个值。
假如有另外一个分布(q(z|x)),(q(z|x))可以用于拟合(p(z|x)),而(q(z|x))有很好的性质,可以很好的计算,这样就可以间接的计算(p),可以最小化(p)和(q)的KL散度,使得(q)来模拟出(p)。
其中,(mathop{log}p(x))是一个常数,因此减少(KL(q||p))等同于增大(sum_z q(z|x)mathop{log}frac{p(x,z)}{q(z|x)})。(sum_z q(z|x)mathop{log}frac{p(x,z)}{q(z|x)})被称为变分下界。
因此需要增大(E_{q(z|x)}mathop{log}p(x|z)-KL(q(z|x)||p(z)))
其中,第一部分表示重建可能性,第二部分确保学习到的(q)相似于(p)。因此可以用(q)来推测产生的隐变量(p)。
Loss function由两部分组成,一部分是重建误差,另一个是我们学习到的分布(q(z|x))应相似于默认潜在空间的分布(p(z))。