当前位置: 首页 > news >正文

语音合成之十九 为什么对数行列式的值可以作为Flow-based模型loss?

为什么对数行列式的值可以作为Flow-based模型loss?

    • 为什么对数行列式的值可以作为loss?
      • logdet 的作用总结

先上代码,在基于MeloTTS的modules.py文件中有如下代码:

class Log(nn.Module):def forward(self, x, x_mask, reverse=False, **kwargs):if not reverse:y = torch.log(torch.clamp_min(x, 1e-5)) * x_masklogdet = torch.sum(-y, [1, 2])return y, logdetelse:x = torch.exp(x) * x_maskreturn x

其中

  • x是输入张量,形状为(B,C,T),即batchxchannelxtime,x可以理解为输入的音素编码(即将中文的声母、韵母,英文的元音、辅音映射成的数值输入)。
  • x_mask: 掩码张量,形状为 (B, 1, T),用于屏蔽无效区域(如 padding);
  • reverse: 是否执行反向变换,默认为 False;
  • torch.clamp_min(x, 1e-5)
    将输入 x 中小于 1e-5 的值截断为 1e-5,防止对数计算时出现 log(0) 或负值;
    避免数值不稳定(numerical stability)问题。
  • torch.log(…)
    对处理后的 x 进行自然对数运算;
    输出 y = log(x),用于后续的流模型变换。
  • * x_mask
    应用掩码,使无效区域(padding)保持为 0。
  • logdet = torch.sum(-y, [1, 2])
    计算该变换的对数雅可比行列式(log-determinant of Jacobian)
    因为变换是 y = log(x),所以每个元素的导数为 dy/dx = 1/x,整体变换的对数行列式为 -sum(y);
    在 Flow 模型中,这个值用于更新似然损失(loss)
  • else分支,反向传播
    因为前面取了log,这里取exp,是逆操作,反向变换不需要记录对数行列式。

为什么对数行列式的值可以作为loss?

在上述的log变换中,是逐个元素(element-wise)的非线性变换。也就是说,输出张量 y 的第 i i i 个元素只与输入张量 x 的第 i i i 个元素有关。这意味着从x映射到y的变换 f y → x f_{y \rightarrow x} fyx是一个对角阵。可以表示成如下矩阵表示:
[ y 0 y 1 ⋮ y i ] = [ log ⁡ ( x 0 ) 0 ⋯ 0 0 log ⁡ ( x 1 ) ⋯ 0 ⋮ 0 0 ⋯ log ⁡ ( x i ) ] \begin{bmatrix} y_0 \\ y_1 \\ \vdots \\y_i\end{bmatrix} = \begin{bmatrix} \log{(x_0)} & 0 & \cdots &0 \\ 0& \log{(x_1)} & \cdots &0 \\ \vdots \\ 0 & 0 & \cdots & \log{(x_i)} \end{bmatrix} y0y1yi = log(x0)000log(x1)000log(xi)
其雅可比矩阵为:
J f ( x ) = [ ∂ y i ∂ x j ] i , j = 1 D = [ ∂ y 0 ∂ x 0 0 ⋯ 0 0 ∂ y 1 ∂ x 1 ⋯ 0 ⋮ 0 0 ⋯ ∂ y i ∂ x i ] = [ 1 x 0 0 ⋯ 0 0 1 x 1 ⋯ 0 ⋮ 0 0 ⋯ 1 x i ] J_f(x) = \left[\frac{\partial y_i}{\partial x_j}\right]_{i,j=1}^{D}= \begin{bmatrix} \frac{\partial {y_0}}{\partial x_0} & 0 & \cdots &0 \\ 0&\frac{\partial {y_1}}{\partial x_1} & \cdots &0 \\ \vdots \\ 0 & 0 & \cdots & \frac{\partial {y_i}}{\partial x_i}\end{bmatrix}= \begin{bmatrix} \frac{1}{x_0} & 0 & \cdots &0 \\ 0&\frac{1}{x_1} & \cdots &0 \\ \vdots \\ 0 & 0 & \cdots & \frac{1}{x_i}\end{bmatrix} Jf(x)=[xjyi]i,j=1D= x0y0000x1y1000xiyi = x01000x11000xi1

则雅可比矩阵对应行列式的值为:
log ⁡ ∣ det ⁡ J ∣ = log ⁡ ( ∏ i = 1 D 1 x i ) = ∑ i = 1 D log ⁡ ( 1 x i ) = − ∑ i = 1 D log ⁡ x i = − ∑ y i \log |\det J| = \log \left( \prod_{i=1}^{D} \frac{1}{x_i} \right) = \sum_{i=1}^{D} \log \left( \frac{1}{x_i} \right) = -\sum_{i=1}^{D} \log x_i = -\sum y_i logdetJ=log(i=1Dxi1)=i=1Dlog(xi1)=i=1Dlogxi=yi
也就是说:
我们可以直接用 y = log ⁡ ( x ) y = \log(x) y=log(x) 来代替 log ⁡ ( 1 / x ) \log(1/x) log(1/x)
所以最终表达式就是 logdet = -torch.sum(y, [1, 2]);

上面已经求得了logdet,再来回答为什么可以作为loss?
Flow-based 模型是一种显式建模数据分布的生成模型。其核心思想是通过一系列可逆变换将复杂的数据分布 p ( x ) p(x) p(x) 映射到一个简单的先验分布 p ( z ) p(z) p(z),例如标准正态分布。
设:

  • z = f ( x ) z = f(x) z=f(x):可逆变换;
  • x = f − 1 ( z ) x = f^{-1}(z) x=f1(z):逆变换;
    根据概率密度变换公式:
    log ⁡ p ( x ) = log ⁡ p ( z ) + log ⁡ ∣ det ⁡ J f ( x ) ∣ \log p(x) = \log p(z) + \log |\det J_f(x)| logp(x)=logp(z)+logdetJf(x)
    其中:
    log ⁡ p ( z ) \log p(z) logp(z) 是先验分布的对数似然;
    log ⁡ ∣ det ⁡ J f ( x ) ∣ \log |\det J_f(x)| logdetJf(x) 是变换的对数雅可比行列式(log-determinant of Jacobian),即 logdet。
    logdet(对数雅可比行列式)之所以能作为 loss 的一部分,是因为它直接反映了变换前后概率密度的变化。
y = torch.log(torch.clamp_min(x, 1e-5)) * x_mask
logdet = torch.sum(-y, [1, 2])

数学上:
log ⁡ ∣ det ⁡ J ∣ = − ∑ i y i = − ∑ i log ⁡ x i \log |\det J| = -\sum_{i} y_i = -\sum_{i} \log x_i logdetJ=iyi=ilogxi
这个值用于更新整体的 log-likelihood:
log ⁡ p ( x ) = log ⁡ p ( z ) + log ⁡ ∣ det ⁡ J ∣ \log p(x) = \log p(z) + \log |\det J| logp(x)=logp(z)+logdetJ
在 MeloTTS 中,通常假设输出服从标准正态分布(Gaussian):
log ⁡ p ( z ) = − 1 2 ( D log ⁡ ( 2 π ) + ∣ z ∣ 2 ) \log p(z) = -\frac{1}{2} (D \log(2\pi) + |z|^2) logp(z)=21(Dlog(2π)+z2)
所以总的 loss 就是:
− log ⁡ p ( x ) = − log ⁡ p ( z ) − log ⁡ ∣ det ⁡ J ∣ -\log p(x) = -\log p(z) - \log |\det J| logp(x)=logp(z)logdetJ
这就是为什么 logdet 直接参与 loss 构造的原因。

logdet 的作用总结

角度解释
数学意义表示变换引起的概率密度变化
物理意义描述输入空间到潜变量空间的“缩放”程度
训练意义控制模型学习如何更好地拟合数据分布
数值表现一般为负值(因为大多数变换是压缩性的)
loss 组成与 log_pz 一起构成最终 loss

直观理解:logdet 如何影响 loss?

场景logdet 影响
变换压缩空间(如 log(x))logdet 为负,loss 增大 → 鼓励模型少做压缩性变换
变换扩展空间(如 exp(x))logdet 为正,loss 减小 → 鼓励模型更自由地变换
数据更容易被映射到高概率区域logdet 更大 → loss 更小 → 模型学得更好
http://www.xdnf.cn/news/906463.html

相关文章:

  • 【信息系统项目管理师-案例真题】2025上半年(第二批)案例分析答案和详解(回忆版)
  • 蓝牙攻防实战指南:发现隐藏设备
  • 【更新至2024年】2000-2024年上市公司财务困境MertonDD模型数据(含原始数据+结果)
  • LangChain【5】之工具调用:连接大模型与现实世界的桥梁
  • C#中的密封类与静态类:特性、区别与应用实例
  • (力扣)80. 删除有序数组中的重复项 II
  • Seed1.5-VL登顶,国产闭源模型弯道超车丨多模态模型5月最新榜单揭晓
  • 计算机视觉顶刊《International Journal of Computer Vision》2025年5月前沿热点可视化分析
  • C++课设:简易日历程序(支持传统节假日 + 二十四节气 + 个人纪念日管理)
  • java复习 03
  • css元素的after制作斜向的删除线
  • 【Go面试陷阱】对未初始化的chan进行读写为何会卡死?
  • Jenkins 工作流程
  • NoSQL之redis哨兵
  • 《SQL基础教程》第五章 SQL进阶之路:掌握高级查询的核心技巧
  • 2.1 Windows编译环境介绍
  • Caliper 配置文件解析:config.yaml
  • 加密货币钱包开发指南:多链资产管理与非托管安全范式
  • 关于iview组件中使用 table , 绑定序号分页后序号从1开始的解决方案
  • Appium+python自动化(十一)- 元素定位- 下
  • 串:探索 KMP 算法的高效模式匹配之旅
  • Nestjs框架: nestjs-schedule模块注册流程,源码解析与定时备份数据库
  • 【通义万相 Wan2.1】在并行智算云上的部署教程
  • 跨分割信号的回流路径处理
  • 毫米波雷达基础理论(3D+4D)
  • 【Servo】信号激励;激励数据、采集数据、跟踪数据
  • 我爱学算法之—— 前缀和(中)
  • 进程的详解,命令行参数,程序的地址空间(Linux)
  • 学习日记-day23-6.6
  • C++11异常特性