AIGC实战——归一化流模型(Normalizing Flow Model)

AIGC实战——归一化流模型

    • 0. 前言
    • 1. 归一化流模型
      • 1.1 归一化流模型基本原理
      • 1.2 变量变换
      • 1.3 雅可比行列式
      • 1.4 变量变换方程
    • 2. RealNVP
      • 2.1 Two Moons 数据集
      • 2.2 耦合层
      • 2.3 通过耦合层传递数据
      • 2.4 堆叠耦合层
      • 2.5 训练 RealNVP 模型
    • 3. RealNVP 模型分析
    • 4. 其他归一化流模型
      • 4.1 GLOW
      • 4.3 FFJORD
    • 小结
    • 系列链接

0. 前言

我们已经学习了三类生成模型:变分自动编码器 (Variational Autoencoder, VAE)、生成对抗网络 (Generative Adversarial Network, GAN) 和自回归模型 (Autoregressive Model)。每种模型都使用不同的方式对分布 p ( x ) p(x) p(x) 进行建模,其中 VAEGAN 引入了易于使用的潜变量,自回归模型则将分布建模为先前元素值的函数。在本节中,我们将介绍一类新的生成模型,归一化流模型 (Normalizing Flow Model)。

1. 归一化流模型

1.1 归一化流模型基本原理

归一化流模型的目标与变分自编码器类似,变分自编码器学习一个编码器映射函数,用于将复杂分布映射到可以从中采样的简单分布,并学习了一个从简单分布到复杂分布的解码器映射函数,以便通过从简单分布中采样一个点z并应用学到的转换来生成新的数据点。从概率角度来看,解码器用于建模 p ( x ∣ z ) p(x|z) p(xz),但编码器只是真实分布 p ( z ∣ x ) p(z|x) p(zx) 的近似,编码器和解码器是两个完全不同的神经网络。
在归一化流模型中,解码函数被设计为编码函数的精确反函数,且计算速度快,使得归一化流具有可计算性。而神经网络默认情况下并不是可逆函数,因此需要利用深度学习的灵活性创建一个可逆过程,将一个复杂分布转化为一个简单分布。
为此,我们首先需要了解变量转换 (change of variables) 的技术。在本节中,我们使用一个只有两个维度的简单例子,以便了解归一化流的工作原理,将其进行扩展即可适应复杂问题。

1.2 变量变换

假设有一个在二维空间 x = ( x 1 , x 2 ) x=(x_1,x_2) x=(x1,x2) 中定义的矩形 X X X 上的概率分布 p X ( x ) p_X(x) pX(x),如下图所示。

二维空间

此函数在分布的定义域(即 x 1 x_1 x1[1, 4] 范围内, x 2 x_2 x2[0, 2] 范围内)上积分为 1,因此它表示一个明确定义的概率分布,可以写成如下形式:
∫ 0 2 ∫ 1 4 p X ( x ) d x 1 d x 2 = 1 ∫_0^2 ∫_1^4 p_X(x) dx_1 dx_2 = 1 0214pX(x)dx1dx2=1
假设我们想要将这个分布平移和缩放,使其在一个单位正方形 Z Z Z 上定义。我们可以通过定义一个新变量 z = ( z 1 , z 2 ) z = (z_1, z_2) z=(z1,z2) 和一个函数 f f f,将 X X X 中的每个点映射到 Z Z Z 中的点,如下所示:
z = f ( x ) z 1 = x 1 − 1 3 z 2 = x 2 2 z = f(x) \\ z_1 = \frac {x_1 - 1}3 \\ z_2 =\frac {x_2} 2 z=f(x)z1=3x11z2=2x2
此函数是可逆的,也就是说,存在一个函数 g g g,能够将每个 z z z 映射回其对应的点 x x x,即若一函数有反函数,此函数便称为可逆的 (invertible)。这对于变量变换来说是至关重要的,否则我们无法在两个空间之间进行一致的反向和正向映射,我们可以通过重新排列定义f的方程来找到 g g g,如下图所示。

反函数

接下来,我们继续了解从 X X X Z Z Z 的变量变换如何影响概率分布 p X ( x ) p_X(x) pX(x)。我们可以通过将定义 g g g 的方程代入 p X ( x ) p_X(x) pX(x) 来进行转换,得到一个以 z z z 为自变量的函数 p Z ( z ) p_Z(z) pZ(z)
p Z ( z ) = ( ( 3 z 1 + 1 ) − 1 ) ( 2 z 2 ) 9 = 2 z 1 z 2 3 p_Z(z) = \frac{((3z_1 + 1) - 1)(2z_2)}9 =\frac{ 2z_1z_2}3 pZ(z)=9((3z1+1)1)(2z2)=32z1z2
然而,如果在单位正方形上对 p Z ( z ) p_Z(z) pZ(z)进行积分,会出现以下问题:
∫ 0 1 ∫ 0 1 2 z 1 z 2 3 d z 1 d z 2 = 1 6 ∫_0^1 ∫_0^1\frac {2z_1z_2} 3 dz_1 dz_2 = \frac 1 6 010132z1z2dz1dz2=61
即转换后的函数 p Z ( z ) p_Z(z) pZ(z) 不再是一个有效的概率分布,因为它的积分等于 1 6 \frac 1 6 61。如果我们想要将复杂的数据概率分布转换为一个简单的分布以便进行采样,就必须确保其积分为 1 1 1
缺失的因子 6 6 6 源于转换后的概率分布的定义域比原始定义域小六倍——原始矩形 X X X 的面积为 6,变换后被压缩为面积为 1 的单位正方形 Z Z Z。因此,我们需要将新的概率分布乘以一个归一化因子,该因子等于面积(或在更高维度中的体积)的相对变化,可以使用变换的雅可比行列式 (Jacobian determinant) 的绝对值计算给定变换的体积变化。

1.3 雅可比行列式

函数 z = f ( x ) z=f(x) z=f(x) 的雅可比矩阵是其一阶偏导数的矩阵,如下所示:
J = ∂ z ∂ x = [ ∂ z 1 ∂ x 1 ⋯ ∂ z 1 ∂ x n ⋮ ⋱ ⋮ ∂ z m ∂ x 1 ⋯ ∂ z m ∂ x n ] J=\frac{∂z}{∂x}=\begin{bmatrix} \frac{∂z_1}{∂x_1} & \cdots & \frac{∂z_1}{∂x_n} \\ \vdots & \ddots & \vdots \\ \frac{∂z_m}{∂x_1} & \cdots\ & \frac{∂z_m}{∂x_n} \\ \end{bmatrix} J=xz= x1z1x1zm xnz1xnzm
在以上示例中,如果计算 z 1 z_1 z1 关于 x 1 x_1 x1 的偏导,结果为 1 3 \frac 1 3 31,如果计算 z 1 z_1 z1 关于 x 2 x_2 x2 的偏导,结果为 0;同样地,如果计算 z 2 z_2 z2 关于 x 1 x_1 x1 的偏导,结果为 0;最后,如果计算 z 2 z_2 z2 关于 x 2 x_2 x2 的偏导,结果为 1 2 \frac 1 2 21。因此,函数 f ( x ) f(x) f(x) 的雅可比矩阵如下:
J = ( 1 3 0 0 1 2 ) J = \left (\begin{array}{rrrr} \frac13 & 0 \\ 0 & \frac 1 2 \\ \end{array}\right) J=(310021)
行列式 (determinant) 仅对方阵有定义,并且它等于通过将矩阵表示的变换应用到单位(超)立方体上所创建的平行六面体的有向体积 (signed volume)。在二维情况下,这等于将矩阵表示的变换应用到单位正方形上所创建的平行四边形的有向面积 (signed area)。
用于计算 n n n 维矩阵的行列式的时间复杂度为 O ( n 3 ) O(n^3) O(n3)。对于以上示例,只需要两维形式的公式,即:
d e t ( a b c d ) = a d − b c det \left (\begin{array}{rrrr} a & b \\c & d \end{array}\right)= ad - bc det(acbd)=adbc
因此,对于以上示例,雅可比矩阵的行列式为:
1 3 × 1 2 − 0 × 0 = 1 6 \frac 1 3 × \frac 1 2 - 0 × 0 = \frac 1 6 31×210×0=61
此缩放因子 ( 1 6 \frac1 6 61) 用于确保变换后的概率分布积分仍然为 1。根据定义,行列式带有符号,也就是说它可以是负数。因此,我们需要取雅可比矩阵行列式的绝对值才能得到体积的相对变化。

1.4 变量变换方程

我们可以使用变量变换方程描述 X X X Z Z Z 之间的变量变换过程:
p X ( x ) = p Z ( z ) ∣ d e t ( ∂ z ∂ x ) ∣ p_X(x)=p_Z(z)|det(\frac {∂z} {∂x})| pX(x)=pZ(z)det(xz)
基于以上理论构建生成模型,关键在于理解,如果 p Z ( z ) p_Z(z) pZ(z) 是一个简单的分布,我们可以很容易地从中进行采样(例如高斯分布),那么理论上,我们只需要找到一个适当的可逆函数 f ( x ) f(x) f(x),可以将数据 X X X 映射到 Z Z Z,以及相应的反函数 g ( z ) g(z) g(z) 用于将采样的 z z z 映射回原始域中的点 x x x。我们可以利用上述包含雅可比行列式的方程来找到数据分布 p ( x ) p(x) p(x) 的精确的、可计算的公式。
然而,在实际应用中存在两个主要问题。首先,计算高维矩阵的行列式的计算代价较高,其时间复杂度为 O ( n 3 ) O(n^3) O(n3)。在实践中,这并不可行,因为即使是小尺寸的 32x32 像素灰度图像也有 1,024 个维度。其次,通常并无显式计算可逆函数 f ( x ) f(x) f(x) 的方法,我们可以使用神经网络来找到某个函数 f ( x ) f(x) f(x),但我们不能保证能够逆转此网络,因为神经网络只能单向工作。
为了解决这两个问题,我们需要使用一种特殊的神经网络架构,确保变量变换函数 f f f 具有易于计算的行列式,并且是可逆的。接下来,我们将介绍如何使用实值非体积保持 (Real-valued Non-volume Preserving, RealNVP) 变换的技术解决上述问题。

2. RealNVP

实值非体积保持 (Real-valued Non-volume Preserving, RealNVP) 由 Dinh 等人于 2017 年首提出,RealNVP 可以将复杂的数据分布转换为简单的高斯分布,同时还具有可逆性和易于计算的雅可比行列式。

2.1 Two Moons 数据集

在本节中,我们使用由 sklearnmake_moons 函数创建的数据集,make_moons 函数能够创建包含噪声的二维点数据集,类似于两个新月形状。

# 生成一个包含噪声、未标准化的包含 3,000 个点的 Two Moons 数据集
data = datasets.make_moons(30000, noise=0.05)[0].astype("float32")
norm = layers.Normalization()
norm.adapt(data)
# 将数据集标准化,使其均值为 0,标准差为 1
normalized_data = norm(data)

Two Moons 数据集

接下来,我们将构建一个 RealNVP 模型,可以生成与两个新月形数据集类似分布的二维点。使用此简单示例能够帮助我们详细了解归一化化流模型在实践中的工作原理。首先,我们介绍一种称为耦合层的新层。

2.2 耦合层

耦合层 (coupling layer) 为其输入的每个元素输出一个缩放因子和一个平移因子。换句话说,它会输出两个与输入大小完全相同的张量,一个用于缩放因子 s,一个用于平移因子 t

耦合层

为了构建自定义耦合层处理 Two Moons 数据集,我们可以通过堆叠一组 Dense 层来创建缩放输出,并使用另一组 Dense 层来创建平移输出;而对于图像,耦合层可以使用 Conv2D 层替代 Dense 层。

def Coupling(input_dim, coupling_dim, reg):# 为了处理 Two Moons 数据集,耦合层的输入具有两个维度input_layer = layers.Input(shape=input_dim)# 缩放流是一组具有 256 个单元的 Dense 层s_layer_1 = layers.Dense(coupling_dim, activation="relu", kernel_regularizer=regularizers.l2(reg))(input_layer)s_layer_2 = layers.Dense(coupling_dim, activation="relu", kernel_regularizer=regularizers.l2(reg))(s_layer_1)s_layer_3 = layers.Dense(coupling_dim, activation="relu", kernel_regularizer=regularizers.l2(reg))(s_layer_2)s_layer_4 = layers.Dense(coupling_dim, activation="relu", kernel_regularizer=regularizers.l2(reg))(s_layer_3)# 最后一个缩放层具有 2 个单元,并且使用 tanh 激活函数s_layer_5 = layers.Dense(input_dim, activation="tanh", kernel_regularizer=regularizers.l2(reg))(s_layer_4)# 平移流是一组具有 256 个单元的 Dense 层t_layer_1 = layers.Dense(coupling_dim, activation="relu", kernel_regularizer=regularizers.l2(reg))(input_layer)t_layer_2 = layers.Dense(coupling_dim, activation="relu", kernel_regularizer=regularizers.l2(reg))(t_layer_1)t_layer_3 = layers.Dense(coupling_dim, activation="relu", kernel_regularizer=regularizers.l2(reg))(t_layer_2)t_layer_4 = layers.Dense(coupling_dim, activation="relu", kernel_regularizer=regularizers.l2(reg))(t_layer_3)# 最后一个平移层具有 2 个单元,并且使用线性激活函数t_layer_5 = layers.Dense(input_dim, activation="linear", kernel_regularizer=regularizers.l2(reg))(t_layer_4)#   构建耦合层,其包含两个输出,包括缩放因子和平移因子return models.Model(inputs=input_layer, outputs=[s_layer_5, t_layer_5])

在将输出维度还原回与输入维度相同之前,通过增加维度学习数据更复杂的特征。还可以对每一层使用正则化器以惩罚较大的权重。

2.3 通过耦合层传递数据

耦合层的架构并不复杂,它的独特之处在于输入数据在被送入耦合层时如何进行掩码和变换。

耦合层

只有数据的前 d d d 个维度被输入到第一个耦合层中,剩下的 D-d 个维度被掩码(即被设为零)。在本节构建的模型中,我们假设 D = 2 D=2 D=2 d = 1 d=1 d=1,这意味着耦合层不会看到全部值 ( x 1 , x 2 ) (x_1,x_2) (x1,x2),而只能看到 ( x 1 , 0 ) (x_1,0) (x1,0)
耦合层的输出是缩放因子和平移因子,输出也会被掩码,但使用的是之前的相反掩码,以便只有后半部分被传递出去,在以上模型中,输出结果为 ( 0 , s 2 ) (0,s_2) (0,s2) ( 0 , t 2 ) (0,t_2) (0,t2)。然后,这些输出被逐元素地应用于输入的后半部分 x 2 x_2 x2,而输入的前半部分 x 1 x_1 x1 则直接传递,没有进行任何更新。综上,对于一个维度为 D D D d < D d<D d<D 的向量,更新方程如下:
z 1 : d = x 1 : d z d + 1 : D = x d + 1 : D ⊙ e x p ( s ( x 1 : d ) ) + t ( x 1 : d ) z_{1:d} = x_{1:d}\\ z_{d+1:D} = x_{d+1:D} ⊙ exp(s(x_{1:d})) + t(x_{1:d}) z1:d=x1:dzd+1:D=xd+1:Dexp(s(x1:d))+t(x1:d)
想要知道为什么需要构建一个掩码了这么多信息的层,我们首先观察此函数的雅可比矩阵的结构:
∂ z ∂ x = [ I 0 ∂ z d + 1 : D ∂ x 1 : d d i a g ( e x p [ s ( x 1 : d ) ] ) ] \frac {∂z}{∂x} =\begin{bmatrix} \bold {I} &0 \\ \frac {∂z_d+1:D}{∂x1:d} & diag(exp[s(x_{1:d})]) \\ \end{bmatrix} xz=[Ix1:dzd+1:D0diag(exp[s(x1:d)])]
左上角的 d × d d×d d×d 子矩阵是单位矩阵 I \bold {I} I,因为 z 1 : d = x 1 : d z_{1:d} = x_{1:d} z1:d=x1:d,这些元素直接传递而不进行更新。因此,左上角的子矩阵是 0,因为 z d + 1 : D z_{d+1:D} zd+1:D 不依赖于 x d + 1 : D x_{d+1:D} xd+1:D
右下角的子矩阵只是一个对角矩阵,使用元素 e x p ( s ( x 1 : d ) ) exp(s(x1:d)) exp(s(x1:d)) 进行填充,因为 z d + 1 : D z_{d+1:D} zd+1:D 线性依赖于 x d + 1 : D x_{d+1:D} xd+1:D,梯度仅依赖于缩放因子(不依赖于平移因子)。下图展示了该矩阵形式,只有非零元素被填充上颜色。

雅可比矩阵

需要注意的是,对角线上方没有非零元素,因此这种矩阵称为下三角矩阵。这种结构化矩阵(下三角矩阵)的行列式等于对角线元素的乘积。换句话说,行列式不依赖于左下角的复杂导数。因此,可以将这个矩阵的行列式写为:
d e t ( J ) = e x p ( ∑ j s ( x 1 : d ) j ) det(J) = exp(∑_js(x_{1:d})_j) det(J)=exp(js(x1:d)j)
上式十分易于计算的,解决了雅可比行列式的计算问题后,我们继续考虑另一问题,即目标是函数必须易于求其反函数。我们可以通过重新排列正向方程得到可逆函数,如下所示:
x 1 : d = z 1 : d x d + 1 : D = ( z d + 1 : D − t ( x 1 : d ) ) ⊙ e x p ( − s ( x 1 : d ) ) x_{1:d} = z_{1:d} x_{d+1:D} = (z_{d+1:D} - t(x_{1:d})) ⊙ exp(-s(x_{1:d})) x1:d=z1:dxd+1:D=(zd+1:Dt(x1:d))exp(s(x1:d))
如下图所示。

反函数求解

解决了 RealNVP 模型的构建问题后,我们继续考虑如何更新输入的前 d d d 个元素。

2.4 堆叠耦合层

为了更新输入的前 d d d 个元素,我们可以将耦合层堆叠在一起,但交替使用掩码模式,在某一个层保持不变的元素将在下一层中进行更新。这种架构能够学习数据更复杂的表示,因为它是一个更深层的神经网络。
耦合层组合的雅可比矩阵仍然很容易计算,根据线性代数的原理,矩阵乘积的行列式是行列式的乘积。同样地,两个函数组合的反函数就是各自反函数的组合,如下方程所示:
d e t ( A ⋅ B ) = d e t ( A ) d e t ( B ) ( f b ∘ f a ) − 1 = f a − 1 ∘ f b − 1 det(A·B) = det(A) det(B)\\ (f_b ∘ f_a)^{-1} = f_a^{-1} ∘ f_b^{-1} det(AB)=det(A)det(B)(fbfa)1=fa1fb1
因此,如果我们堆叠耦合层,并且每次改变掩码模式,就可以构建一个能够转换整个输入张量的神经网络,同时保持具有简单雅可比矩阵行列式和可逆性的关键特性。总体结构如下图所示。

网络架构

2.5 训练 RealNVP 模型

构建了 RealNVP 模型后,便可以对其进行训练,以学习 Two Moons 数据集的复杂分布。我们希望模型最小化数据的负对数似然 − l o g p X ( x ) -logp_X(x) logpX(x)
− l o g p X ( x ) = − l o g p Z ( z ) − l o g ∣ d e t ( ∂ z ∂ x ) ∣ -logp_X(x)=-logp_Z(z)-log|det(\frac {∂z}{∂x})| logpX(x)=logpZ(z)logdet(xz)
选择正向过程f的目标输出分布 p Z ( z ) p_Z(z) pZ(z) 为标准高斯分布,因为我们可以很容易地从该分布中进行采样。然后,通过应用逆过程 g g g,我们可以将从高斯分布中采样得到的点转换回原始图像域,如下图所示。

转换过程

接下来,使用 Keras 构建 RealNVP 网络。

class RealNVP(models.Model):def __init__(self, input_dim, coupling_layers, coupling_dim, regularization):super(RealNVP, self).__init__()self.coupling_layers = coupling_layers# 目标分布是一个标准的二维高斯分布self.distribution = tfp.distributions.MultivariateNormalDiag(loc=[0.0, 0.0], scale_diag=[1.0, 1.0])# 创建交替掩码模式self.masks = np.array([[0, 1], [1, 0]] * (coupling_layers // 2), dtype="float32")self.loss_tracker = metrics.Mean(name="loss")# 定义由 Coupling 层组成的列表,用于定义 RealNVP 网络self.layers_list = [Coupling(input_dim, coupling_dim, regularization)for i in range(coupling_layers)]@propertydef metrics(self):return [self.loss_tracker]def call(self, x, training=True):log_det_inv = 0direction = 1if training:direction = -1# 在网络的 call 函数中,循环遍历 Coupling 层。如果 training=True,则正向通过耦合层(即从数据到潜空间);如果 training=False,则反向通过耦合层(即从潜空间到数据)for i in range(self.coupling_layers)[::direction]:x_masked = x * self.masks[i]reversed_mask = 1 - self.masks[i]s, t = self.layers_list[i](x_masked)s *= reversed_maskt *= reversed_maskgate = (direction - 1) / 2# 正向和反向方程,取决于方向参数 direction 的值x = (reversed_mask* (x * tf.exp(direction * s) + direction * t * tf.exp(gate * s))+ x_masked)# 雅可比行列式的对数行列式,用于计算损失函数,是缩放因子的总和log_det_inv += gate * tf.reduce_sum(s, axis=1)return x, log_det_invdef log_loss(self, x):y, logdet = self(x)# 损失函数是转换后的数据在目标高斯分布下的负对数概率和雅可比行列式的对数之和的负值log_likelihood = self.distribution.log_prob(y) + logdetreturn -tf.reduce_mean(log_likelihood)def train_step(self, data):with tf.GradientTape() as tape:loss = self.log_loss(data)g = tape.gradient(loss, self.trainable_variables)self.optimizer.apply_gradients(zip(g, self.trainable_variables))self.loss_tracker.update_state(loss)return {"loss": self.loss_tracker.result()}def test_step(self, data):loss = self.log_loss(data)self.loss_tracker.update_state(loss)return {"loss": self.loss_tracker.result()}model = RealNVP(input_dim=INPUT_DIM,coupling_layers=COUPLING_LAYERS,coupling_dim=COUPLING_DIM,regularization=REGULARIZATION,
)# Compile and train the model
model.compile(optimizer=optimizers.Adam(learning_rate=0.0001))model.fit(normalized_data,batch_size=BATCH_SIZE,epochs=EPOCHS,
)

3. RealNVP 模型分析

模型训练完成后,就可以使用它将训练集转换为潜空间(使用正向方程 f f f),或者将从潜在空间中采样的点转换为像是从原始数据分布中采样的点(使用反向方程 g g g)。
在模型进行训练之前网络的输出如下所示,无论是正向还是反向都只是将信息直接传递,几乎没有任何变换。

网络输出

在训练之后,正向过程能够将训练集中的点转换为类似于高斯分布的分布。同样,反向过程可以将从高斯分布中采样的点映射回类似于原始数据的分布。

网络输出

接下来,我们将继续介绍一些改进的归一化流模型,这些模型扩展了 RealNVP 的思想。

4. 其他归一化流模型

另外两个重要的归一化流模型包括 GLOWFFJORD

4.1 GLOW

GLOW2018 年提出,是第一个证明了归一化流具有生成高质量样本和获得有意义的潜空间以用于样本操作的能力的模型之一。其关键步骤是使用可逆的 1×1 卷积层替换反向掩码。例如,在应用于图像的 RealNVP 中,每个步骤之后通道的顺序被翻转,以确保网络有机会转换所有输入。而在 GLOW 中,采用了 1×1 卷积,它有效地充当了产生模型所需的通道排列方法。即使加入了这一步骤,整个分布仍然是可处理的,其行列式和逆矩阵在大规模情况下仍易于计算。

生成图像

4.3 FFJORD

RealNVPGLOW 是离散时间的归一化流,它们通过一组离散的耦合层来转换输入。FFJORD (Free-Form Continuous Dynamics for Scalable Reversible Generative Models) 于 2019 年提出,其将转换建模为连续时间过程(即,通过将流中的步骤数趋近无穷大、步长趋近于零)。在这种情况下,使用一个普通微分方程 (Ordinary Differential Equation, ODE) 来建模动力学,其参数由一个神经网络 ( f θ ) (fθ) (fθ) 生成。使用一个黑盒求解器来解决 ODE 在时间 t 1 t_1 t1 时的问题,即给定从时间 t 0 t_0 t0 采样的高斯分布中的初始点 z 0 z_0 z0,找到 z 1 z_1 z1
z 0 ∼ p ( z 0 ) ∂ z ( t ) ∂ t = f θ ( x ( t ) , t ) x = z 1 z_0 \sim p(z_0)\\ \frac {∂z(t)}{∂t} = f_θ(x(t), t)\\ x = z_1 z0p(z0)tz(t)=fθ(x(t),t)x=z1
转换过程如下图所示。

转换过程

小结

归一化流模型是由神经网络定义的可逆函数,通过变量变换,直接对数据密度函数进行建模。在一般情况下,变量变换方程需要计算高度复杂的雅可比行列式,但这并不实际。为了解决这一问题,RealNVP 模型限制了神经网络的形式,使其满足两个基本条件:可逆性和易于计算的雅可比行列式。GLOW 进一步扩展了这一思想,消除了硬编码的掩码变换的必要性。FFJORD 模型通过使用由神经网络定义的 ODE,将转换过程建模为连续时间归一化流。归一化流是一种强大的生成建模方法,可以产生高质量的样本,并能够可靠地描述数据密度函数。

系列链接

AIGC实战——生成模型简介
AIGC实战——深度学习 (Deep Learning, DL)
AIGC实战——卷积神经网络(Convolutional Neural Network, CNN)
AIGC实战——自编码器(Autoencoder)
AIGC实战——变分自编码器(Variational Autoencoder, VAE)
AIGC实战——使用变分自编码器生成面部图像
AIGC实战——生成对抗网络(Generative Adversarial Network, GAN)
AIGC实战——WGAN(Wasserstein GAN)
AIGC实战——条件生成对抗网络(Conditional Generative Adversarial Net, CGAN)
AIGC实战——自回归模型(Autoregressive Model)
AIGC实战——改进循环神经网络
AIGC实战——像素卷积神经网络(PixelCNN)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/668658.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

小红书种草图文怎么制作?纯干货

一篇优质的小红书种草图文&#xff0c;不仅能提升产品销量&#xff0c;还能为品牌带来广泛的关注。如何制作出高质量的小红书种草图文呢&#xff1f;本文伯乐网络传媒将为你一一揭晓。 一、小红书种草图文制作要点 1. 确定目标受众和主题 明确目标受众是谁&#xff0c;他们有何…

微服务入门篇:Nacos注册中心(Nacos安装,快速入门,多级存储,负载均衡,环境隔离,配置管理,热更新,集群搭建,nginx反向代理)

目录 1.Nacos安装1.官网下载2.解压到本地3.启动nacos 2.Nacos快速入门1.在父工程中导入nacos依赖2.给子项目添加客户端依赖3.修改对应服务的配置文件4.启动服务&#xff0c;查看nacos发现情况 3.Nacos服务多级存储模型4.NacosRule负载均衡5. 服务实例的权重设置6.环境隔离&…

PDF控件Spire.PDF for .NET【安全】演示:检测 PDF 文档是否受密码保护

Spire.PDF for .NET 是一款独立 PDF 控件&#xff0c;用于 .NET 程序中创建、编辑和操作 PDF 文档。使用 Spire.PDF 类库&#xff0c;开发人员可以新建一个 PDF 文档或者对现有的 PDF 文档进行处理&#xff0c;且无需安装 Adobe Acrobat。 E-iceblue 功能类库Spire 系列文档处…

2024数学建模美赛F题Reducing Illegal Wildlife Trade原创论文讲解(含完整python代码)

大家好呀&#xff0c;从发布赛题一直到现在&#xff0c;总算完成了数学建模美赛本次F题目非法野生动物贸易完整的成品论文。 本论文可以保证原创&#xff0c;保证高质量。绝不是随便引用一大堆模型和代码复制粘贴进来完全没有应用糊弄人的垃圾半成品论文。 F题论文共42页&…

Qt|实现时间选择小功能

在软件开发过程中&#xff0c;QtDesigner系统给出的控件很多时候都无法满足炫酷的效果&#xff0c;前一段时间需要用Qt实现选择时间的小功能&#xff0c;今天为大家分享一下&#xff01; 首先看一下时间效果吧&#xff01; 如果有需要继续往下看下去哟~ 功能 1&#xff1a;开…

‘javax.sql.DataSource‘ that could not be found的问题

报错信息如下&#xff1a; 2024-02-04 16:31:14.832 WARN 952 --- [ main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDepen…

Leetcode—38. 外观数列【中等】

2024每日刷题&#xff08;111&#xff09; Leetcode—38. 外观数列 实现代码 class Solution { public:string countAndSay(int n) {string ans "1";while(--n) {string next;for(int i 0; i < ans.size(); i) {int cnt 1;char c ans[i];while(i 1 < an…

【算法与数据结构】647、516、LeetCode回文子串+最长回文子序列

文章目录 一、647、回文子串二、516、最长回文子序列三、完整代码 所有的LeetCode题解索引&#xff0c;可以看这篇文章——【算法和数据结构】LeetCode题解。 一、647、回文子串 思路分析&#xff1a;判断一个字符串是否为回文串那么必须确定回文串的所在区间&#xff0c;而一维…

【RK3288 Android6 T8, 突然无声音问题排查】

文章目录 【RK3288 Android6 T8, 突然无声音问题排查】问题描述问题调查patch【RK3288 Android6 T8, 突然无声音问题排查】 问题描述 页面上方突然出现音量进度条,小铃铛图标显示静音状态,不再播报语音 手动去安卓设置内查看,小铃铛音量为0,手动恢复到有声音后继续执行…

Redis -- set集合

挑战自己&#xff0c;每天进步一点点&#xff0c;成就将属于不停止脚步的你。 目录 Redis集合&#xff1f; 集合基本命令 sadd smembers sismember scard spop srandmember smove srem 集合间操作 sinter sinterstore sunion sdiff sdiifstore Redis集合&#…

【Linux】EXT2文件系统 | 磁盘分区块组 | inode

文章目录 一、前言二、EXT2文件系统 - 逻辑存储结构&#x1f4be;分区&#xff08;Partition&#xff09;分区的概念每个分区的内容Linux下查询磁盘分区 &#x1f4be;块组&#xff08;Block Group&#xff09;磁盘格式化每个块组的内容1. Superblock&#xff08;超级块&#x…

【Delphi 基础知识 28】ListView控件的详细使用

文章目录 控件设置增加数据删除选中的行按标题删除读取某行某列内容修改某行某列内容清空内容设置焦点上下移动条目读出选中行信息点击正反排序每行item显示不一样的颜色 控件设置 ViewStyle 设为vsReportReadOnly 设为TrueGridLines 设为TrueRowSelect 设为True 增加数据 …

《Redis核心技术与实战》学习笔记0——开篇词 | 这样学Redis,才能技高一筹

开篇词 | 这样学Redis&#xff0c;才能技高一筹 文章目录 开篇词 | 这样学Redis&#xff0c;才能技高一筹为什么懂得了一个个技术点&#xff0c;却依然用不好 Redis&#xff1f; 作为键值数据库&#xff0c;Redis 的应用非常广泛&#xff0c;如果你是后端工程师&#xff0c;我猜…

RCS-YOLO复现

复现结果–Precision&#xff1a;0.941&#xff0c;Recall&#xff1a;0.945&#xff0c;AP 50 _{50} 50​&#xff1a;0.941&#xff0c;AP 50 : 95 _{50:95} 50:95​&#xff1a;0.693&#xff0c;误差在5个点内&#xff0c;可以接受 感想 第5篇完全复现的论文

Palworld幻兽帕鲁自建服务器32人联机开黑!

玩转幻兽帕鲁服务器&#xff0c;阿里云推出新手0基础一键部署幻兽帕鲁服务器教程&#xff0c;傻瓜式一键部署&#xff0c;3分钟即可成功创建一台Palworld专属服务器&#xff0c;成本仅需26元&#xff0c;阿里云服务器网aliyunfuwuqi.com分享2024年新版基于阿里云搭建幻兽帕鲁服…

「Kafka」消费者篇

「Kafka」消费者篇 Kafka 消费方式 Kafka 消费者工作流程 消费者总体工作流程 新版本&#xff08;0.9之后&#xff09;的 offset 保存在 kafka 的 Topic 里&#xff0c;持久化到磁盘&#xff0c;可靠性有保障。 老版本&#xff08;0.9之前&#xff09;的 offset 保存在 Zook…

uniapp中配置开发环境和生产环境

uniapp在开发的时候&#xff0c;可以配置多种环境&#xff0c;用于自动切换IP地址&#xff0c;用HBuilder X直接运行的就是开发环境&#xff0c;用HBuilder X发布出来的&#xff0c;就是生产环境。 1.使用HBuilder X创建原生的uniapp程序 选择vue3 2.什么都不改&#xff0c;就…

机器学习复习(8)——基本概念

目录 "benchmark"和"baseline"的定义和区别 R1 score概念 LoRA微调概念 "benchmark"和"baseline"的定义和区别 在计算机视觉领域的论文中&#xff0c;"benchmark"和"baseline"这两个术语经常被使用&#xff0…

一文讲透ast.literal_eval() eval() json.loads()

文章目录 一文讲透ast.literal_eval() eval() json.loads()1. ast.literal_eval()2. eval()3. json.loads()4. 总结 一文讲透ast.literal_eval() eval() json.loads() 在Python库中&#xff0c;我们经常会遇到需要将字符串转换为相应对象或数据结构的情况。在这种情况下&#…

ShardingSphere 5.x 系列【5】Spring Boot 3 集成并实现读写分离

有道无术&#xff0c;术尚可求&#xff0c;有术无道&#xff0c;止于术。 本系列Spring Boot 版本 3.1.0 本系列ShardingSphere 版本 5.4.0 源码地址&#xff1a;https://gitee.com/pearl-organization/study-sharding-sphere-demo 文章目录 1. 概述2. 使用限制3. 案例演示3.…