updating...
1 动机
基于香农定理,使用估计所得熵模型对隐层表示建模理论上的编码下界为:
其中为隐层表示(latent representation)实际分布,为熵模型估计分布,熵模型是一个发送人与接收人共享的先验概率模型,用来估计真实隐层表示分布。上面的式子说明当熵模型估计与实际分布完全相同的时候会有编码长度最小。这告诉我们,一方面,当熵模型使用全分解(fully factorized)概率分布的时候,如果实际分布中存在统计依赖,熵模型估计分布天然不能拟合实际分布;另一方面,因为是一个确定性的过程,如果想要在使用全分解概率分布的情况下效果提升,则需要对输入的自然图像尽量多的去除统计依赖。
这篇文章,关键在于引入边信息,捕捉隐层表示的隐藏信息以辅助熵模型的参数生成,从而改善熵模型估计与隐层实际分布不匹配问题。将边信息导入比特流,这使得decoder也可以共享熵模型。解压时decoder先解压边信息,构建熵模型,之后基于正确的熵模型解压隐层信息。
2 变分模型
算法的优化问题可以建模为VAE模型。VAE是一个概率生成模型。熵模型对应VAE隐层表示的先验。边信息可以看做是熵模型参数的先验,先验的先验这里称之为超先验。
把压缩问题中的分析模型看做VAE中的推理模型,把合成模型看做生成模型。在VAE的推理模型,目的是要估计真实的后验概率,这通常不可行。于是VAE中使用一个带参变分密度来拟合真实后验概率,通过最小化优化目标——隐变量真实分布与模拟分布的KL散度来达到拟合的效果,这相当于最小化图像压缩中的率失真(rate-distortion)性能:
1. 第一项如下所示,U是一个宽度为1的均匀分布(如第三章中描述,在训练的时候使用添加均匀噪声代替量化),概率为1。。
2. 如果假设满足下面的分布:
那么第二项就是和的平方差,以为权重。也就是说,如果以为条件的的分布满足如上条件的多维高斯分布,那么第二项可以看做图像压缩中的类MSE的失真项distortion,最小化目标函数等同于缩小重构图像的失真。
第三项,,很容易看出与边缘分布(经过合成变换、量化操作之后的隐层分布)和先验(熵模型分布)的交叉熵[1]相同,当边缘分布与先验相同时最小,即最小化目标函数等同于使熵模型分布更拟合边缘分布。反映了编码的代价,可以看做图像压缩中的率rate。这里将先验建模成为一个无参数、可全分解的密度函数如下(A.6.1):
其中,代表每一个单变量分布的所有参数。在图像压缩中,熵模型的分布只由参数决定。*代表卷积,目的是让先验能够更好地匹配边缘分布。称上面这种式子为可分解先验模型(A.6.2)。
[1]:交叉熵定义:
3 超先验
如下所示,左二,由分析模型得出的隐层表示在尺度上存在空间耦合性,如高对比度区域响应集中的高、存在边缘。只靠全分解的熵模型不能够捕获这些耦合情况,超先验用来捕获这些空间耦合性。
超先验的方法,通过引入隐藏变量来建模空间相关性,扩展模型,将每个隐层变量建模成满足均值为0标准差为的高斯分布,其中由隐藏变量经过变换得来(同样卷积上一个标准均匀分布):
拓展推理模型,之上加一个变换,得到一个联合可分解变分后验概率(single joint factorized variational posterior)如下:
由于没有的先验信息,所以使用之前建模的全分解密度模型建模(A.6.1):
总损失函数如下所示,其中第三项和第四项分别代表编码和的交叉熵,第四项代表边信息:
直观来看,由经过分析变换得到,其规模进一步缩小,然后又通过合成变换扩大规模,得到熵模型的参数,其中可能会有两个位置的参数来源与同一个,这就达到了对两个元素之间耦合性建模的目的。
4 网络结构
5 实验
A.6.1 单变量无参密度模型
借助累计分布函数定义密度模型。其中累计分布函数满足:
累计分布函数应满足单调性,所以需要密度函数非负。假设累计分布函数可以分解为若干个函数:
是雅克比矩阵,矩阵形状为,为了保证是一个单变量函数,即的形状为,需要(矩阵相乘从左向右)
为满足,首先需要雅克比矩阵非负,则选择如下:
代表逐元素相乘,代表权重矩阵,代表偏置向量。将上面的式子求导如下:
为了限制导数非负,需要限制所有元素非负,所有元素以-1为下界,通过重参数化操作实现(其中带hat的是真实参数):
下面是使用该密度函数拟合一种高斯混合分布的情况(熵模型最终目的是要拟合真实分布):
该模型pytorch版对应于entropy_model中的bottleneck,可以看出累计分布函数形如一个多层感知机MLP。在实现代码使用多种方法解决精度表示的数值问题。
其中累计分布函数部分代码如下:
def _logits_cumulative(self, inputs: Tensor, stop_gradient: bool) -> Tensor:
# TorchScript not yet working (nn.Mmodule indexing not supported)
logits = inputs
for i in range(len(self.filters) + 1):
matrix = getattr(self, f"_matrix{i:d}")
if stop_gradient:
matrix = matrix.detach()
logits = torch.matmul(F.softplus(matrix), logits)
bias = getattr(self, f"_bias{i:d}")
if stop_gradient:
bias = bias.detach()
logits += bias
if i < len(self.filters):
factor = getattr(self, f"_factor{i:d}")
if stop_gradient:
factor = factor.detach()
logits += torch.tanh(factor) * torch.tanh(logits)
return logits
另外,实现的时候,设计了一个辅助损失函数,...,略。
A.6.2 加上均匀噪声来建模先验
在正文中,用到了与均匀噪声卷积后的密度函数来建模先验(熵模型)和超先验,以使先验更加灵活的拟合变分后验(实际分布)。假设变分后验和先验只有一维,此时,总是为相应维度生成一个常数值:
由于量化操作添加了均匀噪声,此时变分后验应该要精确匹配边缘分布:
交叉熵为:,该交叉熵应该为0,为了使交叉熵估计为0,此时先验应该足够灵活地估计后验的形状——单位宽度均匀密度。
均匀分布不仅是高斯密度也是A.6.1中单变量无参密度函数的边界案例。为了解决这个问题,给先验卷上一个均匀分布:
其中是累计分布函数。于是,先验的概率密度可以使用累计分布函数的差来表示。此时不论是什么样的,当它的尺度参数[2](简单来说,尺度越大分布越分散,尺度越小分布越集中)趋向于0的时候,趋向于一个单位均匀密度。如下所示,卷积上一个均匀分布使得先验概率对均匀分布的陡峭边界更加拟合:
[2]https://en.wikipedia.org/wiki/Scale_parameter