CS294-158 补1 基于能量的模型
admin
2023-08-16 21:41:46
0
  • 本文整理自Jakub M. Tomczak的书籍《Deep Generative Modeling》 第六章基于能量的模型
  • 本文已收录到以下专栏
  • 在本系列课程(UCB CS294-158 深度无监督学习)中介绍了一些深度生成模型,例如:
    • CS294-158 第二讲 自回归模型(autoregressive models, ARMs);
    • CS294-158 第三讲 流模型(flow-based models)
    • CS294-158 第四讲 变分自编码器(variational auto-encoders, VAEs)
    • CS294-158 第五、六讲 生成对抗网络(generative adversarial networks, GANs)
  • 本文介绍另一种基于能量的模型(energy-based models, EBMs),也是深度生成式模型
  • 本文内容
    • 引言
    • 模型构建
    • 训练
    • 模型代码
    • 受限玻尔兹曼机
    • 终评

1 引言

1.1 能量函数

  • EBMs的历史比较悠久,来自于玻尔兹曼机(Boltzmann Machines)。
  • 对数据的概率分布进行描述时,简单点就是取个高斯分布、伯努利分布的形式。这些概率分布都可以写成基于能量函数的形式(energy funciton),。对于连续变量,每个数据点对应一个概率密度函数值,对应一个能量值,如此概率分布即可写成如下玻尔兹曼分布的形式,也叫作吉布斯分布(Boltzmann/Gibbs distribution):

    • 为概率归一化的分母,也称为配分函数(partition function),

  • 由以上公式可知,概率值较高的位置对应着能力较低的点。举一个简单的例子看一下,将高斯分布以能量函数的形式表示:


1.2 使用EBMs的难点

  • 在实际使用EBMs时会遇到两个难点:
    • 1)概率未归一化,不知道配分函数
    • 2)难以从EBMs中采样,仅知道每个点对应的能量值

1.3 为什么使用EBMs?

  • 1)能量函数没有限制,可以是任意函数,可引入神经网络
  • 2)能量函数可能是多峰值的(multimodal),不需要借助混合分布
  • 3)对于离散变量与连续变量,在使用EBMs时没有区别

2 模型构建

2.1 数据与标签的联合分布

  • 假设数据集为,能量函数由神经网络参数化,这里的表示神经网络的输出。
  • 依据以上能量函数可写出的联合概率分布

  • 根据以上联合分布可写出边缘分布与条件分布

2.2 边缘分布

  • 将联合分布中的积分掉,即得到边缘分布

  • 以上分子可换一种写法,


  • 即可看成是边缘分布的能量函数

2.3 条件分布

  • 条件分布为联合分布比边缘分布,这两个分布的配分函数相同,分子之比为

  • 以上结果正是使用神经网络执行分类任务时使用的Softmax函数!有相关文献[1]表明所有分类器都可以看作是能量模型。

2.4 模型表示

  • 联合分布的log可写为如下形式




  • 可以看到这两项中包括共同的神经网络,计算图如下:


3 训练

  • 在训练部分即需要对2.4节中的联合似然进行求导,第一项是训练分类器的损失函数,求导比较简单,第二项求导就比较复杂了,公式如下


  • 上式导数比较难以计算,因为:最后含有一项期望值,这个期望目前无法解析计算,并且从模型中采样也是比较困难的;这个期望可以通过蒙特卡洛(Monte Carlo)采样进行逼近,在文献[1]中作者提出可以基于Langevin动力学[2]生成来自模型中的样本,先随机初始化

    其中,来自于标准正态分布。
  • 在以上迭代式执行步后,数据似然函数(2.4中的第二项)对参数的导数可写为如下形式

  • 最终的训练步骤为:
    • 从数据集中采样
    • 计算
    • 初始化,比如使用均匀分布
    • 执行步Langevin动力学
    • 计算参数的梯度,并且更新模型

4 模型代码

  • 以下代码来自于
    https://github.com/jmtomczak/intro_dgm/blob/main/ebms/ebm_example.ipynb
class EBM(nn.Module):
def __init__(self, energy_net, alpha, sigma, ld_steps, D):
super(EBM, self).__init__()

print('EBM by JT.')

# EBM所使用的神经网络
self.energy_net = energy_net

# 分类任务的损失函数
self.nll = nn.NLLLoss(reduction='none') # it requires log-softmax as input!!

# 一些超参数
self.D = D

self.sigma = sigma

self.alpha = torch.FloatTensor([alpha])

self.ld_steps = ld_steps

def classify(self, x):
f_xy = self.energy_net(x)
y_pred = torch.softmax(f_xy, 1)
return torch.argmax(y_pred, dim=1)

def class_loss(self, f_xy, y):
# - 计算分类网络的预测
y_pred = torch.softmax(f_xy, 1)

return self.nll(torch.log(y_pred), y)

def gen_loss(self, x, f_xy):
# - 使用Langevine动力学采样
x_sample = self.sample(x=None, batch_size=x.shape[0])

# - 计算网络对于采样值的输出 f(x_sample)[y]
f_x_sample_y = self.energy_net(x_sample)

return -(torch.logsumexp(f_xy, 1) - torch.logsumexp(f_x_sample_y, 1))

def forward(self, x, y, reduction='avg'):
# =====
# 网络前向传播
# - 计算 f(x)[y]
f_xy = self.energy_net(x)

# =====
# 判别式部分
# - 计算判别损失: 交叉熵
L_clf = self.class_loss(f_xy, y)

# =====
# 生成部分
# - 计算生成损失: E(x) - E(x_sample)
L_gen = self.gen_loss(x, f_xy)

# =====
# 最终目标
if reduction == 'sum':
loss = (L_clf + L_gen).sum()
else:
loss = (L_clf + L_gen).mean()

return loss

def energy_gradient(self, x):
self.energy_net.eval()

# 复制数据
x_i = torch.FloatTensor(x.data)
x_i.requires_grad = True # 在生成服从模型分布的采样值时,需要对数据x进行求导

# 计算梯度
x_i_grad = torch.autograd.grad(torch.logsumexp(self.energy_net(x_i), 1).sum(), [x_i], retain_graph=True)[0]

self.energy_net.train()

return x_i_grad

def langevine_dynamics_step(self, x_old, alpha):
# 计算梯度 wrt x_old
grad_energy = self.energy_gradient(x_old)
# 采样 eta ~ Normal(0, alpha)
epsilon = torch.randn_like(grad_energy) * self.sigma

# 新的样本
x_new = x_old + alpha * grad_energy + epsilon

return x_new

def sample(self, batch_size=64, x=None):
# - 1) 初始化样本
x_sample = 2. * torch.rand([batch_size, self.D]) - 1.

# - 2) 运行 Langevine 动力学采样
for i in range(self.ld_steps):
x_sample = self.langevine_dynamics_step(x_sample, alpha=self.alpha)

return x_sample
  • 在执行完整代码后,将得到以下结果
    • A 真实数据样本
    • B 20步Langevine采样结果
    • C 总损失
    • D 生成部分的损失


5 受限玻尔兹曼机

  • 基于能量模型的经典代表是玻尔兹曼机(Boltzmann machines, RMs)家族模型[3,4]
  • RMs的能量函数为

  • RMs因为配分函数的问题,难以训练。大家更熟悉的是在此基础上引入隐变量以及限制节点连接的受限玻尔兹曼机RBM。RBM可参考如下内容

CMU-10707 第九讲 受限玻尔兹曼机

  • 书中还介绍了再引入其他隐变量,使用能量函数建模更高阶的关系,能量函数如下


6 终评

6.1 RBMs

  • RBMs使用对比散度训练,并且利用了块吉布斯采样的优势;
  • 在二元RBMs中潜在变量的分布可以给出解析表达式,是Sigmoid函数的形式;
  • 对于连接施加限制使得我们可以开发更强的模型,例如 spike-and-slab RBMs,高阶RBMs,以及对比类别数据/实值数据的RBMs。RBMs还可用于处理时序数据,具体可参看原文;
  • BM可以通过正则化或其他学习算法,如Perturband-MAP方法、最小概率流,或其他算法来训练实现特定的特征。

6.2 DBMs

  • 对RBMs的扩展为深度玻尔兹曼机,可以使用逐层训练的方式来训练DBMs。
  • 与此相关的深度信念网络可参考如下

CMU-10707 第十讲 深度信念网络

6.3 近似配分函数

  • 配分函数的难以解析求解,使得我们需要借助一些近似方法
    • 变分方法:使用Bethe近似、使用树重加权sum-product算法
    • 随机近似:使用采样过程,例如退火重要性采样

6.4 EBMs是未来吗?

  • EBMs模型拥有如下潜能:
    • 不需要权衡分类损失与生成损失
    • 文献[1]结果表明,EBMs有不错的分类错误率,能够合成清晰图片,并且对离群点有较好检测

  • 仍待解决的问题:
    • 对于数据边缘分布的计算
    • 高效计算配分函数
    • 从模型中高效采样

7 参考文献

[1] Will Grathwohl, Kuan-Chieh Wang, Joern-Henrik Jacobsen, David Duvenaud, Mohammad Norouzi, and Kevin Swersky. Your classifier is secretly an energy based model and you should treat it like one. In International Conference on Learning Representations, 2019

[2] Max Welling and Yee W Teh. Bayesian learning via stochastic gradient Langevin dynamics. In Proceedings of the 28th international conference on machine learning (ICML-11), 2011

[3] David H Ackley, Geoffrey E Hinton, and Terrence J Sejnowski. A learning algorithm for Boltzmann machines. Cognitive science, 9(1):147–169, 1985.

[4] Geoffrey E Hinton, Terrence J Sejnowski, et al. Learning and relearning in Boltzmann machines. Parallel distributed processing: Explorations in the microstructure of cognition, 1(282-317):2, 1986.


推荐阅读

  • CS294-158 第一讲 逻辑与动机
  • CS294-158 第二讲 自回归模型
  • CS294-158 第三讲 流模型
  • CS294-158 第四讲 变分自编码器
  • CS294-158 第五、六讲 生成对抗网络
  • CS294-158 第七讲 自监督学习
  • CS294-158 第八讲 优缺点综述
  • CS294-158 第九讲 半监督学习与无监督分布对齐
  • CS294-158 第十讲 压缩
  • CS294-158 第十一讲 文本学习
  • CS294-158 第十一讲 附-Transformer注释中译本
  • 复旦邱锡鹏组最新Transformer综述
  • CS294-158 第十二讲 强化学习中的表示学习

  • CMU-10707 第九讲 受限玻尔兹曼机
  • CMU-10707 第十讲 深度信念网络

相关内容