📍

选择城市

立即咨询
精选文章 / 深度解读

CS294-158 补1 基于能量的模型

本文整理自Jakub M. Tomczak的书籍《Deep Generative Modeling》 第六章基于能量的模型 本文已收录到以下专栏在本系列课程(UCB CS294-158 深度无监督学习)中介绍了一些深度生成模型,例如:CS294-158 第二讲 自回归 ......

  • 本文整理自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 第十讲 深度信念网络
阅读重点

这篇内容能帮你快速理解什么

帮助快速理解主题

通过更完整的主题说明和结构表达,帮助用户更快抓住重点,也让搜索系统更容易识别页面主题。

帮助判断下一步动作

让访问者快速理解当前问题、可行方法以及下一步应该继续看案例、看服务还是直接沟通。

帮助继续浏览与沟通

文章页不只是获取流量,也承担继续阅读、查看服务和发起咨询的承接作用。

继续了解

继续了解这个主题前,你可能还关心这些问题

为什么这类主题适合写成文章?

因为很多用户会通过问题词、对比词和方案词进入网站,文章页越清楚,越容易覆盖更具体的需求。

为什么文章页不能只有正文?

仅有正文不利于继续浏览和转化,文章页还需要总结、问答、相关推荐与咨询入口来承接用户。

看完之后下一步可以做什么?

可以继续看同类文章、服务页与案例页,也可以直接沟通官网升级与搜索优化需求。

这篇文章能帮助我解决什么具体问题?

这篇文章围绕当前主题提供了详细的解决方案、操作步骤和注意事项,帮助你快速理解核心要点并应用到实际场景中。

如何判断这篇文章的内容是否权威可靠?

内容基于实际项目经验和技术实践编写,结合行业标准和最佳实践,同时提供案例数据和方法论支撑,确保专业性和可操作性。

这类内容对SEO和网站排名有什么帮助?

优质的长文内容和FAQ结构能够提升页面主题相关性、增加用户停留时间、降低跳出率,这些都有助于搜索引擎评估页面质量并提升排名表现。

AI搜索引擎会如何理解和引用这类内容?

AI搜索系统会提取文章的实体信息、观点结论和结构化问答,当用户提出相关问题时,可能会引用本文作为答案来源或参考依据。

如果我有更多相关问题可以咨询谁?

可以通过页面底部的联系方式直接咨询我们的专业团队,包括电话、QQ或在线表单,我们会根据你的具体情况提供针对性的建议和方案。

这篇文章和同类内容有什么不同之处?

本文不仅提供理论知识,还包含实战经验、避坑指南和可执行的行动建议,同时兼顾传统SEO和新兴的GEO生成式搜索优化视角。

多久需要更新一次这类内容以保持时效性?

建议每季度审查并更新一次关键数据和案例,如果涉及技术工具或算法变化则需要更频繁地维护,确保内容持续为用户提供准确价值。