语音助手通常拥有多种不同的语音合成器,这些合成器在表现力、个性、语言和说话风格等属性上各不相同。支撑这些不同应用的机器学习模型可能具有完全不同的架构,将这些架构集成到单个语音服务中可能是一个耗时且具有挑战性的过程。
为了使这个过程更简单快捷,某中心的文本转语音团队开发了一个通用模型集成框架,使我们能够以快速且可扩展的方式定制生产语音模型。
模型多样性
最先进的语音模型通常使用两个大型神经网络从文本输入合成语音。第一个网络称为声学模型,接收文本作为输入并生成梅尔频谱图,这是一种随时间表示语音音高和能量等声学参数的图像。第二个网络称为声码器,将梅尔频谱图作为输入并产生语音音频波形作为最终输出。
虽然我们已经发布了支持各种说话风格的通用声码器架构,但我们仍然使用不同的声学模型架构来生成这种多样化的说话风格。
声学模型最常见的架构依赖于注意力机制,该机制学习输入文本的哪些元素与输出频谱图的当前时间片段最相关。通过这种机制,网络隐式地建模了文本不同部分的语音持续时间。该模型还使用"教师强制"技术,即使用先前生成的语音帧作为输入来产生下一帧。虽然这种架构可以生成富有表现力和自然声音的语音,但容易出现清晰度错误,如含糊不清、丢词或重复词语,并且错误很容易从一帧传播到下一帧。
更现代的架构通过显式建模文本块的持续时间并并行生成语音帧来解决这些问题,这比依赖先前生成的帧作为输入更高效和稳定。为了对齐文本和语音序列,模型简单地"上采样"或重复其对文本块的编码,重复次数由外部持续时间模型指定的语音帧数决定。
在不同上下文中使用的复杂文本转语音模型的持续演进,创造了对能够处理所有这些模型的可扩展框架的需求。
集成挑战
要将声学模型集成到生产中,我们需要一个组件来接收输入文本话语并返回梅尔频谱图。第一个困难是语音通常是按顺序块生成的,而不是一次性合成的。为了最小化延迟,我们的框架应尽快返回数据。将整个模型包装在代码中并通过单个函数调用处理所有内容的简单解决方案将慢得不可接受。
另一个挑战是调整模型以与各种硬件加速器配合工作。例如,为了受益于高性能的某机构推理运行时,我们需要确保所有张量具有固定大小。这意味着我们需要:
- 添加将较长话语分割成适合特定输入大小的较小块的逻辑
- 添加确保适当填充的逻辑
- 决定哪些功能应由模型直接处理,哪些应由集成层处理
当我们想在通用GPU上运行相同模型时,我们可能不需要这些更改,如果框架能够轻松在不同上下文之间切换将会很有用。因此,我们将文本转语音模型解耦为一组更专业的集成组件,能够执行所有必需的逻辑。
集成组件
集成层将模型封装在一组能够将输入话语转换为梅尔频谱图的组件中。由于模型通常在两个阶段运行——预处理数据和按需生成数据——使用两种类型的组件很方便:
- SequenceBlock:接收输入张量并返回转换后的张量
- StreamableBlock:按需生成数据,并接收其他StreamableBlock的结果和/或由SequenceBlock生成的数据作为输入
这些简单的抽象在创建声学模型变体方面提供了极大的灵活性。
声学模型由以下部分组成:
- 两个编码器,将输入文本嵌入转换为一维表示张量
- 一个上采样器,根据编码器返回的数据创建中间语音长度序列
- 一个解码器,生成梅尔频谱图帧
整个模型封装在名为StreamablePipeline的专用StreamableBlock中,该块恰好包含一个SequenceBlock和一个StreamableBlock。
集成层
声学模型作为插件提供,我们称之为"addon"。一个addon包含导出的神经网络,每个网络表示为一组命名符号和参数,以及配置数据。其中一个称为"stack"的配置属性指定了应如何连接集成组件以构建工作集成层。
这种JSON格式使我们能够轻松进行更改。例如,我们可以创建一个在特定硬件加速器上并行运行所有序列块的专用组件,并将其命名为CustomizedEncoders。在这种情况下,配置规范中唯一的更改是将名称"Encoders"替换为"CustomizedEncoders"。
使用具有额外诊断或数字信号处理效果的组件运行实验也很简单。新组件的唯一要求是扩展两个通用抽象之一;除此之外没有其他限制。根据框架设计,甚至用一个完整的嵌套序列到序列堆栈替换一个StreamableBlock也是完全可以的。
该框架已在生产中使用。它是我们最近成功集成最先进的文本转语音架构和传统模型的重要支柱。
更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)或者 我的个人博客 https://blog.qife122.com/
对网络安全、黑客技术感兴趣的朋友可以关注我的安全公众号(网络安全技术点滴分享)
公众号二维码
公众号二维码