杂记(2019.04.13)

这本是近三个月间零零散散看到的知识点,今记录于此。


韵律预测

口语句子的韵律结构是指某些词似乎自然地结合在一起,而某些词似乎有明显间隔或彼此分开。如:

I want to go London, but could only get tickets for France.

包含两个语调短语,边界即是逗号处。

在第一个短语中,似乎还有更小的韵律边界,通常称为中间短语,把单词做如下分割:

I wanted/to go/to London.

从一个语调短语的开始到结尾,\(F_0\)往往会有一个轻微的下降,然后在一个新的韵律短语开始的时候,\(F_0\)又会复位。可以将短语边界的预测看成是一个二元分类问题,对于一个给定的单词,判定在它后面是否存在一个韵律边界。边界预测的简单模型是基于确定性规则的。现行精确度最高的规则:

  • 在标点符号之后都插入一个韵律边界;
  • 在实词之后如果有一个虚词,则在虚词之前插入一个韵律边界

如果将韵律预测作为一个机器学习问题,在该问题中通常最有效的特征有:

  • 长度特征
    • 话语中单词和音节总数;句子开始至句子结尾的距离;单词离最后一个标点符号的距离
    • 相邻词类和标点:前两个单词词类与后两个单词词类;后面一个标点符号的类型

语音情感

情感语音数据库分为离散情感数据库和维度情感数据库。其中离散情感问题是分类问题;而维度情感是打分连续值,是回归问题。

语音情感特征提取:

  • 韵律学特征
  • 基于谱的相关特征
  • 音质特征

这些特征常常以帧为单位进行提取,但是以全局特征统计值的形式参与情感的识别。

韵律学特征

韵律是指语音中凌驾于语义符号之外的音高、音长、快慢和轻重方面的变化。常用的韵律特征有时长、基频、能量等。基频均值、能量均值、基频方差,基础对数的动态范围。

基于谱的相关特征

线性谱特征一般有:LPCOSALPCLFPC

倒谱特征一般有:LPCCOSALPCCMFCC

声学质量特征

对语音质量产生影响的声学表现有:喘息、颤音、哽咽等

因此,声音质量的声学特征一般有:共振峰频率及其带宽,频率微扰和振幅

分类器
  • 离散语音情感分类器

    • 线性
      • 朴素贝叶斯
      • 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)。通过优化锚正例与正例距离小于锚正例与负例距离,实现样本相似度计算。

\[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),注意:xsys必须相关,不相关则会报错。

    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=\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) \]

生成模型

  • GAN
  • VAEs
  • 自回归模型
    • RNNs
      • 普通RNN
      • 门:LSTM、GRU,双向RNN
      • 自回归模型

常见的生成模型:

  • RNNs
    • 普通RNN
    • 门:LSTM,GRU,双向
    • seq2seq+attention
  • 带洞卷积
    • WaveNet
    • ByteNet
    • PixelRNN
    • PixelCNN

音频表示

  • 原始波形

    无压缩,一维,幅度-时间

  • 线性谱

    二维,频率桶(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\)

AL9ERA.md.png

通常中间潜在表达的维度比输入小,中间层要对输入\(x\)进行压缩,提取输入\(x\)的主要信息,然后利用得到的\(z\)进行重建,得到原来的\(x\)。在重建过程中,从低维到高维势必产生一定的误差,这样可以保证重建数据和输入数据不完全相像。

如果抹去encoder,剩下的decoder就是一个生成器,可以输入\(z\)得到想生成的数据。

变分自编码器(VAE)

VAE不像标准的auto-encoder中encoder产生一个单一数值来描述潜在表达\(z\)的分布,而是用概率来表达产生的数值。

VAE的encoder会将图片编码成一个个概率分布,然后decoder会从这个分布中随机采样作为decoder的输入。

ALChn0.md.png

不同时刻的输出都是从潜在表达的概率分布中生成的,因此希望生成的输出尽可能相似。

在贝叶斯公式中,

\[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)) \]

一些有意思的综述

posted @ 2019-04-13 11:46  冬色  阅读(428)  评论(0编辑  收藏  举报