前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >机器学习会议论文(三)StarGAN-VC实现非并行的语音音色转换

机器学习会议论文(三)StarGAN-VC实现非并行的语音音色转换

作者头像
千与编程
发布2023-04-28 13:43:44
4360
发布2023-04-28 13:43:44
举报
文章被收录于专栏:公众号:千与编程
  1. The address of paper STARGAN-VC: NON-PARALLEL MANY-TO-MANY VOICE CONVERSION WITH STAR GENERATIVE ADVERSARIAL NETWORKS 论文地址:https://arxiv.org/pdf/1806.02169.pdf

2.The introduction starGAN-VC是将一篇语音方向的论文,在上一篇论文中我们介绍了starGAN的网络结构以及工作原理,以及starGAN是如何实现多域的图像风格迁移,但是starGAN-vc则是进行了领域的融合与迁移,vc是(voice conversion),也就是将图像领域的starGAN放入语音领域,进行语音的音色转换,在图像领域我们实现性别的转换,比如将一张male picture转换为female picture,当然指的是风格迁移。starGAN-VC则是将模型放入语音,将male voice转换为female voice。 3.The related work starGAN与StarGAN-vc的网络模型相似,变化不大,但是图像信号与语音信号的差别比较大,语音信号是典型的时序信号,可以理解为一个一维数组的数据,对于神经网络来说处理运算的是矩阵数据,所以需要对语音信号进行预处理,才能实现网络的可以接受的数据格式 (1)对于语音信号需要进行语音信号的特征提取——梅尔频率倒谱系数(MFCC) MFCC中包涵语音信号的特征,同时以矩阵的形式进行的存储, MFCC:Mel频率倒谱系数的缩写。Mel频率是基于人耳听觉特性提出来的,它与Hz频率成非线性对应关系。Mel频率倒谱系数(MFCC)则是利用它们之间的这种关系,计算得到的Hz频谱特征。

提取语音信号MFCC的流程图:

将语音信号通过一个预加重处理,所谓预加重,就是提高语音的高频部分,使得信号变得平坦化,滤掉噪声。进行分帧,则是将语音信号进行采样,也就是将连续信号进行离散化,通常采样率为22.5khZ,就是1s内进行22.5k次采样,分帧则是每次采样的采样点个数作为一帧。 加入汉明窗函数后对每一帧进行快速傅里叶变换,FFT将时域的信号转换为频域的信号,经过FFT变换后的频域信号进行时间的拼接可以得到语音信号的声谱图。

由于得到的声谱图较大,为了得到合适大小的声音特征,通常将它通过梅尔尺度滤波器组,变换为梅尔频谱。梅尔频谱是为了让人耳对频率的感知度就变为线性。在经过倒谱分析(取对数,做DCT转换)得到梅尔频率倒谱系数(MFCC),输入网络模型进行矩阵运算。

在文章中进行了starGAN-VC与CycleGAN-VC的对比,仍然区别在于starGAN的可以进行多域的转换,实现many to many的语音音色转换。 4. The model starGAN-VC的网络模型与starGAN的网络模型很近似,我们来看一下实际的编码: 生成器的模型代码:

代码语言:javascript
复制
class Generator(nn.Module): #定义生成器Generator
    """docstring for Generator."""
    def __init__(self):  #初始化网路结构
        super(Generator, self).__init__()
        self.downsample = nn.Sequential(    #定义下采样的网络机构
            Down2d(1, 32, (3,9), (1,1), (1,4)),
            Down2d(32, 64, (4,8), (2,2), (1,3)),
            Down2d(64, 128, (4,8), (2,2), (1,3)),
            Down2d(128, 64, (3,5), (1,1), (1,2)),
            Down2d(64, 5, (9,5), (9,1), (1,2))
        )

        #定义四层上采样的网络层
        self.up1 = Up2d(9, 64, (9,5), (9,1), (0,2))
        self.up2 = Up2d(68, 128, (3,5), (1,1), (1,2))
        self.up3 = Up2d(132, 64, (4,8), (2,2), (1,3))
        self.up4 = Up2d(68, 32, (4,8), (2,2), (1,3))
       #定义转置卷积层
        self.deconv = nn.ConvTranspose2d(36, 1, (3,9), (1,1), (1,4))
#构建动态图网络结构
    def forward(self, x, c):
        x = self.downsample(x)
        c = c.view(c.size(0), c.size(1), 1, 1)

        c1 = c.repeat(1, 1, x.size(2), x.size(3))
        x = torch.cat([x, c1], dim=1)
        x = self.up1(x)

        c2 = c.repeat(1,1,x.size(2), x.size(3))
        x = torch.cat([x, c2], dim=1)
        x = self.up2(x)

        c3 = c.repeat(1,1,x.size(2), x.size(3))
        x = torch.cat([x, c3], dim=1)
        x = self.up3(x)

        c4 = c.repeat(1,1,x.size(2), x.size(3))
        x = torch.cat([x, c4], dim=1)
        x = self.up4(x)

        c5 = c.repeat(1,1, x.size(2), x.size(3))
        x = torch.cat([x, c5], dim=1)
        x = self.deconv(x)
        return x

判别器代码

代码语言:javascript
复制
class Discriminator(nn.Module):
    """docstring for Discriminator."""
    def __init__(self):
        super(Discriminator, self).__init__()
        
        self.d1 = Down2d(5, 32, (3,9), (1,1), (1,4))
        self.d2 = Down2d(36, 32, (3,8), (1,2), (1,3))    
        self.d3 = Down2d(36, 32, (3,8), (1,2), (1,3))    
        self.d4 = Down2d(36, 32, (3,6), (1,2), (1,2)) 
        
        self.conv = nn.Conv2d(36, 1, (36,5), (36,1), (0,2))
        self.pool = nn.AvgPool2d((1,64))
    def forward(self, x, c):
        c = c.view(c.size(0), c.size(1), 1, 1)
        
        c1 = c.repeat(1, 1, x.size(2), x.size(3))
        x = torch.cat([x, c1], dim=1)
        x = self.d1(x)

        c2 = c.repeat(1, 1, x.size(2), x.size(3))
        x = torch.cat([x, c2], dim=1)
        x = self.d2(x)

        c3 = c.repeat(1, 1, x.size(2), x.size(3))
        x = torch.cat([x, c3], dim=1)
        x = self.d3(x)

        c4 = c.repeat(1, 1, x.size(2), x.size(3))
        x = torch.cat([x, c4], dim=1)
        x = self.d4(x)

        c5 = c.repeat(1, 1, x.size(2), x.size(3))
        x = torch.cat([x, c5], dim=1)
        x = self.conv(x)
       
        x = self.pool(x)
        x = torch.squeeze(x)
        x = torch.tanh(x)
        return x

分类器代码

代码语言:javascript
复制
class DomainClassifier(nn.Module):
    """docstring for DomainClassifier."""
    def __init__(self):
        super(DomainClassifier, self).__init__()
        self.main = nn.Sequential(
            Down2d(1, 8, (4,4), (2,2), (5,1)),
            Down2d(8, 16, (4,4), (2,2), (1,1)),
            Down2d(16, 32, (4,4), (2,2), (0,1)),
            Down2d(32, 16, (3,4), (1,2), (1,1)),
            nn.Conv2d(16, 4, (1,4), (1,2), (0,1)),
            nn.AvgPool2d((1,16)),
            nn.LogSoftmax()
        )
        
    def forward(self, x):
       x = x[:, :, 0:8, :]
       x = self.main(x)
       x = x.view(x.size(0), x.size(1))
       return x

整个模型的工作流程由生成器进行假的图片,由判别器进行判别真假,分类器则需要进行深入的标签划分,确定具体的种类。这里的图片指的是语音信号的MFCC。 对以上的G,D,C三个模型进行优化与反向传播,使用Adam的优化方法。

5.The network architecture

网路结构中的GLU网络层能减轻梯度弥散,加速收敛。

6.The related work

使用的VCC 2018 dataset的数据集进行训练,其中包括6个男士的声音,以及6个女士的声音,进行音色的转换,在RTX2080Ti的显卡环境下,大概需要训练7小时左右,感兴趣的可以进行复现一下。

参考文章:

  1. https://blog.csdn.net/lvziye00lvziye/article/details/100132715
  2. http://www.360doc.com/content/17/0520/16/15077656_655595658.shtml
  3. https://github.com/qianyuqianxun-DeepLearning/pytorch-StarGAN-VC
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-08-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 千与编程 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档