语言处理 之 fastspeech2,ar,nar研究

回归(regression):Y变量为连续数值型(continuous numerical variable)。这就是回归的本质。

目前主流的神经机器翻译模型为自回归模型,自回归就是y自己当自己的变量。AR模型,即自回归(AutoRegressive, AR)模型又称为时间序列模型。
NLP中的 sequence2sequence 和 Transformer (Encoder-Decoder,Seq2seq的集大成)都是AR模型。sequence to sequence模型是一类End-to-End的算法框架,也就是从序列到序列的转换模型框架,应用在机器翻译,自动应答等场景。

Encoder-Decoder模型可以预测任意的序列对应关系,但同时也有一个很大的问题就是从编码到解码的准确率很大程度上依赖于一个固定长度的语义向量c,输入序列到语义向量c的压缩过程中存在信息的丢失,并且在稍微长一点的序列上,前边的输入信息很容易被后边的输入信息覆盖,也就是说编码后的语义向量c已经存在偏差了,解码准确率自然会受到影响。其次在解码的时候,每个时刻的输出在解码过程中用到的上下文向量是相同的,没有做区分,也就是说预测结果中每一个词的的时候所使用的预测向量都是相同的, 这也会给解码带来问题。

一句话,就是中间形式就已经出现信息丢失了。中间形式就是固定向量,为了解决这样的问题,在Seq2Seq模型加入了注意力机制(attention mechanism),在预测每个时刻的输出时用到的上下文是跟当前输出有关系的上下文,而不是统一只用相同的一个。这样在预测结果中的每个词汇的时候,每个语义向量c中的元素具有不同的权重,可以更有针对性的预测结果。图示如下,增加了一个“注意力范围”,表示接下来输出词时候要重点关注输入序列中的哪些部分,然后根据关注的区域来产生下一个输出:

可以看到原初方式是非常容易被后面覆盖的。attention模型最大的不同在于Encoder将输入编码成一个向量的序列,而在解码的时候,每一步都会选择性的从向量序列中挑选一个子集进行输出预测,这样,在产生每一个输出的时候,都能找到当前输入对应的应该重点关注的序列信息,也就是说,每一个输出单词在计算的时候,参考的语义编码向量c都是不一样的,所以说它们的注意力焦点是不一样的。

自Attention机制提出后,加入attention的Seq2seq模型在各个任务上都有了提升,所以现在的seq2seq模型指的都是结合RNN和attention的模型。之后google又提出了解决Seq2Seq问题的Transformer模型,用全attention的结构代替了lstm,在翻译任务上取得了更好的成绩。和大多数seq2seq模型一样,transformer的结构也是由encoder和decoder组成。

前馈神经网络(FNN)是人工智能领域中最早发明的简单人工神经网络类型。在它内部,参数从输入层经过隐含层向输出层单向传播。与递归神经网络不同,在它内部不会构成有向环。FNN由一个输入层、一个(浅层网络)或多个(深层网络,因此叫作深度学习)隐藏层,和一个输出层构成。每个层(除输出层以外)与下一层连接。这种连接是 FNN 架构的关键,具有两个主要特征:加权平均值和激活函数。就是不带环呗。最基本的transformers 完全依赖于注意力机制.一个单词,有注意力模型后,就对其他单词有不同权值,如果没有注意力机制,那么就都是一样的。这里要特别注意一下,编码可以并行计算,一次性全部encoding出来,但解码不是一次把所有序列解出来的,而是像rnn一样一个一个解出来的,因为要用上一个位置的输入当作attention的query

NAR

非自回归(Non-autoregressive,NAR)模型并行生成序列的所有标记,与自回归(AR)模型相比,生成速度更快,但代价是准确性较低。在神经机器翻译(neural machine translation,NMT)、自动语音识别(automatic speech recognition,ASR)和语音合成(TTS)等不同的任务中,人们提出了包括知识提取和源-目标对齐在内的不同技术来弥补AR和NAR模型之间的差距。在这些技术的帮助下,NAR模型可以在某些任务中赶上AR模型的准确性,但在其他任务中则不能。说白了,就是一次到位,不挨个生成。

举例说明:在机器翻译中,不同于自回归(Autoregressive Translation , ART)模型需要用已生成的词来预测下一个位置的词,非自回归 (Non-Autoregressive Translation, NART)模型打破了生成时的串行顺序,希望一次能够解码出整个目标句子,从而解决AT模型所带来的问题。与自回归模型相比,非自回归(Non-Autoregressive)模型尝试同时生成一整个序列,从而解决上述三个问题。一个简单的非自回归模型直接假设目标序列的每个词都是独立的。然而这一独立性假设过强,显然与实际问题不符。为了缓解独立性假设过强的问题,一个方案是引入隐变量z,得到:
Pθ(y|x)=∫zPθ(y|z,x)pθ(z|x)dzPθ(y|x)=∫zPθ(y|z,x)pθ(z|x)dz
假定给定隐变量的前提下,目标序列的每个词是独立的,则:
Pθ(y|z,x)=∏t=1TPθ(yt|z,x)Pθ(y|z,x)=∏t=1TPθ(yt|z,x)
从上面的公式可以看出,隐变量需要保存关于目标序列的全部信息,才能解码整个目标序列。因此隐变量的概率分布必须有足够的复杂度。

近年来,以 FastSpeech 为代表的非自回归语音合成(Text to Speech, TTS)模型相比传统的自回归模型(如 Tacotron 2)能极大提升合成速度,提升语音鲁棒性(减少重复吐词、漏词等问题)与可控性(控制速率和韵律),同时达到相匹配的语音合成质量。

对于一些在线预测任务来说,复杂的模型结构不利于线上预测任务的快速响应需求,因此模型压缩的需求应运而生。深度学习下为了能够获得更好的准确率,训练出的网络往往结构比价复杂,这个teacher-student模式架构主要的目的就是用来进行深度学习模型的压缩,属于model compression领域中的一种比较流行的做法。teacher结构相当于原始的复杂的深度神经网络结构,student则是一种轻量级的网络结构;因此teacher会有更高的预测准确率,它会指导student到达在简化参数之后最好的模型效果。

在化学中,蒸馏是一个有效的分离沸点不同的组分的方法,大致步骤是先升温使低沸点的组分汽化,然后降温冷凝,达到分离出目标物质的目的。在前面提到的这个过程中,我们先让温度 T 升高,然后在测试阶段恢复「低温」,从而将原模型中的知识提取出来,因此将其称为是蒸馏,实在是妙

FastSpeech 2,它抛弃了 Teacher-Student 知识蒸馏框架降低训练复杂度,直接用真实的语音数据作为训练目标避免信息损失,同时引入了更精确的时长信息和语音中的其它可变信息(包括音高(Pitch)和音量(Energy)等)来提高合成的语音质量。基于 FastSpeech 2,我们还提出了加强版 FastSpeech 2s 以支持完全端到端的从文本到语音波形的合成,省略了梅尔频谱的生成过程。实验结果表明,FastSpeech 2 和 2s 在语音质量方面优于 FastSpeech,同时大大简化了训练流程减少了训练时间,还加快了合成的速度。

在 FastSpeech 2 的基础上,我们提出了 FastSpeech 2s 以实现完全端到端的文本到语音波形的合成。FastSpeech 2s 引入了一个波形解码器,如图1(d)所示,它以可变信息适配器的输出隐层序列为输入,以波形为输出。在训练时,为了帮助可变信息预测器的训练,梅尔频谱解码器及其训练损失函数被保留。在生成阶段,将梅尔频谱解码器丢弃后,使其成为一个文本到波形的端到端系统。

FastSpeech2 Trainer基于FastSpeech Trainer

混合精度,唉,做不了。。。

在训练模型的过程中,一个step其实指的就是一次梯度更新的过程。例如在每个epoch中有2000个用于训练的图片,我们选取了batch_size=100,那么我们就需要2000 images / 100 (images/step) = 20 steps来完成这个epoch。

用Python写代码的时候,在想看的地方写个print xx 就能在控制台上显示打印信息,这样子就能知道它是什么了,但是当我需要看大量的地方或者在一个文件中查看的时候,这时候print就不大方便了,所以Python引入了logging模块来记录我想要的信息。

        print也可以输入日志,logging相对print来说更好控制输出在哪个地方,怎么输出及控制消息级别来过滤掉那些不需要的信息。默认生成的root logger的level是logging.WARNING,低于该级别的就不输出了

with是从Python2.5引入的一个新的语法,它是一种上下文管理协议,目的在于从流程图中把 try,except 和finally 关键字和

资源分配释放相关代码统统去掉,简化try….except….finlally的处理流程。with表达式其实是try-finally的简写形式。但是又不是全相同。with发生了异常也会关闭程序。但是with本身并没有异常捕获的功能,但是如果发生了运行时异常,它照样可以关闭文件释放资源。

Adam 是一种可以替代传统随机梯度下降(SGD)过程的一阶优化算法,它能基于训练数据迭代地更新神经网络权重。Adam 最开始是由 OpenAI 的 Diederik Kingma 和多伦多大学的 Jimmy Ba 在提交到 2015 年 ICLR 论文(Adam: A Method for Stochastic Optimization)中提出的。

「Adam」,其并不是首字母缩写,也不是人名。它的名称来源于适应性矩估计(adaptive moment estimation)。Adam 算法和传统的随机梯度下降不同。随机梯度下降保持单一的学习率(即 alpha)更新所有的权重,学习率在训练过程中并不会改变。而 Adam 通过计算梯度的一阶矩估计和二阶矩估计而为不同的参数设计独立的自适应性学习率 Adam 算法的提出者描述其为两种随机梯度下降扩展式的优点集合。

在python的类中,没有真正的私有化,不管是方法还是属性,为了编程的需要,约定加了下划线 _ 的属性和方法不属于API,不应该在类的外面访问,也不会被from M import * 导入。

在类A中,__method方法其实由于name mangling技术的原因,变成了_A__method,所以在A中method方法返回的是_A__method,B作为A的子类,只重写了__method方法,并没有重写method方法,所以调用B中的method方法时,调用的还是_A__method方法

matplotlib,风格类似 Matlab 的基于 Python 的图表绘图系统。

matplotlib 是 Python 最著名的绘图库,它提供了一整套和 matlab 相似的命令 API,十分适合交互式地进行制图。而且也可以方便地将它作为绘图控件,嵌入 GUI 应用程序中。

@tf.function

  1. 将python的函数编译成tensorflow的图结构,所以可以方便的直接使用python的语法去写深度学习的一些函数代码
  2. 易于将模型导出为GraphDef+checkpoint和saveModel
  3. 使得eager exection默认打开。如果不使用@tf.function,虽然可以使用eager exection去写代码,但是模型的中间结果无法保存,所以无法进行预测
  4. tf1.0的代码可以经过@tf.function修饰之后在tf2里面继续使用。
    此时其功能就是tf1里面的session

Learner可以是learn to classify 也可以是learn to approximate (regression),是一个广义概念。

Classifier特指learn to classify

Predictor在绝大多数时候指learn to approximate,有的时候特指具有时序结构的regression问题。

Estimator主要特指估算概率分布,也是learn to approximate的一类问题。但是不排除其他用法

pipeline,管道机制,可以看成java的string的函数调用链,就是如此了。

说实在的现在明白的差不多了,接下来就是改模型了。

那么,我应该在哪里插入呢?

它会有一个很明显的位置,而且说的很明白。即便非自回归也是用的编码器解码器那种形式,不变的,而编码器解码器如何编程呢?这个就需要看看了。

FastSpeech2 Trainer class based on FastSpeechTrainer.

example里只是,emmm,解析参数。打开输入文件,设置输出文件夹。初始化训练器。

这个trainer设计了损失值,保存情况,绘图。还有一个编译模型?训练器是训练器,模型 是模型。对,模型只是模型而已。它没有评价机制。

现在看看decode和dataset

确实又做了一点琐碎的工作。而且decode是单独运行的吧。。。这个包括数据的分批次分割。

即便是内部模型,也只是调用了keras的层而已。层自然是要另学的。添加层就在这其中。现在学学它是如何分割的。

这说明了embedding与特征组合没有关系,是在之外的。。。Feed-Forward Transformer,FTT,就是普通编码解码器吧。

phoneme,音素,说明已经处理好是这样的格式了。嵌入(embedding)层的理解,王-男人+女人=女王,就是这么个东西,这是词embedding,这个是音素embedding。或者这里统一叫:关联性编码。音素编码器吧。

然后一个positional encoding,位置编码,嗯,可以理解它为输入位置信息吧。然后是Encoder,接下来是variance adapter,方差适配器,emmm,可变信息适配器。有什么用呢?又继续位置编码。然后是解码。方差适配器里面是各种预测器,时长预测器,音高预测器,能量预测器。就开始解码了。。。来解决语音合成中的一对多映射问题(文本到语音合成中,一条文本可以对应到多条可变的语音,这些可变信息包括语音时长、音高、音量等。通过引入对应的可变信息作为解码器输入,使输入输出信息尽量匹配,来解决这个问题。

可变信息适配器(Variance adaptor)包含了多种可变信息的预测器。在本工作中引入了时长预测器、音高预测器和能量预测器。

在训练时,模型直接使用可变信息的真实值,与编码器的输出融合(哦是融合),作为解码器的输入,同时训练预测器使其拟合真实的可变信息。相当于求导改正了。

在推理阶段,模型使用预测器预测的可变信息。

可变信息预测器(Variance predictor)如图所示,由ReLU激活的2层一维卷积网络组成,每个网络后加上Layer Norm层归一化加速网络收敛、对网络参数的初始化不敏感和Dropout抛弃一部分节点不更新防止过拟合,以及最后输出标量的线性层。虽然它们的结构是一样的,它们的输入是一样的,但是它们的检测函数是不一样的。相当于挂在这上面进行训练,另外,输入其实是不一样的,它们是依次的关系,在训练中,emmm,相对而言更难收敛吧。

这个模块堆叠在音素编码器之上,并与FastSpeech2模型共同训练,使用均方误差(MSE)作为损失函数。

可变信息预测器的输出是对应的可变信息序列。其中音高预测器的输出是梅尔频谱对应的音高序列,能量预测器的输出是梅尔频谱的能量序列,而时长预测器的输出是音素的时长序列,与FastSpeech中的时长信息提取方式(使用自回归Teacher模型提取时长信息)不同,FastSpeech2 使用文字语音对齐工具(Montreal Forced Aligner,MFA)来提取更精准的时长信息。这个反向传播一下,就没问题了。

声码器的话,也是这么一个东西。

跟我想的差不多。只不过解码后就直接梅尔输出。嗯。

我们将Speaker Embedding与Energy Embedding和Pitch Emedding一起加入至编码器的输出用于后续Mel特征的预测,加入说话人的信息,可以让模型更好的学习到不同说话人之间的特征差异,来达到通过使用Speaker Embedding切换不同说话人音色的效果。这就是重心了。是解码了之后仍要进行melgan。

行,接下来就是普通的,完善工作。

那么接下来怎么做呢?

就好像是,改变了一点什么。它是松耦合的。

我之前用fastspeech训练出来什么?基础模型。然后现在其实可以用了。然后再加上一个embeding,就改变声色了。

但我要如何使用那个模型呢?用就是loadmodel,然后开始合成。它可能训练与合成都用同一套代码,也就是model,训练时不用改,合成时添加进去就行了。

那么这个embedding就要提取出这个特征,并要正确地修改中间数据。那么这个embedding该怎么做呢?它好像是一个单独的东西唉。

它的输入只是一小段语音,输出却是一个不知道是什么东西。这个东西要怎么训练呢?反正就是一个输入,一个输出嘛,不同人音色,然后相应的输出,就是如此。

接下来就是看看embedding怎么做。

自动语音识别技术(Automatic Speech Recognition)是一种将人的语音转换为文本的技术。TTS则相反。

传统的解决这个问题的方法主要基于GMM(高斯混合模型)来将声音特征映射为低维的向量,比如最典型的i-vector。i-vector是通过高斯混合模型来实现处理声色的。

LSTM 通过门控机制使循环神经网络不仅能记忆过去的信息,同时还能选择性地忘记一些不重要的信息而对长期语境等关系进行建模,而 GRU 基于这样的想法在保留长期序列信息下减少梯度消失问题

相当简单且可理解的神经网络模型:门控循环单元(GRU)。GRU 旨在解决标准 RNN 中出现的梯度消失问题。GRU 也可以被视为 LSTM 的变体,因为它们基础的理念都是相似的,且在某些情况能产生同样出色的结果。

  • 为什么不适用 softmax函数呢,softmax最终的类别数是确定的,而Triplet loss学到的是一个好的embedding,相似的图像在embedding空间里是相近的,可以判断是否是同一个人脸。

实验结果证明deep speaker在speaker verification、speaker identification(text independent)等任务上都有提升,其表现超过了DNN-based i-vector baseline。但是,用其合成呢?当然,这样做的确更清晰了。

模型首先将audio文件进行处理,然后通过DNN来提取特征,之后经过sentence average、线性变换和length normalization得到speaker embedding,训练的损失函数是triplets loss。

深度网络难以训练,梯度消失,梯度爆炸,老生常谈,不多说,resnet 解决了这个问题,并且将网络深度扩展到了最多152层。在普通的卷积过程中加入了一个x的恒等映射(identity mapping),专家把这称作 skip connections  或者 shortcut connections

比如人类识别杯子里的水烫不烫

一杯水,我摸了一下,烫,好,我的神经开始运转,最后形成理论杯子里的水烫,这显然不对

又一杯水,我一摸,不烫,好嘛,这咋办,认知混乱了,也就是无法得到有效的参数,

那人类是怎么办呢?

我们不止是摸一摸,而且在摸过之后还要把杯子拿起来仔细看看,有什么细节可以帮助我们更好的识别,这就是在神经经过运转后,又把x整体输入,

当然即使我们拿起杯子看半天,也可能看不出任何规律来帮助我们识别,那人类的作法是什么呢?我记住吧,这种情况要小心,这就是梯度消失了,学习不到任何规律,记住就是恒等映射,

这个过程和resnet是一致的。

1. 当梯度消失时,模型就是记住,长这样的就是该类别,是一个大型的过滤器

2. 在网络上堆叠这样的结构,就算梯度消失,我什么也学不到,我至少把原来的样子恒等映射了过去,相当于在浅层网络上堆叠了“复制层”,这样至少不会比浅层网络差。

3. 万一我不小心学到了什么,那就赚大了,由于我经常恒等映射,所以我学习到东西的概率很大。

明白咋回事了,但是,怎么用于TTS呢?实际上,这个embedding仅仅是用来对照,对照是没问题,如何生成呢?其实不用生成,即便是生成,也是有生成的方差,就是如此。

再多看看一些文献。

fastspeech是如何求导的呢?编码解码模型反正也是反向传播的,这个并没有什么问题。

那么,这个里面的插件该如何运作呢?它这是加入了什么信息呢?

在训练时,模型直接使用可变信息的真实值,与编码器的输出融合,作为解码器的输入,同时训练预测器使其拟合真实的可变信息。真实的可变信息就真的是已经预先处理好的tag。大致明白了。如何融合,可能就是简单加上。

在推理阶段,模型使用预测器预测的可变信息。

可变信息预测器的输出是对应的可变信息序列。其中

音高预测器的输出是梅尔频谱对应的音高序列,

能量预测器的输出是梅尔频谱的能量序列,

而时长预测器的输出是音素的时长序列

FastSpeech2 使用文字语音对齐工具(Montreal Forced Aligner,MFA)来提取更精准的时长信息。大致明白了。

如果是一个embedding的话,也只是简单的加入融合。那么如何训练呢?自然结合在一起训练了。只不过其训练方式稍微与其他的预测器有一些差异而已。

那么接下来怎么做呢?如何融合fastspeech和speakerembedding?

很显然,这个需要重新训练,联合训练,就是如此。

fastspeech就是在正向过去就过去了,反向回来的时候,是分开误差函数的,过程中反向传播。

我之前只是一次性地输入进很多参数而已。我要改的话,一是添加上这个模块,二是解决好它的反向传播的问题,三是搞好它的输入问题。最后一起训练,完成。

我大致都能猜到那个地方。插入的embedding肯定也是一个模块。

分三步走,找到位置插入一个空白模块,你至少知道上下文的关系。搞好输入输出。

做一个简单的神经网络模块。能够实现反向传播。当然深究的话别人弄。但至少自己的也能差不多能运行。

基本就做完了,然后考虑一下这个必要的问题,写写论文。

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值