简单transformer运用

通俗易懂解读:hw04.py 文件内容与 Transformer 的应用

这个文件是一个 Python 脚本(hw04.py),用于完成 NTU 2021 Spring 机器学习课程的 HW4 作业任务:扬声器分类(Speaker Classification) 。它主要通过 Transformer 模型(尤其是自注意力机制,Self-Attention)来实现分类,并提供了训练和推理代码。以下我会详细讲解文件的结构,重点教你如何使用 Transformer 和 Self-Attention,并让你明白如何训练模型、调整参数。


1. 文件概述
  • 任务:从语音特征(梅尔频谱图,mel-spectrogram)中分类扬声器(600 个类别)。
  • 数据集:Voxceleb2 数据集的子集,包含 600 个扬声器的音频特征。
  • 目标
    • 学习使用 Transformer 模型(Simple 级别)。
    • 调整 Transformer 参数(Medium 级别)。
    • 构建 Conformer(Hard 级别,代码中未实现)。
    • 进一步实现 Self-Attention Pooling 和 Additive Margin Softmax(Boss 级别,代码中未实现)。
  • 代码结构
    • 数据准备:解压数据、加载数据集、定义 DataLoader。
    • 模型定义:使用 TransformerEncoderLayer 实现分类器。
    • 训练:实现训练循环、学习率调度和验证。
    • 推理:加载模型,预测测试集扬声器并生成提交文件。

2. Transformer 和 Self-Attention 的原理与应用

先简单讲解 Transformer 和 Self-Attention 的原理,然后结合代码看它们如何被使用。

(1) Transformer 和 Self-Attention 原理
  • Transformer
    • 由 Google 在 2017 年论文《Attention is All You Need》提出,是一种基于注意力机制的模型,取代了传统的 RNN。
    • 核心组件:自注意力(Self-Attention)前馈神经网络(Feedforward Network)
    • 优点:能并行处理序列(不像 RNN 逐个处理),捕捉长距离依赖。
  • Self-Attention
    • 是一种注意力机制,让模型在处理序列中的每个元素时,关注整个序列的其他元素。
    • 比如处理"[苹果, 香蕉, 橙子]"时,Self-Attention 会计算:
      • "苹果"和其他元素(香蕉、橙子)的相关性。
      • "香蕉"和其他元素的相关性,依此类推。
    • 计算步骤
      1. 将输入序列(每个元素是一个向量)映射为 Query(Q)、Key(K)、Value(V)三个向量。
      2. 计算注意力分数:Attention(Q,K,V)=softmax(QKTdk)V \text{Attention}(Q, K, V) = \text{softmax}(\frac{QK^T}{\sqrt{d_k}})V Attention(Q,K,V)=softmax(dkQKT)V。
      3. 输出一个加权后的向量,表示当前元素对整个序列的关注结果。
(2) 代码中的 Transformer 和 Self-Attention
  • 模型定义 (Classifier 类):

    python

    收起自动换行运行
    复制

    class Classifier(nn.Module): def __init__(self, d_model=80, n_spks=600, dropout=0.1): super().__init__() self.prenet = nn.Linear(40, d_model) self.encoder_layer = nn.TransformerEncoderLayer( d_model=d_model, dim_feedforward=256, nhead=2 ) self.pred_layer = nn.Sequential( nn.Linear(d_model, d_model), nn.ReLU(), nn.Linear(d_model, n_spks), )

    • self.prenet:将输入特征(梅尔频谱图,维度为 40)投影到 d_model=80 的维度,为 Transformer 处理做准备。
    • self.encoder_layer:使用 PyTorch 的 nn.TransformerEncoderLayer,这是一个标准的 Transformer 编码层,包含:
      • Self-Attention:通过 nhead=2 设置多头注意力(Multi-Head Attention),将 d_model 均分为 2 头,每头处理 d_model/nhead=40 维度。
      • Feedforward Network:通过 dim_feedforward=256 设置前馈网络的隐藏层维度。
      • 默认使用 dropout(0.1)和 ReLU 激活函数。
    • 代码中注释掉了一个 nn.TransformerEncoder,原本应该是堆叠多个 TransformerEncoderLayer(比如 num_layers=2),但当前只用了一层。
  • 前向传播 (forward 方法):

    python

    收起自动换行运行
    复制

    def forward(self, mels): out = self.prenet(mels) # (batch size, length, 40) -> (batch size, length, d_model) out = out.permute(1, 0, 2) # (batch size, length, d_model) -> (length, batch size, d_model) out = self.encoder_layer(out) # Transformer 编码 out = out.transpose(0, 1) # (length, batch size, d_model) -> (batch size, length, d_model) stats = out.mean(dim=1) # 平均池化:(batch size, d_model) out = self.pred_layer(stats) # (batch size, n_spks) return out

    • Self-Attention 的作用
      • 输入 mels 是梅尔频谱图,形状为 (batch size, length, 40),表示一个 batch 的音频特征。
      • 经过 self.prenet,维度变成 (batch size, length, d_model)。
      • out = out.permute(1, 0, 2) 调整维度为 (length, batch size, d_model),因为 TransformerEncoderLayer 期望输入是 (sequence length, batch size, d_model)。
      • self.encoder_layer(out) 执行 Self-Attention 和 Feedforward 操作:
        • Self-Attention 计算每个时间步(帧)对其他所有帧的关注权重。
        • Feedforward 对每个帧独立应用前馈网络。
      • 最后通过平均池化(out.mean(dim=1))将序列维度压缩,得到每个样本的特征向量 (batch size, d_model),再通过 self.pred_layer 输出分类结果 (batch size, n_spks)。

3. 如何使用 Transformer

通过这个代码,我教你如何在 PyTorch 中使用 Transformer 来完成一个分类任务。

(1) 定义 Transformer 模型
  • 使用 nn.TransformerEncoderLayer 构建基本层: python

    收起自动换行运行
    复制

    self.encoder_layer = nn.TransformerEncoderLayer( d_model=d_model, # 输入和输出的特征维度 nhead=2, # 多头注意力的头数,d_model 必须能被 nhead 整除 dim_feedforward=256, # 前馈网络的隐藏层维度 dropout=0.1 # dropout 比例 )

  • 如果需要堆叠多层,可以用 nn.TransformerEncoder: python

    收起自动换行运行
    复制

    self.encoder = nn.TransformerEncoder(self.encoder_layer, num_layers=2)
    (代码中注释掉了这部分,当前只用了一层。)

(2) 输入数据准备
  • Transformer 需要输入形状为 (sequence length, batch size, d_model):
    • 代码中通过 out.permute(1, 0, 2) 调整维度。
    • 输入的 mels 是 (batch size, length, 40),先通过 self.prenet 投影到 d_model=80,再调整维度。
(3) 前向传播
  • 直接调用 self.encoder_layer(out),PyTorch 会自动处理 Self-Attention 和 Feedforward。
  • 输出需要根据任务调整:
    • 这里是分类任务,所以用平均池化(out.mean(dim=1))压缩序列维度,然后通过全连接层输出分类结果。
(4) 应用场景
  • Transformer 适合处理序列数据(如语音、文本)。
  • Self-Attention 让模型能捕捉序列中任意两个位置之间的关系,比如语音中不同帧之间的关联。

4. 如何训练模型

训练一个模型需要准备数据、定义模型、设置优化器和学习率调度器,然后进入训练循环。以下是代码中的训练过程解析。

(1) 数据准备
  • 数据集 (myDataset 类):
    • 加载梅尔频谱图(torch.load),随机截取 segment_len=128 帧。
    • 标签是扬声器 ID(从 mapping.json 中获取)。
  • DataLoader (get_dataloader 函数):
    • 按 90%(训练)/10%(验证)划分数据集。
    • 使用 collate_batch 函数填充批次数据,确保长度一致(填充值为 -20,表示极小的对数值)。
(2) 模型和优化器
  • 模型:model = Classifier(n_spks=speaker_num).to(device),初始化 Classifier。
  • 损失函数:criterion = nn.CrossEntropyLoss(),用于多分类任务。
  • 优化器:optimizer = AdamW(model.parameters(), lr=1e-3),使用 AdamW 优化器,初始学习率 1e-3。
  • 学习率调度器 (get_cosine_schedule_with_warmup):
    • 包含 Warmup 阶段(前 1000 步,学习率从 0 线性增加到 1e-3)。
    • 之后按余弦衰减(Cosine Decay)降低学习率。
(3) 训练循环(main 函数)
  • 训练步骤

    python

    收起自动换行运行
    复制

    for step in range(total_steps): batch = next(train_iterator) loss, accuracy = model_fn(batch, model, criterion, device) loss.backward() optimizer.step() scheduler.step() optimizer.zero_grad()

    • 每步从 train_loader 获取一个批次。
    • 计算损失和准确率(model_fn)。
    • 反向传播、优化器更新参数、调度器调整学习率、清空梯度。
  • 验证

    • 每 2000 步(valid_steps)验证一次,计算验证集准确率。
    • 保存最佳模型(best_accuracy)。
  • 保存模型:每 10,000 步(save_steps)保存最佳模型到 model.ckpt。

(4) 推理(main 函数,推理部分)
  • 加载训练好的模型,预测测试集扬声器,生成 output.csv(格式:Id, Category)。

5. 如何调整 Transformer 参数

调整 Transformer 参数是 HW4 的 Medium 级别任务。以下是代码中可以调整的部分,以及调整的意义。

(1) 调整参数的地方
  • 在 Classifier 的 init 中: python

    收起自动换行运行
    复制

    self.encoder_layer = nn.TransformerEncoderLayer( d_model=d_model, dim_feedforward=256, nhead=2 )

    • d_model=80:特征维度,增加会提升模型容量,但计算量更大。
    • nhead=2:多头注意力头数,d_model 必须能被整除(当前 80/2=40)。
    • dim_feedforward=256:前馈网络隐藏层维度,增加会增强模型表达能力。
  • 堆叠多层(当前注释掉了): python

    收起自动换行运行
    复制

    self.encoder = nn.TransformerEncoder(self.encoder_layer, num_layers=2)

    • num_layers=2:增加层数会让模型更深,能捕捉更复杂的模式,但可能过拟合。
(2) 调整建议
  • 增大 d_model:比如从 80 增加到 128,增强模型容量,但需要确保 nhead 能整除(比如 nhead=4)。
  • 增加 nhead:比如从 2 增加到 4,允许多头注意力捕捉更多不同类型的依赖关系。
  • 调整 dim_feedforward:比如从 256 增加到 512,增强前馈网络的能力。
  • 增加层数:取消注释 self.encoder,设置 num_layers=3,让模型更深。
  • 调整 dropout:默认 0.1,可以尝试 0.2 或 0.05,防止过拟合。
  • 效果:文档中提到(HW04.pdf 第13页),调整参数后公共基准从 0.82523(Simple)提升到 0.90547(Medium)。
(3) 注意事项
  • 增加参数会增加计算量,可能需要更大的 batch size 或更长的训练时间。
  • 过大的模型可能过拟合,需要调整学习率或增加 dropout。

6. 总结:如何使用 Transformer 训练模型
  • 步骤
    1. 准备数据:加载梅尔频谱图,划分训练/验证集,用 DataLoader 批次加载。
    2. 定义模型:使用 nn.TransformerEncoderLayer,设置 d_model、nhead 等参数。
    3. 前向传播:通过 Self-Attention 处理序列,池化后输出分类结果。
    4. 训练:设置优化器、学习率调度器,循环计算损失、更新参数。
    5. 调整参数:修改 d_model、nhead、num_layers 等,优化性能。
  • Self-Attention 的作用:捕捉序列中帧与帧之间的关系,比如语音中不同时间点的关联。
  • 训练技巧
    • 使用 Warmup 学习率调度(代码中已实现)。
    • 定期验证,保存最佳模型。
    • 调整参数时,观察验证集准确率,避免过拟合。

7. 动手实践

如果你想自己训练一个类似模型,可以用以下步骤:

  1. 环境准备
    • 安装 PyTorch:pip install torch
    • 下载数据集(代码中的链接已失效,可用其他语音数据集如 LibriSpeech 替代)。
  2. 修改代码
  3. 训练
    • 运行 main 函数,设置 total_steps=70000,观察验证准确率。
  4. 推理
    • 用训练好的模型预测测试集,生成提交文件

逐行讲解 Conformer 代码实现

由于你之前没有接触过 Conformer,我会从零开始详细讲解之前提供的 ConformerBlock 和 ConformerConvModule 的代码实现,逐行分析其功能、原理和实现细节。Conformer 是 Transformer 的变种,专为语音任务设计,结合了全局建模(Self-Attention)和局部建模(卷积)的优势。以下代码来自之前修改的 hw04.py,我们会重点聚焦 Conformer 的实现部分。


1. Conformer 代码实现

以下是 ConformerConvModule 和 ConformerBlock 的完整代码,我会逐行解释其作用。

python 复制代码
import torch
import torch.nn as nn
import torch.nn.functional as F

# 卷积模块,用于捕捉局部特征
class ConformerConvModule(nn.Module):
    def __init__(self, d_model=80, kernel_size=31, dropout=0.1):
        super().__init__()
        # Pointwise Convolution 1
        self.pointwise_conv1 = nn.Conv1d(d_model, d_model * 2, kernel_size=1, stride=1, padding=0, bias=True)
        self.glu = nn.GLU(dim=1)  # Gated Linear Unit
        # Depthwise Convolution
        self.depthwise_conv = nn.Conv1d(
            d_model,
            d_model,
            kernel_size=kernel_size,
            stride=1,
            padding=(kernel_size - 1) // 2,
            groups=d_model,  # Depthwise
            bias=True
        )
        self.bn = nn.BatchNorm1d(d_model)
        self.swish = nn.Swish()
        # Pointwise Convolution 2
        self.pointwise_conv2 = nn.Conv1d(d_model, d_model, kernel_size=1, stride=1, padding=0, bias=True)
        self.dropout = nn.Dropout(dropout)

    def forward(self, x):
        # x: (batch, length, d_model) -> (batch, d_model, length) for conv
        x = x.transpose(1, 2)
        # Pointwise Conv 1 + GLU
        x = self.pointwise_conv1(x)
        x = self.glu(x)
        # Depthwise Conv + BN + Swish
        x = self.depthwise_conv(x)
        x = self.bn(x)
        x = self.swish(x)
        # Pointwise Conv 2
        x = self.pointwise_conv2(x)
        x = self.dropout(x)
        # Back to (batch, length, d_model)
        x = x.transpose(1, 2)
        return x

# Conformer 块,包含 FFN、Self-Attention 和卷积模块
class ConformerBlock(nn.Module):
    def __init__(self, d_model=80, nhead=2, dim_feedforward=256, dropout=0.1, kernel_size=31):
        super().__init__()
        # Feed-Forward Module (half-step)
        self.ffn1 = nn.Sequential(
            nn.LayerNorm(d_model),
            nn.Linear(d_model, dim_feedforward),
            nn.Swish(),
            nn.Dropout(dropout),
            nn.Linear(dim_feedforward, d_model)
        )
        # Multi-Head Self-Attention
        self.self_attention = nn.MultiheadAttention(d_model, nhead, dropout=dropout)
        self.norm1 = nn.LayerNorm(d_model)
        self.dropout1 = nn.Dropout(dropout)
        # Convolution Module
        self.conv_module = ConformerConvModule(d_model, kernel_size, dropout)
        self.norm2 = nn.LayerNorm(d_model)
        self.dropout2 = nn.Dropout(dropout)
        # Feed-Forward Module (half-step)
        self.ffn2 = nn.Sequential(
            nn.LayerNorm(d_model),
            nn.Linear(d_model, dim_feedforward),
            nn.Swish(),
            nn.Dropout(dropout),
            nn.Linear(dim_feedforward, d_model)
        )
        self.norm3 = nn.LayerNorm(d_model)
        self.dropout3 = nn.Dropout(dropout)

    def forward(self, x):
        # x: (length, batch, d_model)
        # FFN 1 (half-step)
        x = x + 0.5 * self.dropout1(self.ffn1(x))
        # Multi-Head Self-Attention
        attn_output, _ = self.self_attention(x, x, x)
        x = self.norm1(x + self.dropout1(attn_output))
        # Convolution Module
        x = self.norm2(x + self.dropout2(self.conv_module(x)))
        # FFN 2 (half-step)
        x = self.norm3(x + self.dropout3(self.ffn2(x)))
        return x

2. 逐行讲解 ConformerConvModule
(1) 初始化方法 init

python

收起自动换行运行

复制

class ConformerConvModule(nn.Module): def __init__(self, d_model=80, kernel_size=31, dropout=0.1):

  • class ConformerConvModule(nn.Module):定义一个卷积模块,继承 PyTorch 的 nn.Module 类,所有神经网络模块都需要继承这个类。
  • d_model=80:输入和输出的特征维度(类似 Transformer 的隐藏维度)。
  • kernel_size=31:卷积核大小,决定了捕捉局部特征的范围(越大,感受野越大)。
  • dropout=0.1:Dropout 比例,防止过拟合。

python

收起自动换行运行

复制

super().__init__()

  • 调用父类 nn.Module 的初始化方法,确保正确初始化模块。

python

收起自动换行运行

复制

self.pointwise_conv1 = nn.Conv1d(d_model, d_model * 2, kernel_size=1, stride=1, padding=0, bias=True)

  • nn.Conv1d:一维卷积,适用于序列数据(如语音的梅尔频谱图)。
  • d_model:输入通道数(特征维度)。
  • d_model * 2:输出通道数,升维到两倍,用于后续 GLU(Gated Linear Unit)操作。
  • kernel_size=1:点卷积(Pointwise Convolution),只对每个时间步独立操作,不涉及邻域。
  • stride=1:步幅为 1,不改变序列长度。
  • padding=0:无填充,因为 kernel_size=1 不需要填充。
  • bias=True:包含偏置参数。

python

收起自动换行运行

复制

self.glu = nn.GLU(dim=1) # Gated Linear Unit

  • nn.GLU:Gated Linear Unit,一种门控机制。
  • dim=1:在通道维度上操作(因为输入是 (batch, channel, length))。
  • GLU 的作用:将 d_model * 2 的通道分成两部分,一部分作为值,另一部分通过 sigmoid 激活作为门控,输出 d_model 个通道。公式为: GLU(x)=x1⋅σ(x2)\text{GLU}(x) = x_1 \cdot \sigma(x_2)GLU(x)=x1⋅σ(x2) 其中 x1 x_1 x1 和 x2 x_2 x2 是通道拆分的两部分。

python

收起自动换行运行

复制

self.depthwise_conv = nn.Conv1d( d_model, d_model, kernel_size=kernel_size, stride=1, padding=(kernel_size - 1) // 2, groups=d_model, # Depthwise bias=True )

  • nn.Conv1d:定义深度可分离卷积(Depthwise Convolution)。
  • d_model:输入和输出通道数保持一致。
  • kernel_size=31:卷积核大小,捕捉局部特征。
  • stride=1:步幅为 1。
  • padding=(kernel_size - 1) // 2:自动计算填充,确保输出长度不变(例如 kernel_size=31 时,padding=15)。
  • groups=d_model:深度卷积,每个输入通道独立卷积,减少参数量。
  • bias=True:包含偏置。

python

收起自动换行运行

复制

self.bn = nn.BatchNorm1d(d_model)

  • nn.BatchNorm1d:一维批归一化,作用于通道维度。
  • 归一化每个通道的特征,加速训练,稳定梯度。

python

收起自动换行运行

复制

self.swish = nn.Swish()

  • nn.Swish:激活函数,公式为 Swish(x)=x⋅σ(x) \text{Swish}(x) = x \cdot \sigma(x) Swish(x)=x⋅σ(x),比 ReLU 更平滑。

python

收起自动换行运行

复制

self.pointwise_conv2 = nn.Conv1d(d_model, d_model, kernel_size=1, stride=1, padding=0, bias=True)

  • 第二个点卷积,将特征降维回 d_model。

python

收起自动换行运行

复制

self.dropout = nn.Dropout(dropout)

  • Dropout 层,随机丢弃部分神经元,防止过拟合。
(2) 前向传播方法 forward

python

收起自动换行运行

复制

def forward(self, x):

  • 定义前向传播,输入 x 是 (batch, length, d_model) 的张量。

python

收起自动换行运行

复制

x = x.transpose(1, 2)

  • transpose(1, 2):将 (batch, length, d_model) 转换为 (batch, d_model, length),因为 nn.Conv1d 期望输入是 (batch, channel, length)。

python

收起自动换行运行

复制

x = self.pointwise_conv1(x)

  • 应用第一个点卷积,将通道数从 d_model 升到 d_model * 2。

python

收起自动换行运行

复制

x = self.glu(x)

  • 应用 GLU,将通道数降回 d_model,并通过门控机制选择性保留信息。

python

收起自动换行运行

复制

x = self.depthwise_conv(x)

  • 应用深度卷积,捕捉局部特征(kernel_size=31 覆盖 31 个时间步)。

python

收起自动换行运行

复制

x = self.bn(x)

  • 应用批归一化,稳定特征分布。

python

收起自动换行运行

复制

x = self.swish(x)

  • 应用 Swish 激活,增加非线性。

python

收起自动换行运行

复制

x = self.pointwise_conv2(x)

  • 应用第二个点卷积,进一步处理特征,保持维度为 (batch, d_model, length)。

python

收起自动换行运行

复制

x = self.dropout(x)

  • 应用 Dropout,防止过拟合。

python

收起自动换行运行

复制

x = x.transpose(1, 2)

  • 将维度转回 (batch, length, d_model),与输入一致。

python

收起自动换行运行

复制

return x

  • 返回处理后的张量。

3. 逐行讲解 ConformerBlock
(1) 初始化方法 init

python

收起自动换行运行

复制

class ConformerBlock(nn.Module): def __init__(self, d_model=80, nhead=2, dim_feedforward=256, dropout=0.1, kernel_size=31):

  • 定义 Conformer 块,参数与 ConformerConvModule 类似。
  • nhead=2:多头注意力的头数。
  • dim_feedforward=256:前馈网络的隐藏层维度。

python

收起自动换行运行

复制

super().__init__()

python

收起自动换行运行

复制

self.ffn1 = nn.Sequential( nn.LayerNorm(d_model), nn.Linear(d_model, dim_feedforward), nn.Swish(), nn.Dropout(dropout), nn.Linear(dim_feedforward, d_model) )

  • 定义第一个前馈模块(FFN1)。
  • nn.LayerNorm(d_model):层归一化,归一化每个时间步的特征。
  • nn.Linear(d_model, dim_feedforward):将维度从 d_model 扩展到 dim_feedforward。
  • nn.Swish():Swish 激活。
  • nn.Dropout(dropout):Dropout。
  • nn.Linear(dim_feedforward, d_model):降维回 d_model。

python

收起自动换行运行

复制

self.self_attention = nn.MultiheadAttention(d_model, nhead, dropout=dropout)

  • nn.MultiheadAttention:多头自注意力。
  • d_model:输入维度。
  • nhead=2:头数,每头处理 d_model/nhead=40 维度。
  • dropout=dropout:注意力中的 Dropout。

python

收起自动换行运行

复制

self.norm1 = nn.LayerNorm(d_model) self.dropout1 = nn.Dropout(dropout)

  • norm1 和 dropout1:用于自注意力后的归一化和 Dropout。

python

收起自动换行运行

复制

self.conv_module = ConformerConvModule(d_model, kernel_size, dropout)

  • 调用 ConformerConvModule,处理局部特征。

python

收起自动换行运行

复制

self.norm2 = nn.LayerNorm(d_model) self.dropout2 = nn.Dropout(dropout)

  • norm2 和 dropout2:卷积模块后的归一化和 Dropout。

python

收起自动换行运行

复制

self.ffn2 = nn.Sequential( nn.LayerNorm(d_model), nn.Linear(d_model, dim_feedforward), nn.Swish(), nn.Dropout(dropout), nn.Linear(dim_feedforward, d_model) )

  • 定义第二个前馈模块(FFN2),结构与 FFN1 相同。

python

收起自动换行运行

复制

self.norm3 = nn.LayerNorm(d_model) self.dropout3 = nn.Dropout(dropout)

  • norm3 和 dropout3:FFN2 后的归一化和 Dropout。
(2) 前向传播方法 forward

python

收起自动换行运行

复制

def forward(self, x):

  • 输入 x 是 (length, batch, d_model),符合 Transformer 的输入格式。

python

收起自动换行运行

复制

x = x + 0.5 * self.dropout1(self.ffn1(x))

  • 应用 FFN1,半步前馈(系数 0.5 是 Conformer 的设计)。
  • self.ffn1(x):通过 FFN1 处理。
  • self.dropout1(...):应用 Dropout。
  • x + 0.5 * ...:残差连接,稳定训练。

python

收起自动换行运行

复制

attn_output, _ = self.self_attention(x, x, x)

  • 应用多头自注意力。
  • self.self_attention(x, x, x):输入 Query、Key、Value 均为 x,计算自注意力。
  • attn_output:注意力输出,形状仍为 (length, batch, d_model)。
  • _:忽略注意力权重。

python

收起自动换行运行

复制

x = self.norm1(x + self.dropout1(attn_output))

  • x + self.dropout1(attn_output):残差连接。
  • self.norm1(...):层归一化。

python

收起自动换行运行

复制

x = self.norm2(x + self.dropout2(self.conv_module(x)))

  • 应用卷积模块。
  • self.conv_module(x):通过 ConformerConvModule 处理。
  • self.dropout2(...):Dropout。
  • x + ...:残差连接。
  • self.norm2(...):层归一化。

python

收起自动换行运行

复制

x = self.norm3(x + self.dropout3(self.ffn2(x)))

  • 应用 FFN2,与 FFN1 类似。

python

收起自动换行运行

复制

return x

  • 返回处理后的张量,形状不变。

4. 总结与使用
  • ConformerConvModule:通过卷积捕捉局部特征,适合语音任务中的短时相关性。
  • ConformerBlock:结合 FFN、Self-Attention 和卷积,平衡全局和局部建模。
  • 如何使用
    • 在 Classifier 中替换 TransformerEncoderLayer 为 ConformerBlock。
    • 堆叠多层:self.encoder = nn.Sequential(*[ConformerBlock(...) for _ in range(2)])。
    • 调整参数(如 d_model、kernel_size)优化性能。
相关推荐
云卓SKYDROID3 分钟前
无人机光纤FC接口模块技术分析
人工智能·无人机·科普·高科技
宋一诺3310 分钟前
机器学习——什么时候使用决策树
人工智能·决策树·机器学习
RaceSnail17 分钟前
昇腾NPU上基于MindIE服务的AIME和MATH500测评方案
人工智能
LaughingZhu27 分钟前
PH热榜 | 2025-06-05
前端·人工智能·经验分享·搜索引擎·产品运营
大模型真好玩28 分钟前
最强大模型评测工具EvalScope——模型好不好我自己说了算!
前端·人工智能·python
MYH51637 分钟前
GPU加速与非加速的深度学习张量计算对比Demo,使用PyTorch展示关键差异
人工智能·pytorch·深度学习
追光的独行者1 小时前
Dify工作流实践—根据word需求文档编写测试用例到Excel中
人工智能
新知图书1 小时前
OpenCV在图像上绘制文字示例
人工智能·opencv·计算机视觉
lowcode1 小时前
MCP协议在LLM系统中的架构与实现原理研究
人工智能·llm·mcp
声网1 小时前
中科大、月之暗面等开源对话式语音合成模型 MoonCast;ChatGPT 发布「录音模式」,自动录音和生成会议纪要丨日报
人工智能