语音代理(如Alexa)通常包含多种不同的语音合成器,这些合成器在表现力、个性、语言和说话风格等属性上各不相同。支撑这些不同应用的机器学习模型可能具有完全不同的架构,将这些架构集成到单一语音服务中是一个耗时且具有挑战性的过程。
为简化并加速这一过程,某中心的文本转语音团队开发了通用模型集成框架,能够以快速且可扩展的方式定制生产级语音模型。
模型多样性 最先进的语音模型通常使用两个大型神经网络从文本输入合成语音。第一个网络称为声学模型,以文本作为输入并生成梅尔频谱图(一种随时间表示语音音高和能量等声学参数的图像)。第二个网络称为声码器,以梅尔频谱图作为输入并生成语音音频波形作为最终输出。
虽然已发布支持多种说话风格的通用声码器架构,但仍需使用不同的声学模型架构来生成这种多样化的说话风格。
声学模型最常见的架构依赖于注意力机制,该机制学习输入文本的哪些元素与输出频谱图的当前时间片(或“帧”)最相关。通过这种机制,网络隐式建模文本不同部分的语音持续时间。
该模型还使用“教师强制”技术,即使用先前生成的语音帧作为输入来生成下一帧。虽然这种架构可以生成富有表现力且自然的语音,但容易产生清晰度错误(如含糊不清、丢词或重复词),且错误容易在帧之间累积。
更现代的架构通过显式建模文本块的持续时间并并行生成语音帧来解决这些问题,这比依赖先前生成的帧作为输入更高效和稳定。为对齐文本和语音序列,模型简单地进行“上采样”,或根据外部持续时间模型指定的语音帧数重复其文本块的编码(其表示向量)。
在不同场景(如问答、儿童故事讲述和智能家居自动化)中使用的复杂TTS模型的持续演进,催生了需要能够处理所有模型的可扩展框架。
集成挑战 将声学模型集成到生产中,需要一个接收输入文本话语并返回梅尔频谱图的组件。第一个困难是语音通常以顺序块生成,而不是一次性合成。为最小化延迟,框架应尽快返回数据。将整个模型包装在代码中并通过单一函数调用处理所有内容的简单解决方案速度会慢得无法接受。
另一个挑战是调整模型以适配各种硬件加速器。例如,为受益于高性能AWS Inferentia运行时,需要确保所有张量具有固定大小(在模型编译阶段一次性设置)。这意味着需要:
- 添加将较长话语拆分为适合特定输入大小(取决于模型)的较小块的逻辑;
- 添加确保适当填充的逻辑;
- 决定哪些功能应由模型直接处理,哪些应由集成层处理。
当希望在通用GPU上运行相同模型时,可能不需要这些更改,如果框架能够轻松在上下文之间切换将会很有用。因此,将TTS模型解耦为一组更专业的集成组件,能够执行所有所需逻辑。
集成组件 集成层将模型封装在一组能够将输入话语转换为梅尔频谱图的组件中。由于模型通常在两个阶段运行(预处理数据和按需生成数据),使用两种类型的组件很方便:
- SequenceBlock:接收输入张量并返回转换后的张量(输入可以是应用另一个SequenceBlock的结果);
- StreamableBlock:按需生成数据(例如帧)。作为输入,它接收另一个StreamableBlock的结果(块可以形成管道)和/或由SequenceBlock生成的数据。
这些简单抽象在创建声学模型变体时提供了极大的灵活性。以下是一个示例:
使用SequenceBlock和StreamableBlock抽象构建的声学模型示例。该声学模型包括:
- 两个编码器(SequenceBlocks),将输入文本嵌入转换为一维表示张量,一个用于编码文本,一个用于预测持续时间;
- 一个上采样器(StreamableBlock,以编码器结果作为输入),根据编码器返回的数据创建中间语音长度序列;
- 一个解码器(StreamableBlock),生成梅尔频谱图帧。
整个模型封装在一个名为StreamablePipeline的专用StreamableBlock中,该块恰好包含一个SequenceBlock和一个StreamableBlock:
- SequenceBlockContainer是一个专用的SequenceBlock,由一组能够运行神经网络编码器的嵌套SequenceBlocks组成;
- StreamableStack是一个专用的StreamableBlock,从上采样器解码输出并创建梅尔频谱图帧。
集成框架确保所有组件以正确顺序运行,并根据组件的特定版本,允许使用各种硬件加速器。
集成层 声学模型作为插件提供,称为“addon”。一个addon包含导出的神经网络,每个网络由一组命名符号和参数(编码器、解码器等)以及配置数据表示。其中一个配置属性称为“stack”,指定应如何将集成组件连接在一起以构建工作的集成层。以下是描述上述架构的stack属性代码:
'stack'=[
{'type' : 'StreamablePipeline',
'sequence_block' : {'type' : 'Encoders'},
'streamable_block' :
{'type': 'StreamableStack',
'stack' : [
{'type' : 'Upsampler'},
{'type' : 'Decoder'}
]}
}
]
此定义将创建一个集成层,包括:
- 一个StreamablePipeline,包含addon中指定的所有编码器(框架将自动创建所有所需组件);
- 一个上采样器,为解码器生成中间数据;
- addon中指定的解码器,生成最终帧。
JSON格式允许轻松进行更改。例如,可以创建一个在特定硬件加速器上并行运行所有序列块的专用组件,并将其命名为CustomizedEncoders。在这种情况下,配置规范中唯一的更改是将名称“Encoders”替换为“CustomizedEncoders”。
使用具有额外诊断或数字信号处理效果的组件运行实验也很简单。新组件的唯一要求是扩展两个通用抽象之一;除此之外没有其他限制。根据框架设计,甚至可以用整个嵌套的序列到序列堆栈替换一个StreamableBlock也是完全可以的。
该框架已在生产中使用。它是最近成功集成最先进TTS架构(无注意力)和传统模型的重要支柱。
致谢:Daniel Korzekwa