李宏毅 自然语言处理(Voice Conversion) 笔记

前一章笔记:李宏毅 自然语言处理(Speech Recognition) 笔记

引入

什么是voice conversion?

输入一段声音,输出另一段声音,我们希望这两端声音:内容一样,其他方面不一样(这个其他方面最常见的是:说话的人,比如领结变声器)。

为什么要变成另一个人说呢?同一句话,不同人说的效果是不一样的;还可以拿来骗人(什么一天一个入 狱 小 技 巧);还可以做个人化的语音合成系统;歌声转换(这个今年还蛮常见的,经常在B站刷到《假如xxx唱xxx》);隐私保护(声音里有很多信息,虽然这个例子没有见过,但是B站上确实看到有人通过一张照片推测拍摄地点,还蛮震惊的。老师举的例子就是可以搞那种把小孩子的声音转换成父母的声音的对讲系统,这样外面按门铃的人就觉得有父母在家这个样子)。

还可以做speaking style的转换。可以改变说话的情绪(比如人说话很温柔,即使生气听起来也不严重);把正常的声音转化成Lombard的声音(听老师给的例子,有点类似于我们平常打电话和在嘈杂的环境里打电话的区别,不仅仅是音量变化,听起来有点像喊);把呓语转化成正常的声音(比如在图书馆/其他不适合大声说话的场所打电话,让电话另一段听正常的声音);唱歌技巧up

增进一段声音的可理解性。比如有人说话不清楚(比如有小朋友啊老人啊说话会比较黏黏的听不清楚),或者是口音上的不好理解。保留说话的人的特性,但是更好懂。

做data augmentation。把男生和女生的声音互相转化,这样就多了一倍的数据;把干净的声音转化成有噪声的声音,或者反过来

需要说明,在voice conversion的时候,输入和输出的长度可以是不一样的(甚至不一样更好,不同的口音说一句话的长度不一样很正常)。但是在很多文献中都采用输入和输出相同(这样能让模型简单一些,不需要用seq2seq)。

输出也是acoustic feature sequence,但是这一串向量往往不能直接转化成声音信号。假设这一串向量是一个spectrumgram,转成声音信号还差一个phase(相位)。需要另外一个model做vocoder,吃acoustic feature当做输入,直接输出声音信号。这里vocoder可以采用传统的信号处理的方法(不见得能得到好的结果,我们在听合成的时候听到的那种假假的声音往往就是这里的问题),也可以用DL。

在本章节中不会涉及到怎么把acoustic feature转化成声音信号,只是得到acoustic feature(因为这一方法并不是仅仅用于voice conversion)

voice conversion可以按照训练资料分为两类。

成对的资料:

我们很难收集到大量的成对的资料。可以采用比较好的pre-train的model。先把seq2seq的model pre-train好,再用少量的资料去fine-tune。也可以采用语音合成的方法(这里举例是让谷歌把别人说过的话再说一遍,这样就可以得到一个把所有人说的话都转化成谷歌声音的model)。

不成对的资料:

每个说话的人说的内容甚至说的语言都是不一样的,让model把一个人的声音转化成另一个人的声音。

这里有两个方法:feature disentagle&direct transformation。

Feature Disentangle

feature disentangle:声音信号中包含了很多维度的信息,可能包含了内容的信息(文字),说话人的信息,背景的信息。feature disentagle要做的就是把这些混在一起的信息分开。我们不仅仅可以把说话人的信息提取出来,替换,我们也可以把情绪/口音的部分提取出来进行替换。在之后的例子中都只涉及到speaker的转换,但是应注意到其实都可以转化。

content encoder把只和文字内容有关的部分提取出来,speaker encoder得到一句话,忽略内容,只把与speaker特征有关的部分提取出来。接下来需要一个decoder,会根据两个特征念出来这句话的内容。

这样,只要吧speaker encoder这边的特征替换成别人说话的特征就能得到其他人说这句话的语言。

我们希望不同的encoder抽取的是不同的信息。

但是我们怎么确保一个encoder只抽content,一个encoder只抽speaker呢?如果只是像一般的autoencoder那样end-to-end的train,输入一段声音信号,中间输出什么也不管,直接吧中间输出的转回声音信号,没道理content encoder和speaker encoder就按照我们的要求提取信息。->加一些额外的东西。

在训练的时候,我们知道每句话是谁说的,那就不用speaker encoder了,每一个speaker就是由一个one-hot vector表示,比如:如果是speakerA,对应的speaker的code就是10,如果是speakerB就是01。 

但是也存在问题:没有办法合成出新的speaker的声音

有几个不同的speaker就要开响应长度的向量(one-hot),假设训练资料中有10个speaker,就需要长度为10的向量,如果我们现在来一个新的speaker,就要重新训练模型,用原来的模型没办法合成第十一个人的声音。

解决方法还可以是提前训练好一个speaker encoder(输入一段声音信号,输出一个向量,这个向量代表了speaker的特征)。

怎么确保content encoder抽出来的就只和文字内容有关呢?->常见的方法,直接把一个语音识别系统塞在content encoder这里,当做content encoder来用。

其他方案:加上GAN,让content encoder不要encode speaker的信息。可以train一个discriminator,作为一个speaker classifier,判断向量来自于哪个speaker。而content encoder要做的就是想办法去骗过这个speaker classifier。speaker classifier和content encoder是交替训练的。希望content encoder可以成功的骗过speaker classifier->代表content encoder的输出没有带有speaker的任何信息。

实际上,我们可以通过设计网络的架构让它encode我想让它encode的东西。可以通过设计,让content encoder去encode content的信息,让speaker encoder去encode speaker的信息。给encoder不同的架构。

这里举的例子在image transfer中已经有应用了。

为了让content encoder去encode content的信息,在content encoder里面加了一个instance normalization->可以帮助去掉speaker的信息。

那么instance normalization做的是什么呢?

这里的encoder的架构就像是LAS里面的encoder,很多层的CNN,首先input的是声音信号,用1-D的convolution扫过这排声音信号得到一排数值,

再用另一个filter也得到一排数值

通过一组filter以后,每一小块声音信号都会变成一个vector(即:通过1-D convolution的layer之后会得到一个vector sequence)

instance normalization就作用在这个vector sequence上面,对这些vector的同一个dimension做normalization,会计算出这些vector的同一个dimension的mean和variance,然后减去mean除以variance。因此这些vector的同一个dimension的mean都会是0,variance都是1。以往这种方法多用在input feature上,在这里用在encoder的hidden layer上。

那么为什么这种方法可以去掉speaker的特性呢?

我们可以认为在CNN里面(1-D convolution里面,每一个filter其实就是抓声音信号中的某一种pattern,所以每一个row都代表声音信号中某一个pattern是否出现。)

比如,有的抓高频的信号,有的抓低频的信号,那么男生的声音进来低频的filter输出比较大,高频的比较小,女生的声音进来,高频的filter的输出比较大,低频的filter输出的比较小。

做normalization之后,就相当于吧speaker的特征去掉了(没有哪个filter的值特别大)

那么怎么让speaker encoder去encode speaker的信息呢?

采用adaptive instance normalization(只影响speaker的信息)

在decoder中,也有instance normalization,也会对CNN输出的每一个row,做normalization,去掉speaker的信息,那这时,怎么输出speaker的信息呢(来自encoder)。

speaker encoder会输出一个vector,这个vector通过两个transform之后分别产生两个vector γ β,接下来,γ 和 β会去影响做完instance normalization的结果。

但是实际上产生声音的效果并不都会很理想。其实model在training的时候,从来没有考虑过要做voice conversion这件事。model在training的时候,content encoder和speaker encoder其实吃的是同一个speaker的信息,并且是同一个句子的信息。在training的时候用的是minimize autoencoder的reconstruction error,但是在testing的时候,model要做的并不是autoencoder,而是voice conversion->model发现吃的可以是不同的speaker的信息。

idea:做2nd stage training

在training feature disentangle的时候从来没有把voice conversion考虑进来->考虑在training的时候把voice conversion考虑进来。

可以给content encoder和speaker encoder不同的speaker->在training的时候sample一个句子给content encoder,再sample一个speaker给speaker encoder,让decoder看到不同的speaker。

这么做的问题在哪里呢?

如果给不同的信息,最后要产生什么样的语音信息呢?这是没有ground truth的,因此没办法训练。

这里的思路是引入GAN的概念,train一个discriminator,这个discriminator的任务是判断decoder的声音信号听起来是真的声音信号还是生成的声音信号。虽然不知道合成的声音信号听起来应该是什么样子的(不知道ground truth),但是我们也可以确保decoder输出的信号像真实的声音信号。还可以加上一个speaker classifier,判断声音信号是不是某个人讲的。假设我们给的是B说‘hello’的声音,要合成A说'hello'的声音,虽然我们不知道A说‘hello’是什么样子,但是有了speaker classifier以后,decoder会想办法让speaker classifier把合成出来的声音信号分类成A发出的声音。

如果直接update decoder的参数让decoder去骗过speaker classifier可能训练不出来。tip是加一个patcher。patcher也是一个model,吃的input和decoder一样(content encoder的输出+speaker encoder的输出),decoder得到一段声音信号,patcher也产生一段声音信号,这一段声音信号会加到decoder产生的声音信号上,所以这个patcher的作用是打补丁。

Direct Transformation

Cycle GAN

直接把A的声音转成B的声音,采用图像上常用的cycleGAN

吃进来X的声音,经过一系列的转化(train一个generator),变成Y的声音。

但是我们并不知道X的声音转成Y的声音听起来应该是什么样子的,没有ground truth,那么怎么训练这个generator呢?需要一个discriminator,只要提供给discriminator很多Y的声音,然后discriminator就会去学会去鉴别一段声音信号是否是Y的声音。这个discriminator吃一段声音信号会output一个scalar,代表输出的声音信号听起来像不像Y的声音。

generator的目标就是骗过discriminator。

如果只是train一个discriminator和一个generator是不够的,generator可能学到的就是无论输入的是什么就只管输出Y最常说的内容

因此我们还需要加另一个generator,这个generator负责把Y的声音转回X的声音,让输入的声音信号和输出的声音信号越接近越好

在train cycle GAN的时候还有小tip:在trainX->Y的generator的时候不仅可以喂X的声音让转成Y的声音,还可以多加一个训练的目标,直接喂Y的声音,让直接合成一模一样的Y的声音,让训练的更稳定一点。

同样也可以先把Y的声音转成X的声音,加一个discriminator,这个discriminator判断输出是不是像X的声音,再用另一个generator把X的声音转回Y的声音,一样要有cycle consistency 的loss

StarGAN

如果我们现在有多个speaker,这个想法就不太适用了。假设现在有四个speaker,我们就需要在4个speaker之间两两做cycle GAN

改一下cycle GAN。在starGAN里,generator要做很多事情,可以把输入的各式各样的声音信号转成我们需要的speaker的声音。

首先给generator一段声音信号(要被转的声音信号)si的声音信号,要转成sj的声音。

可以把每个speaker ont-hot,每个speaker都是一个特定的向量。也可以有一个已经pre-train好的speaker encoder,这个encoder可以把每个speaker的声音用一个continuous的向量表示,etc。

discriminator也要做一些改变,原来的discriminator是吃一段声音信号,判断这段声音信号是不是某个人讲的。

这里的discriminator也要吃一个speaker的声音信号,现在discriminator要做的是鉴别吃进来的信号是不是某个speaker讲的。

starGAN的运作方式和cycle GAN大同小异(图片上方就是cycle GAN)

在做starGAN的时候先随便sample一个speaker的声音(比如sk的声音),再随便sample一个speaker(比如si),generator就知道我们要把speaker sk的声音转化成speaker si的声音,然后就把si的声音合成出来。

discriminator会去判断合成的声音是不是si的声音。discriminator为什么能够判断呢?是因为我们也会把si的声音信号丢给discriminator。

接着我们会把同一个generator拿来,现在给另一个speaker,sk的信息,这时generator会把声音信号转成sk的信号,让输出和输入越接近越好

两个方法也许可以合成(比如把encoder和decoder放在generator里面?)

其他方法

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/588691.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[设计模式 Go实现] 创建型~建造者模式

建造者模式(Builder Pattern)使用多个简单的对象一步一步构建成一个复杂的对象。这种类型的设计模式属于创建型模式,它提供了一种创建对象的最佳方式。 一个 Builder 类会一步一步构造最终的对象。该 Builder 类是独立于其他对象的。 代码实…

每日一题——LeetCode977

方法一 个人方法&#xff1a; 以示例1为例&#xff1a;把[-4,-1,0,3,10] 中n<0的元素拆分出来&#xff0c;把他们的平方从小到大放入arr数组&#xff0c;则arr[0,1,16] ,那数组就还剩[3,10] 对于剩下的元素&#xff0c;看arr里面有没有比他们平方更小的元素先放入res数组&…

vue3-12

需求是用户如果登录了&#xff0c;可以访问主页&#xff0c;如果没有登录&#xff0c;则不能访问主页&#xff0c;随后跳转到登录界面&#xff0c;让用户登录 实现思路&#xff0c;在用户登录之前做一个检查&#xff0c;如果登录了&#xff0c;则token是存在的&#xff0c;则放…

回顾2023,我的编程学习之旅

文章目录 前言我与C语言初识C语言简易扫雷游戏二进制的美妙神奇的指针强大的结构体灵活的动态内存管理总结 我与竞赛我与CSDN结语 前言 6月8号高考结束了&#xff0c;虽然还没有出分&#xff0c;但是也大致规划好自己想学什么专业了&#xff0c;没错就是计算机&#xff0c;出分…

RedisTemplate自增时保证原子性的lua脚本限制接口请求频率

场景&#xff1a;限制请求后端接口的频率&#xff0c;例如1秒钟只能请求次数不能超过10次&#xff0c;通常的写法是&#xff1a; 1.先去从redis里面拿到当前请求次数 2.判断当前次数是否大于或等于限制次数 3.当前请求次数小于限制次数时进行自增 这三步在请求不是很密集的时…

yarn run dev运行ant design pro项目报错-‘max‘ 不是内部或外部命令

运行ant design pro项目报错&#xff1a; >>yarn run dev yarn run v1.22.19 $ npm run start:dev > ant-design-pro6.0.0-beta.1 start:dev > cross-env REACT_APP_ENVdev MOCKnone UMI_ENVdev max dev max 不是内部或外部命令&#xff0c;也不是可运行的程序 …

PyTorch中常用的工具(4)Visdom

文章目录 前言3.2 Visdom 前言 在训练神经网络的过程中需要用到很多的工具&#xff0c;最重要的是数据处理、可视化和GPU加速。本章主要介绍PyTorch在这些方面常用的工具模块&#xff0c;合理使用这些工具可以极大地提高编程效率。 由于内容较多&#xff0c;本文分成了五篇文…

影视后期: PR调色处理,调色工具面板介绍

写在前面 整理一些影视后期的相关笔记博文为 Pr 调色处理&#xff0c;涉及调色工具面板简单认知包括 lumetri 颜色和范围面板理解不足小伙伴帮忙指正 元旦快乐哦 _ 名词解释 饱和度 是指色彩的鲜艳程度&#xff0c;也被称为色彩的纯度。具体来说&#xff0c;它表示色相中灰色…

从马尔可夫奖励过程到马尔可夫决策到强化学习【01/2】

一、说明 关于马尔可夫过程&#xff0c;如何将马尔可夫决策转化成决策依据&#xff0c;这里介绍的基本的思想路径&#xff0c;为读者将来设计和应用决策模型提供理论上的参考。 这是了解强化学习的一系列基础文章的后续文章。如果您有兴趣了解强化学习&#xff0c;请查看此处。…

运维系列Nginx:设置黑/白名单IP限制

黑/白名单IP限制访问配置 第一种&#xff1a;deny和allow指令属于ngx_http_access_module&#xff0c;nginx默认加载此模块&#xff0c;所以可直接使用。这种方式&#xff0c;最简单&#xff0c;最直接。设置类似防火墙iptable&#xff0c;使用方法&#xff1a; # 白名单设置&a…

【数值分析】choleskey分解,matlab实现

平方根分解&#xff08;Choleskey分解&#xff09; A G G T , A 对称正定 AGG^ \mathrm T \,\,,\,\, A对称正定 AGGT,A对称正定 A L D M L D L T ( L D 1 / 2 ) ( L D 1 / 2 ) T G G T \begin{align*} A LDM LDL^ \mathrm T(LD^{1/2})(LD^{1/2})^ \mathrm TGG^ \mathrm T…

huggingface的tokenizer解读

文章目录 前言一、huggingface的tokenizer含义1、含义2、整体概括 二、加载lmsys/vicuna-7b-v1.5模型的tokenizer三、调用tokernizer方法四、字符串的tokens应用1、tokenizer应用2、tokenizer进行token分词(tokenizer.tokenize)3、tokens转模型识别ids(tokenizer.convert_token…

STM32F407-14.3.10-表73具有有断路功能的互补通道OCx和OCxN的输出控制位-00x10

如上表所示&#xff0c;MOE0&#xff0c;OSSI0&#xff0c;CCxE1&#xff0c;CCxNE0时&#xff0c;OCx与OCxN的输出状态取决于GPIO端口上下拉状态。 ---------------------------------------------------------------------------------------------------------------------…

Python 中的运算符介绍(1)

算数运算符 常见的% 、//、/ 用法 赋值运算符 赋值运算&#xff1a;将等号右边赋值给等号左边 常见场景&#xff1a; 比较运算符 代码解析&#xff1a; 逻辑运算符 位运算符&#xff08;了解&#xff09; 三目运算符 身份证运算符 成员运算符

考研后SpringBoot复习2—容器底层相关注解

考研后SpringBoot复习2 SpringBoot底层注解学习 与容器功能相关的注解与springboot的底层原理密切相关 组件添加注解configuration Spring Ioc容器部分回顾 包括在配置中注册&#xff0c;开启包扫描和注解驱动开发等需要在进行重新的学习回顾 实例 package com.dzu.boot;imp…

zyqn-arm软中断设置

所有SGI都是边缘触发的&#xff0c;sgi的灵敏度类型是固定的&#xff0c;不能改变。 软中断初始化流程 1、初始化异常处理 2、初始化中断控制器 3、注册异常处理回调函数到CPU 4、连接软中断信号与注册软中断回调函数 5、使能中断控制器中的软中断中断 6、使能异常处理 …

Android 10.0 mtp模式下PC上显示两个内部存储的问题解决办法

1. 前言 在10.0的系统产品开发中,在mtp模式下,有些时候会在pc端显示两个手机内部存储空间,所以这时候显得特别不友好,出于对产品 的完善,所以要求解决这个问题,接下来分析下这个问题 2.mtp模式下PC上显示两个内部存储的问题解决办法的核心类 frameworks\base\media\jav…

k8s学习 — 各章节重要知识点

k8s学习 — 各章节重要知识点 学习资料k8s版本0 相关命令0.1 yaml配置文件中粘贴内容格式混乱的解决办法0.2 通用命令0.3 Node 相关命令0.4 Pod 相关命令0.5 Deployment 相关命令0.6 Service 相关命令0.7 Namespace 相关命令 1 k8s学习 — 第一章 核心概念1.1 Pod、Node、Servi…

Python装饰器的专业解释

装饰器&#xff0c;其实是用到了闭包的原理来进行操作的。 单个装饰器&#xff1a; 以下是一个简单的例子&#xff1a; def outer(func):print("OUTER enter ...")def wrapper(*args, **kwargs):print("调用之前......")result func(*args, **kwargs)p…

【Vue2+3入门到实战】(17)VUE之VueCli脚手架自定认创建项目、ESlint代码规范与修复、 ESlint自动修正插件的使用 详细示例

目录 一、本节内容二、VueCli 自定义创建项目三、ESlint代码规范及手动修复1.JavaScript Standard Style 规范说明2.代码规范错误3.手动修正 四、通过eslint插件来实现自动修正 一、本节内容 VueCli脚手架自定认创建项目ESlint代码规范与修复ESlint自动修正插件 二、VueCli 自…