wikiAudio06|Glow-TTS:可逆变换与单调对齐搜索02|单调对齐搜索:动态规划与可验证路径
5 分钟
0 次观看

02|单调对齐搜索:动态规划与可验证路径

MAS(Monotonic Alignment Search)不是 softmax 注意力。本实验输入已经计算好的“帧—音素”得分矩阵,输出最佳硬路径;网络如何提供得分属于上游模型。Glow-TTS 论文

递推先计算最优累计得分,回溯再恢复实际对齐路径。 图 1|单调路径的停留、前进与终点约束

图 1|单调路径的停留、前进与终点约束

1. 递推及边界

Dt,i=St,i+max⁡(Dt−1,i,Dt−1,i−1).D_{t,i}=S_{t,i}+\max(D_{t-1,i},D_{t-1,i-1}).
公式符号与约定
符号含义、单位与约定
tt声学帧索引,教学代码从 0 开始。
ii音素索引,教学代码从 0 开始。
St,iS_{t,i}当前帧归属当前音素的局部得分;可来自条件对数似然。
Dt,iD_{t,i}从起点到此单元的最高累计得分。
Dt−1,iD_{t-1,i}上一帧留在同一音素的路径。
Dt−1,i−1D_{t-1,i-1}上一帧位于前一个音素的路径。
max⁡\max选择累计分更高的合法前驱;不合法位置设为负无穷。

起点只允许 (0,0),終点为 (T-1,N-1);帧数 T 至少等于音素数 N。本代码保证每个音素至少占一帧,对零时长特殊符号应在上游先处理。

2. 数据与代码地图

顺序变量作用
输入score[T,N] float局部得分
前向递推dp[T,N] float最优累计得分
前驱记录move[T,N] bool是否来自前一个音素
终点回溯path[T,N]每行一个 1
按帧求和path.sum(0)每个音素的帧数
python19 行
def monotonic_path(score):
    """[frames,phones]; stay or advance by one; every phone gets >=1 frame."""
    frames, phones = score.shape
    if frames < phones: raise ValueError('not enough frames')
    dp = torch.full_like(score, -torch.inf)
    move = torch.zeros_like(score, dtype=torch.bool)
    dp[0,0] = score[0,0]
    for t in range(1, frames):
        for n in range(min(t+1, phones)):
            stay = dp[t-1,n]
            advance = dp[t-1,n-1] if n else score.new_tensor(-torch.inf)
            move[t,n] = advance > stay
            dp[t,n] = score[t,n] + torch.maximum(stay,advance)
    n = phones-1
    path = torch.zeros_like(score)
    for t in range(frames-1,-1,-1):
        path[t,n] = 1
        n -= int(move[t,n])
    return path, dp[-1,-1]

3. 实际检查与数值解释

实验得分矩阵在完整源码中固定;最佳路径为 [0,0,1,2,2],选中分数为 3+2+3+4+5=17,时长为 [2,1,2]。同时枚举五帧分给三个音素的全部正整数时长组合,独立确认 17 是最大值,避免只验证输出形状。

动态规划结果与穷举一致,且每帧恰好分给一个音素。

硬 argmax 路径本身不可按普通连续函数求导;网络是在当前路径下更新,而不是对搜索索引反向传播。

本教学实现用 Python 循环便于阅读,时间与内存复杂度均随 T×N 增长。生产实现通常使用编译后的搜索核并处理 batch mask;把教学版速度当成 Glow-TTS 的模型速度没有意义。运行入口见 机制实验源码,返回 Glow-TTS。

专题导航:TTS 总目录 · 上级章节

正在连接 GitHub 评论…