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的网络模型很近似,我们来看一下实际的编码: 生成器的模型代码:
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
判别器代码
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
分类器代码
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小时左右,感兴趣的可以进行复现一下。
参考文章: