之前讲的那篇CGAN都是有监督学习,那能不能无监督学习呢?当然可以啦,大多数情况我们很难弄到一个个对应匹配的数据,比如做图片风格转换,你很难弄到同一个图片的不同种风格,里面东西还是一模一样的,再比如,你很难把一个人的声音风格转换到另外一个人声音上,因为可能你说的是中文,另外一个人说英文,找不到一模一样的发音,所以我们需要研究无监督学习,只需要两堆数据,可将某种特征从一堆转到另一堆。
从文献上看有两大类的做法:
我们要learn一个生成器,他可以将X domain的东西转换为 Y domain的东西;现在我们X domain的东西有一堆,Y domain的东西有一堆,但是合起来的pair没有。那生成器怎么知道给定X domain的东西输出Y domain的东西呢?
因此生成器不仅要骗过判别器,还要让输出的东西与输入有关
如何做到输出与输入有关呢?
这种方法利用一个判别器,判断生成器输出的图片属于 x domain 或者 y domain,从而训练 生成器使得其输出的图片尽可能贴近于 y domain。
但这样的问题是生成器可能输出和输入不相关的图像。
有很多种方法可以解决这个问题,最简单粗暴的方法就是直接无视,因为直接转换下,生成器的深度不足以产生和输入图像相差过大的输出结果。也就是说如果你的生成器网络很浅,输入和输出会特别像,这时候就不需要额外的处理;如果你的生成器网络很深,输入和输出会真的很不一样,这时候就需要额外的处理;
用一个已训练好的网络,如VGG;把生成器的输入和输出image,统统丢给这个pre-train好的网络,就会输出两个embedding vector;接下来在训练的时候,一方面生成器要骗过判别器,同时希望两个embedding的vector不要差太多。
注意:cycle-GAN中存在的问题:cycle-GAN会把输入的东西藏起来,然后再output的时候再呈现出来;例子:输入和输出很像屋顶上都有黑点,但是中间image屋顶的黑点却没有。中间产物没有黑点,那你是怎么只通过中间层image得到有黑点的屋顶,一个解释是生成器有很大的能力将信息藏在中间image里面,如很小的数值让你看不出来。既然cycle-GAN是藏信息的,是不是失去了cycle-GAN的意义了呢?因为就是这种结构就是为了让第一个生成器的输出和输入不要差太多,但是你现在这种结构是藏信息的,会不会中间层就会和输出差距很大。这种结果,机器可能自己会学习隐藏东西,结构失去了意义…
下面看Cycle GAN的实例:
https://github.com/Aixile/chainer-cyclegan
全部转为白毛:
除了 cycle GAN外,还有其他类似的方法,如Disco GAN、Dual GAN 等,它们和 Cycle GAN 都比较相似。
还有一种叫做star-GAN,用于多个domain之间的转换
理论上如果是4个domain之间的互转,你应该学12个生成器;而star-GAN是只学习了一个生成器就可以在多个domain之间互转;
具体怎么做的呢?
下面是实际的例子: 判别器做的事是首先判断它是real的还是fake;然后还有判断它是不是目标的domain;domain的表示是很多属性编码的,目标domain中:第一个10011黑色头发男性年轻、00000表示没有情绪、10表示只表示前面没有情绪;原始domian中:00101表示棕色女性年轻,00000表示没有情绪,10表示不显示情绪;
下面同样的原理用于情绪:
我们想要做到:
真人图片丢到 E N x EN_x ENx,可以抽出真人的特征到latent vector(橙色),然后经过二次元的 D E y DE_y DEy得到对应的二次元图片
二次元图片丢到 E N y EN_y ENy,可以抽出二次元的特征到latent vector(橙色),然后经过真人的 D E x DE_x DEx得到对应的二次元图片
一般的结构为,分别训练两个编码器以编码实际图片和风格图片,再训练两个解码器以解码实际图片和风格图片,最终即可得到一条路径,可以将实际图片转换为风格图片。
由于两个auto-encoder是分开train的,所以两者之间是没有关联的;例如当你丢个X domain的人脸进去,变成一个vector,当输如Y domain的encoder中时,可能出现一个截然不同的卡通人物。因为是分开训练的,所以在latent space中每个维度的表示属性是不一样的,如上面的auto-encoder用第一维代表性别,而下面一组则用其他代表性别;
怎么解决关联?
让不同domain的decoder的最后几个hidden layer和encoder的最前面几个hidden layer的参数是共用的;通过共享参数,可能会是不同domain的image压缩到同一个latent space(潜在的空间),即同样的dimension 表示同样的属性。这样的技术被用在couple GAN 和UNIT里面。
极端的现象,公用同一个encoder和decoder,只不过在输入的时候给定1表示domain X的图片 -1表示Y domain的图片。
原来X domain和Y domain都是自己搞自己的东西,现在,用一个domain 判别器来判断这个vector是来自于X domain的image还是来自于Y domain的image。两个encoder的作用是骗过这个domain 判别器。当无法判断的时候,就是说明两者被encode到同一个空间。
将一张image经过X encoder变成code;再经过Y docoder把它解回来;然后再丢给Y domain的encoder,再透过X domain的decoder把它解回来;然后希望input和output越接近越好。
与之相似的,还有使用 semantic consistency 的方法。它让原始图像通过 ENX 输出 code,再让这个 code 通过 DEY 和 ENY 生成另一个 code,最后将两个 code 进行比较,使得其越接近越好。这种技术常用在 DTN 和 SGAN 里面。
这也就是在latent space看consistency!!!
https://github.com/Hi-king/kawaii_creator
声音转换,大家对这一项技术的起源应该都是柯南了,柯南拿着变声器然后发出毛利小五郎的声音。
声音转换注意两点,声音转换的输入端长度与输出段长度不一定是一致相等的,甚至在很多时候不相等更加好能会更好。第二点,声音转换都是基于图像形式的音频特征进行转换,也就是我们先将音频转化成为图像,然后对图像在进行端到端训练,所以我们输出的结果也是图像。 所以需要用Vocode的方式将输出的图像还原成为声音。
Vocode传统方法就是Griffin-Lim algorithm,深度学习的方法这里主要介绍WaveNet.
声音转换的方法,我们根据数据的分布可以分为2大类,一类是Parallel Data,另一类是Unparallel Data。 对于parallel data很直觉的做法就是端到端训练一个模型在进行测试。但是他会面对数据集难收集的问题。所以在实作中Unparallel Data是我们面临的比较多的。
面对不平衡音频数据,进行处理的方法可以分为2类。第一类是特征分离(Feature Disentangle),第二类是直接转换( Direct Transformation)。特征分离很好理解就是我们要将声音进转化,我们将音频的特征先进行分离一种只保留语者说话腔调的讯息,一种只保留声音的语义的信息,然后我们如果要将A的声音转化成为B的声音我们只要把A的腔调改为B的腔调语义部分进保留。(当然也可以进行情绪的转化)最后通过解码器输出结果。
Direct Transformation:这种方法我们前面也有讲过,但是我们当时是用图像来进行举例的,可以参考下面的两篇文章:
- Voice Conversion——学习笔记
- 语音转换Voice Conversion —直接转换技术
Feature Disentangle(特征解耦):可以参考以下文章:
- 机器学习-40-Feature Extraction(InfoGAN,VAE-GAN,BiGAN,Triple GAN,Feature Disentangle(Voice Conversion))
过去,用的监督学习的方法,要有一堆对应的声音:
然后训练一个seq2seq的模型就可以了,但是这个模型是有缺陷的,例如我想要变声为张学友,那很难请到张学友跟我一起念同样的句子,然后来训练,很麻烦。那如果我想要变声为尼古拉斯凯奇,那就很难搞了,因为他不会中文,就算请到他也讲不来相同的句子。
如今,我们只要收集两组声音,不用讲一样的内容就可以进行训练。
具体的效果,老师的ppt里有,可以自行查看