news 2026/9/25 12:17:17

ESPnet2 语音情感分析实战:基于 Switchboard 情感标注数据的 Conformer ASR 多任务方案

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
ESPnet2 语音情感分析实战:基于 Switchboard 情感标注数据的 Conformer ASR 多任务方案
  • 人工智能
  • 语音
  • 音频
  • 深度学习
  • NLP

【免费下载链接】espnet

End-to-End Speech Processing Toolkit

项目地址:https://gitcode.com/gh_mirrors/es/espnet
点击查看免费下载

导读

本文围绕 ESPnet2 仓库中的egs2/swbd_sentiment/asr1语音情感分析(Speech Sentiment)配方展开,讲解如何利用 Switchboard Sentiment 语料(LDC2020T14)将「情感分类」作为 ASR 多任务输出进行联合建模:模型在识别转写文本的同时,预测每句话的 Positive / Neutral / Negative 情感标签。读完本文,你将掌握该配方的数据准备流程(含多数投票标签消歧)、两套可复现的训练配置(纯 Conformer 与 wav2vec2.0 前端)、F1 评测脚本的调用方式,以及官方实验的基线结果与预训练模型资源。

一、任务背景与数据集

1.1 什么是语音情感分析

语音情感分析(Speech Sentiment Analysis)的目标是从一句话语音中判定说话人的情感倾向。与传统的"意图分类"(Intent Classification)不同,本配方将情感分类与 ASR 结合在一起:同一个模型既输出转写文本,又输出情感标签,属于 ESPnet2 ASR 多任务学习(multi-task)的典型应用。

该配方的核心数据是Speech Sentiment Annotations(Switchboard Sentiment),语料来自 LDC(编号 LDC2020T14),配套论文为 LREC 2020 的《Switchboard Sentiment》相关工作。它基于经典的 Switchboard 电话对话语料(LDC97S62)人工标注了每句话的情感倾向。

1.2 标签体系与多数投票

每个话语的情感标注可能包含多个子标签(例如Neutral-{Questioning}#Neutral-{No emotion}#Neutral-{No emotion},其中#分隔多个标注者的意见)。egs2/swbd_sentiment/asr1/local/prepare_sentiment.py中的majorityvote()函数实现了论文所述的多数投票(majority voting)消歧策略:

  • 统计一句话中 Positive / Neutral / Negative 三类标签的出现次数;
  • 取出现次数最多的类别作为最终标签;
  • 若最高票出现并列(len(keys) != 1),则丢弃该样本(返回-1)。
def majorityvote(line): count_pos = line.count("Positive") count_neu = line.count("Neutral") count_neg = line.count("Negative") dic = {"Positive": count_pos, "Neutral": count_neu, "Negative": count_neg} max_value = max(dic.values()) keys = [key for key, value in dic.items() if value == max_value] label = keys[0] if len(keys) == 1 else -1 return label

最终文本行的格式为utt_id <情感标签> <转写文本>,即标签被拼接在转写文本之前,作为序列的第一个 token,与 ASR 输出共用同一个 Transformer 解码器——这就是"预测转写的同时预测情感"的实现方式。

二、数据准备与配方运行

2.1 前置数据与目录配置

运行前需在egs2/swbd_sentiment/asr1/db.sh中设置SWBD变量,指向存放 LDC 语料的根目录。egs2/swbd_sentiment/asr1/local/data.sh假设:

  • Switchboard 原始语料位于${SWBD}/LDC97S62;
  • 情感标注文件位于${SWBD}/speech_sentiment_annotations/data/sentiment_labels.tsv。

2.2 数据准备流水线

local/data.sh分为三个阶段:

Stage 1:数据准备——调用swbd1_data_download.sh、swbd1_prepare_dict.sh、swbd1_data_prep.sh完成 Switchboard 标准数据准备;随后用sed给data/train/wav.scp追加sox管道,将 8k 采样率上采样到 16k,使配方与其他 ESPnet2 配方保持一致。

Stage 2:文本清洗——备份原文后通过sed移除._、.等符号,并修正them_1等特殊词:

sed -i 's/\._/ /g; s/\.//g; s/them_1/them/g' data/train/text

Stage 3:情感标注与转写拼接——调用prepare_sentiment.py,将情感标签与转写文本对齐并拼接,同时按行号范围切分 train / dev / test:

python3 local/prepare_sentiment.py \ --train_dir data/train/ \ --dev_dir data/dev/ \ --test_dir data/test/ \ --sentiment_file ${swbd_sentiment} \ --text_file data/local/tmp/text \ --wavscp_file data/local/tmp/wav.scp

该脚本内部会:

  1. 以sentiment_labels.tsv为基准逐行读取(utt_id、起止时间、情感标签);
  2. 在文本文件中按相近时间戳(允许eps = 0.05秒的误差)匹配对应转写,见prepare_sentiment.py中start_time_id >= float2str(float(start) - eps)的判断逻辑;
  3. 调用normalize_transcript()清洗转写:去除标点(保留撇号)、去除[LAUGHTER]等标签、拆开撇号缩写、合并多余空格;
  4. 写出utt2spk、segments、text、wav.scp、reco2file_and_channel等 Kaldi 风格数据文件。

训练 / 验证 / 测试划分:官方没有提供标准切分,配方参照论文(arXiv 1911.09762)采用train 90%、dev 5%、test 5%的比例,对应情感标注文件的行区间为0-47056、47056-49673、49673-52293。

2.3 一键运行入口

egs2/swbd_sentiment/asr1/run.sh是配方的主入口,关键参数如下:

train_set="train" valid_set="dev" test_sets="test dev" ./asr.sh \ --lang en \ --ngpu 1 \ --use_lm false \ --nbpe 5000 \ --token_type word \ --feats_type raw \ --max_wav_duration 30 \ --inference_nj 8 \ --inference_asr_model valid.acc.ave_10best.pth \ --asr_config "${asr_config}" \ --inference_config "${inference_config}" \ --feats_normalize "utterance_mvn" \ --train_set "${train_set}" \ --valid_set "${valid_set}" \ --test_sets "${test_sets}" "$@"

要点说明:

  • --token_type word:词级 token 化。情感标签作为独立词 token 进入词表;
  • --use_lm false:不训练语言模型,解码时不使用 LM;
  • --feats_type raw:直接使用原始波形(配合--feats_normalize utterance_mvn),特征在前端/预处理器中即时计算;
  • --inference_asr_model valid.acc.ave_10best.pth:解码时选用验证集准确率最优的 10 个模型平均权重;
  • asr.sh会依据--skip_stages等机制跳过 LM、ngram、packing、上传等无关阶段(详见egs2/swbd_sentiment/asr1/asr.sh中的 skip 逻辑)。

说明:当前仓库run.sh默认引用conf/train_asr.yaml,而文档中的两组实验结果分别使用conf/tuning/下的两个 Conformer 配置;复现实验时应将--asr_config指向对应的 tuning 配置。

三、实验一:Conformer + Transformer 解码器 + 频谱增强

3.1 核心配置

完整配置见 train_asr_conformer.yaml,关键参数如下:

# encoder related encoder: conformer encoder_conf: output_size: 512 attention_heads: 4 linear_units: 2048 num_blocks: 12 dropout_rate: 0.1 positional_dropout_rate: 0.1 attention_dropout_rate: 0.1 input_layer: conv2d normalize_before: true macaron_style: true pos_enc_layer_type: "rel_pos" selfattention_layer_type: "rel_selfattn" activation_type: "swish" use_cnn_module: true cnn_module_kernel: 31 # decoder related decoder: transformer decoder_conf: attention_heads: 4 linear_units: 2048 num_blocks: 6 dropout_rate: 0.1 positional_dropout_rate: 0.1 self_attention_dropout_rate: 0.1 src_attention_dropout_rate: 0.1 optim: adam optim_conf: lr: 0.0025 scheduler: warmuplr scheduler_conf: warmup_steps: 40000 batch_type: numel batch_bins: 40000000 accum_grad: 3 max_epoch: 50

该配置的技术要点:

  • Conformer 编码器:12 层、输出维度 512、4 头注意力、前馈隐藏层 2048;启用macaron_style(Macaron 结构)、相对位置编码(rel_pos)与相对自注意力(rel_selfattn)、swish激活、卷积模块内核尺寸 31,input_layer: conv2d表示用二维卷积对输入特征做下采样;
  • Transformer 解码器:6 层、4 头注意力、线性单元 2048,各 dropout 均为 0.1;
  • 训练策略:Adam 优化器(lr=0.0025)+ WarmupLR 调度器(40000 步预热);batch_type: numel按总元素数动态组批(4000 万 bins),accum_grad: 3累积梯度,最多 50 个 epoch;
  • 频谱增强(SpecAugment):时域 warping(窗口 5、bicubic 插值)、2 个频带掩码(宽度 0~30)、2 个时间掩码(宽度 0~40);
  • 模型选择:best_model_criterion以验证集acc最大化为目标,keep_nbest_models: 10保留 Top-10 权重用于平均。

3.2 实验结果

该配置的官方结果如下(labels 为 Positive / Neutral / Negative,token_type 为 word):

datasetSntMacro F1 (%)Weighted F1 (%)Micro F1 (%)
decode_asr_asr_model_valid.acc.ave_10best/valid241561.065.065.6
decode_asr_asr_model_valid.acc.ave_10best/test243864.464.464.6

对应的预训练模型:YushiUeda_swbd_sentiment_asr_train_asr_conformer(可在 HuggingFace 的 espnet 组织下查找,配合asr.sh --download_model参数直接用于解码)。

四、实验二:wav2vec2.0 自监督前端 + Conformer

4.1 核心配置

第二组实验引入s3prl 自监督前端(wav2vec2.0),完整配置见 train_asr_conformer_wav2vec2.yaml。与实验一的差异集中在前端部分:

encoder: conformer encoder_conf: output_size: 512 attention_heads: 8 linear_units: 2048 num_blocks: 12 ... use_cnn_module: true cnn_module_kernel: 31 decoder: transformer decoder_conf: attention_heads: 8 linear_units: 2048 num_blocks: 6 ... freeze_param: [ "frontend.upstream" ] frontend: s3prl frontend_conf: frontend_conf: upstream: wav2vec2_large_ll60k # If the upstream is changed, please change the input_size in the preencoder. # If using hubert, change the above line to "upstream: hubert_large_ll60k" download_dir: ./hub multilayer_feature: True preencoder: linear preencoder_conf: input_size: 1024 # If the upstream is changed, please change this value accordingly. output_size: 80 model_conf: ctc_weight: 0.3 lsm_weight: 0.1 length_normalized_loss: false extract_feats_in_collect_stats: false

关键差异解读:

  • frontend: s3prl:使用 s3prl 工具箱加载预训练自监督模型wav2vec2_large_ll60k(如需 hubert 可改为hubert_large_ll60k),权重下载到./hub;
  • freeze_param: ["frontend.upstream"]:冻结 wav2vec2 上游网络参数,只训练下游部分,避免大规模微调导致显存与训练开销过高;
  • preencoder: linear:线性降维层将 wav2vec2 的 1024 维表征压缩到 80 维,再送入 Conformer 编码器——注释明确提示更换 upstream 时需同步修改input_size;
  • multilayer_feature: True:取 wav2vec2 多层特征的组合(s3prl 的加权层融合机制);
  • ctc_weight: 0.3:训练损失按 0.3 权重引入 CTC 分支,与注意力机制联合训练;
  • lsm_weight: 0.1:标签平滑权重 0.1;
  • extract_feats_in_collect_stats: false:在 collect stats 阶段(asr.sh stage 10)生成伪统计文件而非真正前向前端提取特征,显著降低预训练特征提取开销;
  • 其余训练策略与实验一基本一致,仅warmup_steps调整为 25000。

4.2 实验结果

datasetSntMacro F1 (%)Weighted F1 (%)Micro F1 (%)
decode_asr_asr_model_valid.acc.ave_10best/valid241564.567.567.4
decode_asr_asr_model_valid.acc.ave_10best/test243864.166.566.3

对比可见,引入 wav2vec2.0 自监督特征后,情感分类 F1 全面提升(测试集 Macro F1 从 61.4 提升到 64.1,Weighted F1 从 64.4 提升到 66.5),验证了自监督语音表征对情感这类韵律/语义相关任务的增益。对应预训练模型:YushiUeda_swbd_sentiment_asr_train_asr_conformer_wav2vec2。

五、评测脚本:如何计算 F1 分数

5.1 统一评测入口

egs2/swbd_sentiment/asr1/local/score.sh是评测入口,默认针对inference_asr_model_valid.acc.ave_10best的 devel / test 解码结果,依次调用三个 Python 脚本:

python local/score.py --exp_root ${asr_expdir} python local/generate_asr_files.py --exp_root ${asr_expdir} python local/f1_score.py --exp_root ${asr_expdir}

随后用sclite对剥离情感标签后的纯转写计算 WER,将结果写入score_wer/result_asr.txt:

sclite -r "${asr_expdir}/${valid_inference_folder}/score_wer/ref_asr.trn" trn \ -h "${asr_expdir}/${valid_inference_folder}/score_wer/hyp_asr.trn" trn \ -i rm -o all stdout > "${asr_expdir}/${valid_inference_folder}/score_wer/result_asr.txt"

5.2 F1 计算细节

egs2/swbd_sentiment/asr1/local/score_f1.py使用sklearn.metrics.f1_score分别计算三种 F1:

  • Macro F1:三个类别各自 F1 的算术平均(average="macro"),对类别不平衡不敏感;
  • Weighted F1:按各类样本数加权的 F1(average="weighted");
  • Micro F1:全局混淆矩阵上计算的 F1(average="micro")。
macro_f1 = f1_score(ref_list, hyp_list, average="macro", labels=["Positive", "Neutral", "Negative"]) weighted_f1 = f1_score(ref_list, hyp_list, average="weighted", labels=["Positive", "Neutral", "Negative"]) micro_f1 = f1_score(ref_list, hyp_list, average="micro", labels=["Positive", "Neutral", "Negative"])

而local/score.py则输出按首 token 逐句比对的意图分类准确率,并负责从假设/参考文本中剥离情感标签生成纯 ASR 转写文件(hyp_asr.trn/ref_asr.trn),供 sclite 计算 WER 使用。

六、复现与扩展建议

6.1 复现步骤速览

  1. 在egs2/swbd_sentiment/asr1/db.sh中配置SWBD路径(需具备 LDC 语料访问权限);
  2. 运行run.sh默认流程完成数据准备(stage 1-3);
  3. 按实验目标选择 tuning 配置并执行训练:./run.sh --asr_config conf/tuning/train_asr_conformer_wav2vec2.yaml(实验二);
  4. 训练完成后自动解码并调用local/score.sh输出 F1 与 WER;
  5. 如需使用预训练模型直接推理,可用asr.sh --download_model <HF 模型名> --skip_train true加载valid.acc.ave_10best权重。

6.2 环境信息参考

README 中记录的官方实验环境(2022 年 3 月):

  • Python 3.7.11、PyTorch 1.9.0+cu102、ESPnet 0.10.7a1;
  • Git commit:3b53aedc654fd30a828689c2139a1e130adac077。

需要注意的是,当前仓库代码已演进,直接复现时建议以仓库当前安装要求为准;情感标注数据sentiment_labels.tsv需通过 LDC 渠道获取,仓库仅提供处理脚本。

6.3 扩展方向

  • 更换自监督上游:将upstream改为hubert_large_ll60k等模型时,务必同步调整preencoder_conf.input_size(参见配置内注释);
  • 调整多任务权重:修改model_conf.ctc_weight、lsm_weight观察对情感分类与 ASR 的权衡;
  • 标签策略:prepare_sentiment.py的多数投票与时间戳容差(eps=0.05)可根据标注特性调整,进而影响样本规模与标签质量。

七、总结

egs2/swbd_sentiment/asr1配方展示了 ESPnet2 如何以 ASR 多任务框架统一处理「转写 + 情感分类」:通过把情感标签拼接到文本序列头部,无需改动模型结构即可让 Transformer 解码器同时输出两者。两组官方基线证明:在 Conformer + SpecAugment 基础上叠加 wav2vec2.0 自监督前端(冻结上游 + 线性降维),可在测试集上将情感分类 Macro F1 从 61.4 提升至 64.1。配合仓库提供的 prepare_sentiment.py、score_f1.py 与两套 tuning 配置,该配方可完整复现并作为语音情感分析任务的起点。

  • 人工智能
  • 语音
  • 音频
  • 深度学习
  • NLP

【免费下载链接】espnet

End-to-End Speech Processing Toolkit

项目地址:https://gitcode.com/gh_mirrors/es/espnet
点击查看免费下载

相关推荐

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/25 12:17:06

STM32红外PM2.5通信原理与NEC协议解析实战

1. 为什么STM32接红外PM2.5传感器不是“插上线就能用”的事在嵌入式课程设计、毕业项目甚至小型环境监测设备开发中&#xff0c;“STM32连接红外PM2.5传感器”这个标题听起来简单直接——不就是把传感器模块的VCC、GND、TX/RX接到单片机上&#xff0c;串口读数据吗&#xff1f;…

作者头像 李华
网站建设 2026/9/25 12:15:41

Atlas 300V AI推理加速卡部署YOLO实战:从环境配置到性能调优

1. Atlas 300V 24G的身份确认&#xff1a;它是AI推理加速卡&#xff0c;不是显卡1.1 从"运算加速卡"这个问题说起先说结论&#xff1a;Atlas 300V 24G 是运算加速卡&#xff0c;但它是AI推理加速卡&#xff0c;不是传统意义上的GPU显卡。这个问题看似简单&#xff0c…

作者头像 李华
网站建设 2026/9/25 12:13:49

Atlas 300V部署YOLO实战:AI推理加速卡的环境搭建与调优指南

如果你最近在找 atlas 部署 yolo 的方法&#xff0c;大概率是两种情况&#xff1a;要么手上已经躺着一块 Atlas 300V&#xff0c;正对着各种环境报错发愁&#xff1b;要么还在犹豫&#xff0c;想确认这卡到底能不能用来跑 YOLO。先给结论&#xff1a;Atlas 300V 确实是一张运算…

作者头像 李华
网站建设 2026/9/25 12:07:56

天津短视频代拍运营公司推荐:有实力的服务商合作实力参考

现在越来越多天津实体企业布局短视频线上获客&#xff0c;不少工厂在运营过程中都会遇到这类问题&#xff1a;没有专业内容创作团队&#xff0c;自己拍的内容播放不少但没咨询&#xff0c;找售后完善的短视频代拍运营企业合作&#xff0c;却不知道该怎么筛选靠谱机构。不少企业…

作者头像 李华
网站建设 2026/9/25 12:07:41

Codex 快速接入 DeepSeek V4:用 CC Switch 与 config.toml 一次跑通

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华