这本是近三个月间零零散散看到的知识点,今记录于此。
口语句子的韵律结构是指某些词似乎自然地结合在一起,而某些词似乎有明显间隔或彼此分开。如:
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
对语音质量产生影响的声学表现有:喘息、颤音、哽咽等
因此,声音质量的声学特征一般有:共振峰频率及其带宽,频率微扰和振幅
离散语音情感分类器
使用最广泛的有HMM,GMM,ANN和SVM
维度语音情感预测器
triplet loss是深度学习中的一种损失函数,用于训练差异性较小的样本,送入的数据包括锚正例(anchor)
、正例(positive)
和负例(negative)
。通过优化锚正例与正例距离小于锚正例与负例距离,实现样本相似度计算。
\[
Loss=\sum_i^N(||f(x_i^a)-f(x_i^p)||^2-||f(x_i^a-f(x_i^n))||_2^2+\alpha)_+
\]
其中,\(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.
注意力机制可以理解为一种文本聚集方法,基本思想是对文本分配注意力权重,把注意力集中在相关的文本内容上,增加这部分的贡献。
注意力形式
所用信息:假设对一段原文计算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=\begin{bmatrix} 0.5 & 0.7 \\ 0.3 & 0.1\\ 0.3 & 0.5 \end{bmatrix}_{3\times 2} \begin{bmatrix} 0.5 & 0.3 & 0.3 \\ 0.7 & 0.1 & 0.5 \end{bmatrix}_{2\times 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^T\mathop{tanh}(wq+uk)
\]
常见的生成模型:
原始波形
无压缩,一维,幅度-时间
线性谱
二维,频率桶(frequency bins)-时间(1025 bins)
梅尔谱
易于训练神经网络,有损,需要压缩但也保持充足的特征。
能量集中在线性谱的小部分自己bins
梅尔频谱特征:
低频更重要:低频排布紧密的滤波器
高频不重要
\[
M=1125\mathop{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不像标准的auto-encoder中encoder产生一个单一数值来描述潜在表达\(z\)的分布,而是用概率来表达产生的数值。
VAE的encoder会将图片编码成一个个概率分布,然后decoder会从这个分布中随机采样作为decoder的输入。
不同时刻的输出都是从潜在表达的概率分布中生成的,因此希望生成的输出尽可能相似。
在贝叶斯公式中,
\[
p(z|x)=\frac{p(x|z)p(z)}{p(x)}
\]
其中,\(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\)。
\[
\begin{split}
KL(q||p)&=-\sum q \mathop{log}\frac{p}{q}\&=-\sum_z q(z|x) \mathop{log} \frac{p(z|x)}{q(z|x)}\&=-\sum_z q(z|x) \mathop{log}(\frac{p(x,z)}{p(x)q(z|x)})\&=-\sum_z q(z|x) \mathop{log}(\frac{p(x,z)}{q(z|x)}\cdot \frac{1}{p(x)})\&=-\sum_z q(z|x) (\mathop{log}\frac{p(x,z)}{p(z|x)}+\mathop{log}\frac{1}{p(x)})\&=-\sum_z q(z|x)\mathop{log}\frac{p(x,z)}{q(z|x)}+\sum_z q(z|x)\mathop {log}p(x)\&=-\sum_zq(z|x)\mathop{log}\frac{p(x,z)}{p(z|x)}+\mathop{log} p(x)\\end{split}
\]
\[ \Rightarrow \mathop{log}p(x)=KL(q||p)+\sum_z q(z|x)\mathop{log}\frac{p(x,z)}{q(z|x)} \]
其中,\(\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)}?\)被称为变分下界。
\[
\begin{split}
\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)p(z)}{q(z|x)}\&=\sum_z q(z|x)(\mathop{log}p(x|z)+\mathop{log}\frac{p(z)}{q(z|x)})\&=\sum_z q(z|x)\mathop{log}p(x|z)-KL(q(z|x)||p(z))\&=E_{z\sim q(z|x)}\mathop{log}p(x|z)-KL(q(z|x)||p(z))
\end{split}
\]
因此需要增大\(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)\)。
\[
Loss=L(x,\hat{x})+\sum_j KL(q_j(z|x)||p(x))
\]
原文:https://www.cnblogs.com/mengnan/p/10700493.html