03|门控残差结构与条件对齐
门控残差块把“历史”和“这个时刻要生成什么”结合起来。本篇沿一张结构图读模块,再用两个通道的具体数值走完门控、残差与 skip,最后检查条件边界。
读图先分清: residual 送下一层,skip 送输出头;条件与被预测的目标对齐。
1. 门控残差块的计算结构

图 1|门控残差块的计算结构
蓝色路径读取历史,绿色路径注入条件,橙色路径产生门控结果。 各步骤与图中的节点对应如下:
| 节点 | 输入到输出 | 应检查的关系 |
|---|---|---|
| 历史卷积与条件投影 | 两路分别得到 [B,2C,T],随后相加 | 两路时间轴必须对齐 |
| 通道拆分 | [B,2C,T] → 两份 [B,C,T] | 拆通道,不拆时间 |
| 门控 | tanh 结果与 sigmoid 结果逐元素相乘 | 形状一致,得到 |
| 残差 | 投影后与直达的 相加并缩放 | 图左侧恒等通路没有经过门控 |
| skip | 经独立投影送输出头 | 不作为下一块的主干输入 |
导读中的原论文图 4 给出基本骨架;此图根据本教程实际代码重画,进一步显式画出条件投影、两个独立的 1×1 分支,以及 /√2。两图用途不同,不能把本图的所有选择都归为论文固定配置。
隐藏输入 的形状为 [B,C,T],条件 为 [B,H,T]。
输入维度说明
| 数学记号 | 含义、单位与示例 |
|---|---|
| 批大小;本例为 。 | |
| 隐藏通道数;本例为 。 | |
| 网络时间长度;本例为 。 | |
| 条件通道数;本例为 。 |
一个残差块的计算为:
门控残差块:符号与张量形状
| 数学记号 | 含义、单位与示例 |
|---|---|
| 因果时间卷积;本例核宽为 。 | |
隐藏输入,形状为 [B,C,T]。 | |
与目标对齐的条件,形状为 [B,H,T]。 | |
tanh 分支的卷积权重,形状为 [C,C,2]。 | |
sigmoid 分支的卷积权重,形状同上;代码把两支合为 [2C,C,2]。 | |
tanh 分支的条件投影,矩阵形状为 [C,H]。 | |
| sigmoid 分支的条件投影;逐位置应用,等价于 1×1 卷积。 | |
| tanh 分支的总偏置,包含历史卷积与条件投影的偏置,长度为 。 | |
| sigmoid 分支的总偏置,长度为 。 | |
tanh 分支激活前的张量,形状为 [B,C,T]。 | |
| sigmoid 分支激活前的张量;单独的 与带下标的偏置 不同。 | |
| 双曲正切函数,输出范围为 。 | |
| sigmoid 函数,输出范围为 。 | |
| 逐元素乘法。 | |
门控结果,形状为 [B,C,T]。 | |
残差分支的独立投影矩阵,形状为 [C,C]。 | |
| 残差投影的偏置,长度为 。 | |
skip 分支的独立投影矩阵,形状为 [C,C]。 | |
| skip 投影的偏置,长度为 。 | |
送入下一层的残差结果,形状为 [B,C,T]。 | |
送入输出头的 skip 结果,形状为 [B,C,T]。 | |
| 本教程采用的残差缩放因子。 |
1×1 卷积只混合当前位置的通道,不扩大时间感受野。残差保留 的直达路径,skip 让输出头读取不同深度的结果;两路不是同一个张量换名。上述 /√2 是本教学实现的尺度控制选择,并非原论文所有实现的固定规定。原论文 §2.3—2.5
2. 双通道门控与残差计算示例

图 2|双通道门控与残差计算
固定一个时间位置,取 。下表逐步代入; 是 tanh 的反函数:
| 步骤 | 设定或计算 | 结果 |
|---|---|---|
| 内容分支 | ||
| 门分支 | ||
| 逐元素门控 | ||
| 残差支路 | ,投影为恒等、偏置为零 | |
| skip 支路 | 投影为 2 倍恒等、偏置为零 |
门值可以单独核验:对激活前标量 ,。
门值是连续缩放,不是布尔开关;residual 与 skip 使用独立参数,因此结果不同。 门也不必对应某个可以命名的语音概念。
下面五行正好对应图中的步骤。返回值顺序是“下一层输入、输出头支路”,调用方必须分别接住。
def forward(self, x, cond):
a, b = (self.causal(x) + self.condition(cond)).chunk(2, dim=1)
z = torch.tanh(a) * torch.sigmoid(b)
return (x + self.residual(z)) / math.sqrt(2), self.skip(z)
chunk(2,dim=1) 沿通道拆分,48 通道变成两份 24 通道;不是把时间截成两段。加法前两项都是 [4,48,512],乘法前两项都是 [4,24,512]。这两项 shape 检查比记类名更能发现实现问题。
3. 条件注入与时间对齐
| 条件类型 | 时间上的变化 | 注入方式 | 例子 |
|---|---|---|---|
| 全局条件 | 整段固定 | 投影后沿时间广播 | 说话人向量 |
| 局部条件 | 随位置或帧变化 | 对齐每个预测目标后注入 | 语言特征或声学帧 |
源码只有局部接口 cond_target[B,H,T],没有额外的说话人 embedding。 即使某条人工信号的条件恰好不变,也沿用这个逐位置接口。
本实验使用两个条件通道,各块分别学习自己的条件投影:
| 通道 | 定义与单位 | 125 Hz、振幅 0.55 的例子 |
|---|---|---|
| 基频通道 | ,无量纲 | |
| 振幅通道 | 无量纲振幅系数 |
因此输入条件为 [0.5,0.55],在这一条人工信号内保持不变。

图 3|条件帧与预测目标对齐
图中使用另一组便于算边界的教学配置:采样率 16 kHz,条件每 10 ms 一帧,因此一帧覆盖 16000×0.010=160 点。帧 0 覆盖目标 …,帧 1 从 开始。用 预测 时,条件必须切到帧 1。
一种最简单的对齐规则是 。
条件对齐:索引说明
| 数学记号 | 含义、单位与示例 |
|---|---|
| 网络输入的位置。 | |
| 当前输入对应的波形预测目标位置。 | |
| 网络位置 所使用的目标条件。 | |
| 条件帧的索引。 | |
| 第 帧的条件向量。 | |
| 向下取整;点号代表需要取整的表达式。 | |
| 本例每帧覆盖的波形采样点数。 |
代入 得帧 , 得帧 。这个例子假设音频与条件从同一起点开始,没有额外前瞻或上采样延迟。
代码的 cond[:,:,1:] 正在完成“与目标同偏移”。条件的时间 shape 正确,不代表帧边界就正确。真实系统还要统一裁剪起点、补零、上采样延迟;简单重复或可学习上采样只是实现选项,不能替代索引约定。
本实验的限制: 因为每条信号的条件是常数,错位一格也看不出来。接真实数据前应构造在指定索引突然变化的条件,检查目标落在边界左右时读到哪一帧。离线 TTS 可以利用已知的整句文本;禁止偷看的是尚未生成的目标波形。流式系统还需另行约束条件网络的前瞻。
4. 参数量核算与结构校验
固定 、。每行乘法计算权重,末尾加法计算偏置:
| 部件 | 参数计算 | 参数数 |
|---|---|---|
| 单块因果卷积 | ||
| 单块条件投影 | ||
| 单块残差投影 | ||
| 单块 skip 投影 | ||
| 12 个块 | ||
| Embedding | ||
| 输出头 | ||
| 全模型 |
总数与脚本统计一致。参数数与 shape 是必要检查,但不能独自证明连接关系正确。
自测:删掉 skip、只把最后一层残差送输出头,shape 能否仍然正确?能,但网络函数已改变,不能仅靠 shape 证明结构忠实。下一篇会展示各层 skip 怎样汇总,以及损失究竟在哪里计算。
正在连接 GitHub 评论…