18、归一化流(NFs)入门指南

归一化流(NFs)入门指南

1. 利用TFP进行变量转换

TFP(TensorFlow Probability)对变量转换提供了良好的支持。变量转换的核心是一个双射变换函数 $g$。 tfp.bijector 包就是关于双射器的,下面我们来看看TFP中的双射器示例:

import tensorflow_probability as tfp
import numpy as np

tfb = tfp.bijectors 
g = tfb.Square()       
print(g.forward(2.0))     
print(g.inverse(4.0))    

在上述代码中,双射器 $g$ 将一个分布转换为另一个分布。第一个(通常是简单的)分布称为基础分布或源分布,双射器 $g$ 应用于该分布,得到的分布称为转换后的分布或目标分布。下面展示如何在TFP中实现一个简单的示例:

g = tfb.Square()    
db = tfd.Uniform(0.0,2.0)      
mydist = tfd.TransformedDistribution(    
    distribution=db, bijector=g)
xs = np.linspace(0.001, 5,1000)
px = mydist.prob(xs)     

需要注意的是,我们无需自己实现变量变换公式,TFP会帮我们完成这项工作。如果要创建自己的双射器,则需要实现变量变换公式。

2. 将NF拟合到数据

使用NF对复杂分布进行建模的第一步是使用TFP双射器,我们先从一维分布开始,仅使用一个流 $g$。后续可以通过链接多个流来增加建模复杂分布的灵活性。这些流由参数化的双射函数 $g$ 给出,其参数可以通过最大似然原理来确定。

2.1 确定双射变换 $g$ 的方法
  • 方法一:咨询传统统计学家
    传统统计学家会先使用简单模型(如高斯模型)拟合数据,然后观察模型与数据的差异,给出变换建议。例如,建议对数据进行对数变换,这样就可以使用高斯模型拟合数据。那么从简单分布到复杂分布的流 $g$ 就是对数的逆变换,即指数变换,可使用 tfb.Exp() 实现。
  • 方法二:数据驱动的方法
    利用计算机能力,通过数据驱动的方式找到双射变换 $g$。关键是设置一个具有可学习参数 $\theta$ 的灵活双射变换函数 $g$,使用最大似然方法确定参数值。具体来说,对于训练数据 $x_i$,计算单个训练样本的似然 $p(x_i)$,并通过相乘得到所有数据点的联合似然。在实践中,通常最小化训练数据的负对数似然(NLL)。

下面是一个极其简单的示例,第一个可学习的流是线性的,仅涉及两个参数 $a$ 和 $b$:

import tensorflow as tf
import tensorflow_probability as tfp
tfd = tfp.distributions

a = tf.Variable(1.0)     
b = tf.Variable(0.0)     
bijector = tfb.AffineScalar(shift=a, scale=b)         
dist = tfd.TransformedDistribution(distribution=
        tfd.Normal(loc=0,scale=1),bijector=bijector)
optimizer = tf.keras.optimizers.Adam(learning_rate=0.1)
for i in range(1000):
    with tf.GradientTape() as tape:
        loss = -tf.reduce_mean(dist.log_prob(X))    
        gradients = tape.gradient(loss,             
                    dist.trainable_variables)     
    optimizer.apply_gradients(
        zip(gradients, dist.trainable_variables))   

经过几个epoch的训练,可将 $N(0,1)$ 分布的变量转换为 $N(5,0.2)$ 分布的变量。但这种简单的线性变换不足以将高斯分布转换为更复杂的分布。

3. 通过链接流进行深入建模

线性流只能对基础分布进行平移和拉伸,无法改变分布的形状。因此,我们需要链接多个流来建模与基础分布形状差异很大的目标分布,以处理复杂的现实世界分布,如老忠实间歇泉两次喷发之间的等待时间。

3.1 链式流的原理

从 $z_0$ 开始,经过 $k$ 次变换得到 $x = z_k$。通过逐步使用变量变换公式(方程6.2),可以确定变换后变量的概率密度。通常,对对数概率进行操作更方便,对于完整的流,公式可推广为:
[
\log p_x(x) = \log p_{z_0}(z_0) - \sum_{i=0}^{k-1} \log \left| \frac{\partial g_i(z_i)}{\partial z_i} \right|
]
要计算 $p_x(x)$,只需在链中回溯并对 $\log \left| \frac{\partial g_i(z_i)}{\partial z_i} \right|$ 项求和。

3.2 在TFP中构建链式流

在TFP中创建双射器链很方便,只需使用 tfp.bijectors 包中的 Chain(bs) 类,其中 bs 是双射器列表。为了改变分布的形状,可以在堆叠的线性流之间引入非线性双射器。例如, SinhArcsinh 双射器有两个参数(偏度和尾重),当尾重大于0时,对 $x$ 和 $z$ 没有限制,可用于拟合老忠实间歇泉的数据。以下是构建链式流的代码:

import tensorflow as tf
import tensorflow_probability as tfp
tfd = tfp.distributions
tfb = tfp.bijectors

num_bijectors = 5   
bs=[]
for i in range(num_bijectors):
    sh = tf.Variable(0.0)
    sc=tf.Variable(1.0)
    bs.append(tfb.AffineScalar(shift=sh, scale=sc))  
    skewness=tf.Variable(0.0)
    tailweight=tf.Variable(1.0) 
    bs.append(tfb.SinhArcsinh(skewness,tailweight))   
bijector = tfb.Chain(bs)                      
dist = tfd.TransformedDistribution(distribution=
        tfd.Normal(loc=0,scale=1),bijector=bijector)

访问笔记本 http://mng.bz/xWVW 可以看到这个双射器链用于老忠实间歇泉等待时间的结果。

4. 高维空间中的变换

对于高维数据(如图像数据),也可以使用流方法拟合分布。首先将图像数据展平为向量 $x$,选择一个简单的基础分布 $p_z(z)$,任务是找到一个双射变换 $g(z)$ 将向量 $z$ 转换为向量 $x$。

4.1 高维变换的公式

在一维流中,主要公式为 $p_x(x) = p_z(z) \left| \frac{\partial g(z)}{\partial z} \right|$,其中 $\left| \frac{\partial g(z)}{\partial z} \right|$ 表示从 $z$ 到 $x$ 的长度变化。在三维及更高维度中,需要考虑体积的变化。一维公式中的标量导数被偏导数矩阵(雅可比矩阵)所取代。

雅可比矩阵是一个由函数 $g$ 对各个变量的偏导数组成的矩阵。在高维变量变换公式中,需要使用雅可比矩阵的行列式的绝对值。例如,对于三维空间的数据点 $z = (z_1, z_2, z_3)$ 和 $x = (x_1, x_2, x_3)$,变换 $x = g(z)$ 可以表示为:
[
\begin{cases}
x_1 = g_1(z_1, z_2, z_3) \
x_2 = g_2(z_1, z_2, z_3) \
x_3 = g_3(z_1, z_2, z_3)
\end{cases}
]
雅可比矩阵为:
[
J =
\begin{bmatrix}
\frac{\partial g_1}{\partial z_1} & \frac{\partial g_1}{\partial z_2} & \frac{\partial g_1}{\partial z_3} \
\frac{\partial g_2}{\partial z_1} & \frac{\partial g_2}{\partial z_2} & \frac{\partial g_2}{\partial z_3} \
\frac{\partial g_3}{\partial z_1} & \frac{\partial g_3}{\partial z_2} & \frac{\partial g_3}{\partial z_3}
\end{bmatrix}
]
高维变量变换公式为:
[
p_x(x) = p_z(z) \left| \det(J) \right|
]
其中 $\det(J)$ 是雅可比矩阵的行列式。

4.2 三角雅可比矩阵

为了方便计算雅可比矩阵的行列式,可以构造一个三角雅可比矩阵,即确保 $g_i(z)$ 独立于 $z_j$($j > i$)。这样的双射器便于处理,并且可以证明,对于任何 $D$ 维分布对(复杂分布 $p_x(x)$ 和简单基础分布 $p_z(z)$),都可以找到三角双射器将一个分布转换为另一个分布。

以下是三角雅可比矩阵的一个示例:
假设变换 $x = g(z)$ 满足 $g_1(z)$ 只依赖于 $z_1$,$g_2(z)$ 只依赖于 $z_1$ 和 $z_2$,$g_3(z)$ 依赖于 $z_1$、$z_2$ 和 $z_3$,则雅可比矩阵为:
[
J =
\begin{bmatrix}
\frac{\partial g_1}{\partial z_1} & 0 & 0 \
\frac{\partial g_2}{\partial z_1} & \frac{\partial g_2}{\partial z_2} & 0 \
\frac{\partial g_3}{\partial z_1} & \frac{\partial g_3}{\partial z_2} & \frac{\partial g_3}{\partial z_3}
\end{bmatrix}
]
此时,行列式 $\det(J) = \frac{\partial g_1}{\partial z_1} \cdot \frac{\partial g_2}{\partial z_2} \cdot \frac{\partial g_3}{\partial z_3}$,计算变得简单。

5. 使用网络控制流

可以使用神经网络(NN)来建模 $D$ 维双射函数 $g(z)$ 的各个分量 $g_i$。设计用于建模 $g_i$ 的神经网络时,需要遵循以下准则:
1. 三角雅可比矩阵 :确保 $g_i$ 独立于 $z_j$($j > i$),即 $\frac{\partial g_i}{\partial z_j} = 0$($j > i$)。
2. 易于计算的对角元素 :雅可比矩阵的对角元素 $\frac{\partial g_i}{\partial z_i}$ 要易于计算。
3. 复杂的非对角元素 :雅可比矩阵下三角的非对角元素函数可以很复杂,无需计算其偏导数。
4. 可逆变换 :确保变换是可逆的。

5.1 三角双射函数的分量

三角双射函数 $g(z)$ 的分量可以表示为:
[
\begin{cases}
x_1 = g_1(z_1) \
x_2 = g_2(z_1, z_2) \
\cdots \
x_D = g_D(z_1, z_2, \cdots, z_D)
\end{cases}
]
选择 $g_i$ 关于 $z_i$ 是线性的,即 $g_i(z) = a_i(z_1, \cdots, z_{i-1}) z_i + b_i(z_1, \cdots, z_{i-1})$,其中 $a$ 和 $b$ 可以是关于 $z$ 分量的复杂函数,可使用神经网络建模。为了确保双射性,在多维情况下,要保证雅可比矩阵的行列式不为零,可通过确保对角元素大于零来实现,例如将神经网络的输出通过指数函数处理。

5.2 实现NF模型的网络选择

如果使用全连接网络(fcNN)实现NF模型,需要 $D$ 个不同的网络分别计算 $a_i$ 和 $b_i$,但这会需要大量参数,且采样时间长。可以考虑使用单个网络输出所有 $a_i$ 和 $b_i$ 值,但 fcNN 会违反 $g_i$ 独立于 $z_j$($j > i$)的要求。

解决方法是使用自回归网络,如 TFP 中的 tfp.bijectors.AutoregressiveNetwork ,它可以确保输出节点 $a_i$ 不依赖于输入节点 $z_j$($j > i$)。该网络最早在 “Masked Autoencoder for Distribution Estimation (MADE)” 论文中提出。

5.3 训练自回归网络

以 $D = 4$ 维为例,训练时从观测的四维 $x$ 到四维 $z$,计算似然 $p(z)$,需要求解方程 $x_i = a_i(z_1, \cdots, z_{i-1}) z_i + b_i(z_1, \cdots, z_{i-1})$ 得到 $z_i$。这是一个顺序过程,训练无法并行化,速度较慢,但测试阶段速度较快。

5.4 Real NVP 流

Laurent Dinh 等人提出了一种不同的构建可逆流的方法,即 Real NVP(Real Non-Volume Preserving Flow)。该方法的特点是可以改变体积(雅可比行列式不等于1),与之前的设计相比,其架构更简单。

在 Real NVP 模型中,首先选择一个 $d$($1 \leq d \leq D$),前 $d$ 个分量从 $z$ 直接传递到 $x$,即 $x_{1:d} = z_{1:d}$。这 $d$ 个分量作为输入,用于训练神经网络,该网络输出剩余坐标 $x_{d+1:D}$ 的 $a$ 和 $b$ 值。

例如,当 $D = 5$,$d = 2$ 时:
- 前两个分量:$x_1 = z_1$,$x_2 = z_2$。
- 后三个分量:$x_i = a_i(z_1, z_2) z_i + b_i(z_1, z_2)$($i = 3, 4, 5$)。

神经网络有两个输出头,每个头有 $D - d$ 个节点。该网络满足双射和三角雅可比矩阵的要求,雅可比矩阵的行列式计算只需考虑对角元素。

为了让前 $d$ 个维度也参与变换,可以在进入下一层之前对 $z_i$ 分量进行重新排列,可使用 TFP 双射器 tfb.Permute() 实现。通常会使用多对耦合层和排列层来构建模型。

以下是 Real NVP 模型的架构示意图:

graph LR
    classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px

    A([z1, z2, z3, z4, z5]):::startend --> B[/选择 d = 2/]:::process
    B --> C(x1 = z1, x2 = z2):::process
    C --> D[/使用 z1, z2 训练 NN/]:::process
    D --> E[/输出 a3, a4, a5, b3, b4, b5/]:::process
    E --> F(x3 = a3(z1, z2) * z3 + b3(z1, z2)):::process
    E --> G(x4 = a4(z1, z2) * z4 + b4(z1, z2)):::process
    E --> H(x5 = a5(z1, z2) * z5 + b5(z1, z2)):::process
    F --> I([x1, x2, x3, x4, x5]):::startend
    G --> I
    H --> I

综上所述,归一化流(NFs)是一种强大的工具,可用于建模复杂分布。通过TFP提供的双射器和相关工具,结合神经网络,可以灵活地构建和训练流模型,处理一维和高维数据。不同的方法(如链式流、Real NVP 流)适用于不同的场景,在实际应用中可以根据需求选择合适的方法。

归一化流(NFs)入门指南

6. 不同方法的比较与应用场景

在实际应用中,需要根据具体问题和数据特点选择合适的归一化流方法。以下是对前面介绍的几种方法的比较和适用场景分析:
| 方法 | 优点 | 缺点 | 适用场景 |
| ---- | ---- | ---- | ---- |
| 简单线性流 | 实现简单,参数少,计算速度快 | 只能进行平移和拉伸,无法改变分布形状,建模能力有限 | 数据分布接近简单的线性变换,如从一个高斯分布变换到另一个高斯分布 |
| 链式流 | 可以通过堆叠多个流和引入非线性双射器改变分布形状,建模能力强 | 增加了模型复杂度和计算量 | 处理复杂的现实世界分布,如老忠实间歇泉的等待时间数据 |
| Real NVP流 | 架构相对简单,计算效率高,能有效处理高维数据 | 前d个维度初始不参与变换,需要额外的排列操作 | 高维数据建模,如图像数据的分布拟合 |

7. 归一化流的实际应用案例

归一化流在多个领域都有广泛的应用,下面介绍几个具体的案例。

7.1 图像生成

在图像生成任务中,目标是学习图像数据的分布,以便能够生成新的图像。可以将图像数据展平为高维向量,使用归一化流将简单的基础分布(如高斯分布)转换为图像数据的复杂分布。通过训练归一化流模型,可以从基础分布中采样,经过变换得到新的图像。

例如,使用链式流或Real NVP流构建模型,结合自回归网络控制流的参数。训练过程中,通过最小化负对数似然来调整模型参数,使得生成的图像尽可能接近真实图像的分布。

以下是一个简化的图像生成流程:

graph LR
    classDef startend fill:#F5EBFF,stroke:#BE8FED,stroke-width:2px
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px

    A([简单基础分布 z]):::startend --> B[/归一化流模型/]:::process
    B --> C([生成图像 x]):::startend
    D([真实图像数据]):::startend --> E[/计算负对数似然/]:::process
    E --> F[/更新模型参数/]:::process
    F --> B
7.2 异常检测

在异常检测中,可以使用归一化流学习正常数据的分布。当新的数据样本输入时,计算其在学习到的分布下的概率。如果概率低于某个阈值,则认为该样本是异常的。

具体操作步骤如下:
1. 收集正常数据,使用归一化流模型(如链式流或Real NVP流)对其进行训练,学习正常数据的分布。
2. 确定异常检测的阈值,可以通过在验证集上进行实验来选择合适的阈值。
3. 对于新的数据样本,计算其在训练好的归一化流模型下的概率。
4. 将计算得到的概率与阈值进行比较,如果低于阈值,则判定为异常样本。

8. 归一化流的未来发展趋势

归一化流作为一种新兴的概率建模方法,具有很大的发展潜力。以下是一些可能的未来发展趋势:

8.1 模型架构的创新

未来可能会出现更多新颖的归一化流模型架构,进一步提高模型的建模能力和计算效率。例如,结合其他深度学习架构(如卷积神经网络、循环神经网络),设计出更适合特定任务的归一化流模型。

8.2 与其他方法的融合

归一化流可以与其他概率建模方法(如变分自编码器、生成对抗网络)相结合,发挥各自的优势,解决更复杂的问题。例如,将归一化流与变分自编码器结合,提高变分推理的准确性。

8.3 应用领域的拓展

随着研究的深入,归一化流的应用领域将不断拓展。除了图像生成和异常检测,还可能在自然语言处理、生物信息学、金融等领域得到广泛应用。

9. 总结与建议

归一化流是一种强大的概率建模工具,通过双射变换将简单的基础分布转换为复杂的数据分布。在实际应用中,需要根据数据特点和任务需求选择合适的方法,如简单线性流适用于简单的线性变换,链式流和Real NVP流适用于复杂分布的建模。

为了更好地应用归一化流,建议:
1. 深入理解归一化流的基本原理和数学公式,特别是雅可比矩阵和变量变换公式,这有助于设计和调整模型。
2. 多尝试不同的双射器和网络结构,根据实验结果选择最优的模型配置。
3. 结合实际应用场景,对模型进行适当的优化和改进,提高模型的性能和效率。

总之,归一化流为概率建模和数据生成提供了一种新的思路和方法,随着技术的不断发展,相信它将在更多领域发挥重要作用。

基于粒子群优化算法的配电网光伏储能双层优化配置模型[IEEE33节点](选址定容)(Matlab代码实现)内容概要:本文介绍了基于粒子群优化算法(PSO)的配电网光伏储能双层优化配置模型,针对IEEE33节点系统进行光伏与储能系统的选址定容优化。该模型采用双层优化结构,上层以投资成本、运行成本和网络损耗最小为目标,优化光伏和储能的配置位置与容量;下层通过潮流计算验证系统约束,确保电压、容量等满足运行要求。通过Matlab编程实现算法仿真,利用粒子群算法的全局寻优能力求解复杂非线性优化问题,提升配电网对可再生能源的接纳能力,同时降低系统综合成本。文中还提供了完整的代码实现方案,便于复现与进一步研究。; 适合人群:具备电力系统基础知识和Matlab编程能力的研究生、科研人员及从事新能源规划的工程技术人员;熟悉优化算法与配电网运行分析的专业人士。; 使用场景及目标:①用于分布式光伏与储能系统的规划配置研究,支持科研项目与实际工程设计;②掌握双层优化建模方法与粒子群算法在电力系统中的应用;③实现IEEE33节点系统的仿真验证,提升对配电网优化调度的理解与实践能力。; 阅读建议:建议结合Matlab代码逐步理解模型构建过程,重点关注目标函数设计、约束条件处理及上下层交互逻辑,同时可扩展至其他智能算法对比实验,深化对优化配置问题的认知。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值