Li Y, Swersky K, Zemel R. Generative moment matching networks[C]//International conference on machine learning. PMLR, 2015: 1718-1727.
摘要导读
该任务的目的是通过深度生成模型来建模数据。本文提出了一种方法,通过单一的前馈传播的MLP来产生独立的样本,类似于最近的GAN。然而,训练GAN需要优化较难的minimax平衡“游戏”。相反,本文作者使用了一种称为最大均值差异(MMD)的统计假设检验技术,使得优化目标变得极为简单。该统计量可以解释为--匹配数据集和模型生成样本之间的所有阶统计量,并通过反向传播进行训练。为了验证该想法的有效性,提出将生成网络和自编码器相结合,并使用MMD来产生中间层表示然后通过解码产生样本。
最大均值差异( Maximum Mean Discrepancy)
给定两个样本集合,,目的是来判断产生这些样本的分布是否等于。MMD是回答这个问题的频率估计量,也被称为双样本检验。其含义是:通过比较两个数据集之间的统计数据,如果它们相似,那么这些样本很可能来自相同的分布。
MMD使用下面的形式来度量两组样本对应统计量的均方差:
若选择为恒等映射函数,则可以匹配到样本的均值,而选择其他合适的形式则可以用来匹配高阶矩。从上式中的红框中的形式可知,里面仅涉及到向量之间的内积,因此,这里可以应用核技巧进行转换:
通过核技巧的应用,可以隐式的将样本向量提升到一个无限维的特征空间中。当该特征空间对应到一个通用再生核希尔伯特空间时,可以证明,当且仅当时,MMD趋近于0。文章中指出,当这里使用的是高斯核时,可以使用泰勒展开式得到一个显式的特征映射,它包含无限数量的项,并涵盖所有顺序的统计量。在这种特征展开下,最小化MMD就相当于最小化两个分布的所有矩之间的距离。
模型浅析
Data Space Network
import torch
class GMMN(torch.nn.Module):
"""
The architecture is shown as Figure 1 (left).
in_dim : dimensions of inputs to the layer
out_dim : dimensions of outputs of the layer
"""
def __init__(self, in_dim, out_dim):
super(GMMN, self).__init__()
self.fc1 = torch.nn.Linear(in_dim, 64)
self.fc2 = torch.nn.Linear(64, 256)
self.fc3 = torch.nn.Linear(256, 256)
self.fc4 = torch.nn.Linear(256, 784)
self.fc5 = torch.nn.Linear(784, out_dim)
"""
Forward propagation of the GMMN
input: Input batch of samples from the uniform
"""
def forward(self, input):
h1 = torch.relu(self.fc1(input))
h2 = torch.relu(self.fc2(h1))
h3 = torch.relu(self.fc3(h2))
h4 = torch.relu(self.fc4(h3))
x = torch.sigmoid(self.fc5(h4))
return x
GMMN的思想是使用一个神经网络来学习映射。具体来说,在生成网络中有一个包含个隐藏单元的随机隐层,每个单元都独立地建立在一个先验的均匀分布之上:
其中 是一个[-1, 1]上的均匀分布,而是一个指示矩阵。这里可能是因为笔者太菜了,没有太看懂这里关于指示矩阵I[·]的描述。因此,去查看了源码,发现其实就是在[-1,1]的均匀分布上进行采样,产生随机变量然后进行模型输出。
import torch
args = ...
# 首先是通过均匀分布进行采样
# uniform random noise between [-1, 1]
random_noise = torch.rand((args.batch_size, args.noise_size)) * 2 - 1 #noise_size是GMMN的输入维度
samples = Variable(random_noise ).to(device)
# generate codes from the uniform samples
gen_samples = gmmn_net(samples)
# 最小化原始数据和生成数据之间的MMD
loss = MMD(x, gen_samples)
...
然后将向量输入神经网络,并将其确定地映射到D维数据空间中的一个向量:
为神经网络映射函数,它可以包含多层非线性,表示神经网络的参数。先验和映射共同定义了数据空间中的分布。为了生成样本,只需要从先验均匀先验中采样,然后将其通过神经网络得到。
在GAN中,采用的是博弈的思想来判断生成样本和数据样本,并缩小二者之间的差距。但这个过程需要平衡生成过程和辨别过程。因此,在本文提出的算法中,通过最小化MMD来驱动网路参数的学习。具体操作为:给定训练样本(对应于数据),由模型产生的样本为(对应于生成样本)。当MMD中对应的核函数可微时,MMD对应的目标函数也可微。如,使用高斯核
对应于的梯度为: 根据此梯度,来反向更新网络参数。Auto-Encoder Code Space Networks
AE作为一种简单的以重构为目标函数的抽取器,适当的将其和GMMN结合则可以捕获足够的统计信息用于数据空间的重构。采用二者的结合体,至少存在两点优势,(1)数据的维度可以进行显式的控制。这对类似MMD这样的统计估计器是有益的,因为产生可靠估计器所需的数据量随着数据维度的增加而增加;(2)中间code空间中的每个维度都可以代表原始数据空间中国的复杂变化。
因此在本文中,还构建了一个GMMN+AE的模型。
首先通过数据重建初始化AE,并产生中间层【data code】表示,然后将AE的权重进行冻结,通过最小化生成的code表示【generated code】和【data code】之间的MMD来训练GMMN。
在实验的过程中,作者发现在编码层中添加dropout有助于在code空间中构建一个平滑的mainfold。这种想法和收缩自编码器和降噪自编码器的原理类似。
ae_net = ...
# GMMN+AE
x= x.view(x.size()[0], -1) # 原始输入数据x
with torch.no_grad():
x= Variable(x).to(device)
_, encoded, _, _ = ae_net(x) # 使用预训练好的AE模型进行编码
# uniform random noise between [-1, 1]
random_noise = torch.rand((args.batch_size, args.noise_size)) * 2 - 1
# 此时变成了AE输出的code和GMMN生成的code之间的MMD
samples = Variable(random_noise ).to(device)
# generate codes from the uniform samples
gen_samples = gmmn_net(samples)
loss = MMD(encoded, gen_samples)
可以看出,在基于AE的GMMN的训练中,AE的encoder只负责输出编码的code。而decoder的部分则用于后续的样本的生成。
noise = torch.rand((1, args.noise_size)) * 2 - 1 #随机采样
encoded = gmmn_net(Variable(noise)) #编码
_, decoded = ae_net(encoded) #生成
pytorch源码地址:https://github.com/gxwangupc/GMMN-PyTorch
网友评论