unilm (edgelm) GSLM:基于 ASR 的语音生成单位 LM 评估流程完整指南
2026/9/13 3:27:32 网站建设 项目流程

unilm (edgelm) GSLM:基于 ASR 的语音生成单位 LM 评估流程完整指南

【免费下载链接】unilmLarge-scale Self-supervised Pre-training Across Tasks, Languages, and Modalities项目地址: https://gitcode.com/GitHub_Trending/un/unilm

本文围绕 unilm 仓库中edgelm/examples/textless_nlp下的 GSLM(Generative Speech Language Model)文本无关 NLP 评测体系,以 ASR-based evaluation 官方文档为核心,完整讲解从 UTS 合成音频到后处理指标计算的端到端流程:16kHz 降采样与长度对齐预处理、wav2vec2 + KenLM 语言模型的 ASR 推理配置、以及 PPX / Self-BLEU / Auto-BLEU / Continuation-BLEU / AUC 五类指标脚本的实现细节与可复制命令。读完本文,你可以照步骤跑通整条语音语言模型的评测流水线,并理解每个指标在源码中的具体算法。

一、评估流程总览:从 ULM 采样到 ASR 指标

根据 ASR 评估 README,对一个 ULM(Unit Language Model,语音单位语言模型)做 ASR-based 评估的完整生命周期包含五个步骤:

  1. 训练 ULM 并从其采样(对应 ULM 目录 下的采样流程,入口为 sample.py);
  2. 运行 UTS(Unit-to-Speech,即 Tacotron2 风格的声码器/解码器)把采样出的单位序列合成为音频(对应 unit2speech 目录 的synthesize_audio_from_units.py等);
  3. ASR 预处理:将合成音频降采样到 16kHz,并把生成音频长度对齐到与 ground-truth 话语一致;
  4. 运行 ASR,得到文字转写结果;
  5. 计算后 ASR 评估指标(PPX、Self/Auto-BLEU、Continuation-BLEU、AUC)。

该评估思想的关键在于:ULM 生成的是离散语音单位(HuBERT 等特征聚类的 code),没有天然的文本标签。通过"单位序列 → 音频(UTS)→ 文字(ASR)→ 文本指标"这条链路,把无监督语音生成质量转化为可量化、可比较的文本指标,用于衡量续写(continuation)任务的流畅度、多样性与对原话语的延续能力。官方文档明确说明:本文档假定前两步已完成,只聚焦第 3~5 步。

二、预处理一:批量降采样到 16kHz

ASR 模型(wav2vec2 960h 模型)输入为 16kHz 音频,因此第一步是把 UTS 的输出音频整体转为 16kHz WAV。官方给出的批量转换命令为:

python $FAIRSEQ_ROOT/examples/textless_nlp/gslm/unit2speech/convert_to_16k.py $UTS_OUTPUT $UTS_OUTPUT_DOWNSAMPLE

其中$UTS_OUTPUT是 UTS 生成的音频目录,$UTS_OUTPUT_DOWNSAMPLE是存放降采样结果的目标目录。

从源码看,convert_to_16k.py 的实现要点:

  • 递归遍历输入目录,收集指定扩展名(默认wav,可通过--extension覆盖)的所有音频文件,find_all_files负责路径枚举;
  • 对每个文件调用系统工具sox,命令为sox -c 1 -b 16 <input> -t wav <output> rate 16k,即单声道、16-bit、16kHz 重采样;
  • 自动在输出目录中复刻输入目录的相对层级结构,并用progressbar显示转换进度。

因此该脚本运行前需要系统已安装sox,且 Python 环境装有progressbar依赖。

三、预处理二:按 ground-truth 长度对齐(cut_as)

官方文档指出,"长度对齐"是可选步骤:如果你希望比较同一前缀下生成语音与 ground-truth 语音在流畅度和多样性上的差异,最好强制两者长度一致。命令为:

python $FAIRSEQ_ROOT/examples/textless_nlp/asr_metrics/cut_as.py \ --samples_dir=$UTS_OUTPUT_DOWNSAMPLE --out_dir=$UTS_OUTPUT_DOWNSAMPLE_CUT \ --prompts_description=data/ground_truth_continuation_dev.json

参数说明:

参数含义
--samples_dir降采样后的 UTS 输出目录(即上一步结果)
--out_dir截断/对齐后的音频输出目录
--prompts_descriptionground-truth 续写描述 JSON 文件

其中ground_truth_continuation_dev.json是包含 LibriSpeech dev-clean ground-truth 文本及元数据的 JSON 文件,通常用于 dev-clean 评估;同样地存在面向 test-clean 的ground_truth_continuation_test.json。这两个文件均可从官方 textless_nlp 评估数据资源下载(fbaipublicfiles 的 textless_nlp/gslm/eval_data 路径),且文件内收录的音频序列时长均不低于 6 秒——这一点在源码中被硬断言校验(见下文指标脚本)。

从源码看,cut_as.py 的核心逻辑:

  • 逐文件用torchaudio.load读取音频,并断言采样率必须为 16000Hz(assert sr == 16_000),说明必须放在 16k 转换之后执行;
  • 文件名采用<prompt_id>__<suffix>.wav的命名约定,脚本用name.split('__')[0]提取 prompt id 去 JSON 描述中查该样本的 ground-truth 时长description[name_prompt][0]
  • 目标帧数target_frames = int(l * sr):若生成音频足够长则截断到目标长度(返回 flag=1),否则原样保留并打印 "is not long enough";
  • 最后汇总输出Total files: N; sufficiently long: M,用于检查有多少样本完成了长度对齐。

四、运行 ASR:wav2vec2 + KenLM 解码

4.1 生成 manifest 文件

评估采用预训练的 wav2vec2 模型做 ASR。首先需要生成 manifest 文件——它告诉 ASR 系统要转写哪些音频。命令为:

python $FAIRSEQ_ROOT/examples/wav2vec/wav2vec_manifest.py \ $UTS_OUTPUT_DOWNSAMPLE_CUT --valid-percent 0.0 --dest $MANIFEST_DIR --ext wav
  • $UTS_OUTPUT_DOWNSAMPLE_CUT:预处理后的 UTS 输出目录;
  • --valid-percent 0.0:不做验证集切分,全部音频进入训练集切分(即train.tsv);
  • $MANIFEST_DIR:输出目录,脚本在此生成 TSV 清单。

该脚本在当前仓库中存在,路径为 wav2vec_manifest.py。ASR 推理所需的 960h_scratch.pt 检查点、KenLM、Flashlight decoder 以及 KenLM 4-gram 英文语言模型,需按 wav2vec 官方 README 的说明准备与安装(KenLM 与 Flashlight 解码器为额外依赖)。

4.2 生成 dummy 转写文件

官方 out-of-the-box 的评估脚本需要 ground-truth 转写文件来驱动其指标计算流程。但 ULM 生成的是新话语,没有对应的 ground-truth 文本,因此这里生成 dummy transcripts 代替:

cp $FAIRSEQ_ROOT/examples/textless_nlp/gslm/asr_metrics/misc/dict.ltr.txt $MANIFEST_DIR python $FAIRSEQ_ROOT/examples/textless_nlp/gslm/asr_metrics/misc/dummy_asr_data.py \ --tsv=$MANIFEST_DIR/train.tsv --output-dir=$MANIFEST_DIR

第一个文件 dict.ltr.txt 是 LTR 字母表字典,每行一个字母及其分值(共 28 行,如E 51860T 38431……最后以|结束),配合--labels ltr使用。需要说明:当前仓库的misc/目录中实际包含 bleu_utils.py、cut_as.py 与dict.ltr.txt,README 中引用的dummy_asr_data.py脚本在现仓库中未见同路径文件,执行时若缺失可自行按其参数(--tsv--output-dir)补齐一个依据 TSV 生成空转写的占位脚本。

4.3 执行 ASR 推理

一切就绪后运行推理脚本:

mkdir -p asr python $FAIRSEQ_ROOT/examples/speech_recognition/infer.py \ $MANIFEST_DIR \ --task audio_pretraining --nbest 1 --path 960h_scratch.pt \ --gen-subset=train --results-path $PATH_TO_ASR_OUTPUT \ --w2l-decoder kenlm --lm-model 4-gram.bin \ --lexicon librispeech/lexicon_ltr.lst --word-score -1 \ --sil-weight 0 --lm-weight 2 --criterion ctc --labels ltr --max-tokens 300000 --remove-bpe letter

关键参数逐项说明:

参数作用
--task audio_pretraining使用 wav2vec2 的音频自监督预训练任务接口加载模型
--nbest 1每条音频只输出 1 个最优假设
--path 960h_scratch.pt960h LibriSpeech 训练的 wav2vec2 检查点
--gen-subset=traintrain.tsv中全部音频推理(因 manifest 全部切给了 train)
--w2l-decoder kenlm/--lm-model 4-gram.bin使用 KenLM 4-gram 语言模型做 word-to-letter 解码
--lexicon librispeech/lexicon_ltr.lstLibriSpeech 字母表词汇表(官方 eval_data 资源提供)
--criterion ctc --labels ltrCTC 解码,标签空间为 LTR 字母
--word-score -1 --sil-weight 0 --lm-weight 2解码打分权重:词分 -1、静音权重 0、LM 权重 2
--max-tokens 300000单批最大 token 数,控制显存占用
--remove-bpe letter解码后去掉 letter 级 BPE 分隔符,输出干净字母序列

推理入口 infer.py 位于仓库edgelm/examples/speech_recognition/下。输出目录$PATH_TO_ASR_OUTPUT中会生成形如hypo.word-960h_scratch.pt-train.txt的转写文件,每行以序列 ID 结尾,后续所有指标脚本都依赖这个行格式。

五、评估指标:在最短 1000 条 ≥6s 序列上计算

官方规定评估在"时长至少 6 秒的最短 1000 条序列"上进行。三个指标脚本都接受 manifest 与ground_truth_continuation_*文件路径,用于从 ASR 转写中筛出这批目标样本。这个筛选逻辑在各脚本中是同构的:读取 JSON 描述,断言所有序列时长>= 6.0秒,按时长排序取前 1000 个 prompt id,再按 manifest 行号(跳过表头f.readline())映射出目标行集合。

5.1 Perplexity(PPX)

命令(源自官方文档):

python ppx.py $PATH_TO_ASR_OUTPUT/hypo.word-960h_scratch.pt-train.txt --cut-tail \ --manifest=$MANIFEST_DIR/train.tsv --prompts-description=data/ground_truth_continuation_dev.json

--cut-tail表示丢弃每行最后一个 token——因为 ASR 输出把序列 ID 放在了行尾。

从源码看,ppx.py 的实现细节比命令行更丰富:

  • 语言模型通过torch.hub.load('pytorch/fairseq', 'transformer_lm.wmt19.en', tokenizer='moses', bpe='fastbpe')加载,即WMT19 英文 Transformer LM,并用.eval().cuda()关闭 dropout 保证打分稳定;
  • 参数包括--asr-transcript(转写文件路径)、--cut-id(去掉行首的 seq id token)、--cut-tail(去掉行尾 token)、--manifest--prompts-description(两者同时提供时才做 1000 条筛选,缺省则对全部行计算);
  • 单句 perplexity 由lm.score(sent)['positional_scores'].mean().neg().item()计算:取逐位置对数概率的均值取负作为平均 NLL,再exp得到该句 perplexity;
  • 对 NaN 值会告警并剔除(NaNs detected!);
  • 最终对logprobperplexity两个统计量分别输出Mean ± SEM(标准误 = 标准差/√N)、Median与 10%~90% 百分位区间。

因此该脚本的运行前提是:GPU 环境 + 可访问 torch.hub 的 fairseq 仓库(仓库本身在edgelm/fairseq/下有 vendored 实现可作参考)。

5.2 Self-BLEU 与 Auto-BLEU

命令:

python self_bleu.py $PATH_TO_ASR_OUTPUT/hypo.word-960h_scratch.pt-train.txt --cut-tail \ --manifest=$MANIFEST_DIR/train.tsv --prompts-description=data/ground_truth_continuation_dev.json

当前仓库中对应脚本为 self_auto_bleu.py(README 中写作self_bleu.py,按现仓库实际文件名调用即可),它一次性并行输出 8 个多样性指标:

指标定义
Self-BLEU2-arithmetic / geometric以其余所有句子的 unigram+bigram 为"参考",计算当前句的 BLEU2(权重 0.5/0.5)
Auto-BLEU2-arithmetic / geometric以句子自身前后文(该 n-gram 左、右侧片段)的 n-gram 集合为参考计算自重复度
Self-BLEU3-arithmetic / geometric同上,扩展到 trigram(权重 1/3 三项)
Auto-BLEU3-arithmetic / geometric同上,trigram 版本

源码要点:

  • Self-BLEU 通过 bleu_utils.py 中的sentence_bleu(rest, hypo, weights, no_length_penalty=True, averaging_mode=...)实现——该文件是从 NLTK 的bleu_score改造而来,两处关键改动:支持关闭长度/简短惩罚(对 Self-BLEU 无意义)以及支持算术平均代替几何平均
  • Auto-BLEU 的auto_bleu函数对句内每个 n-gram,统计它是否重复出现在"左侧 + 右侧"拼接出的 n-gram 集合中,得到 n 阶自重复率,再按算术或几何方式聚合;
  • 8 个任务用multiprocessing.Pool(最多 16 进程)并行计算,最终结果以指标名 均值*100 ± 标准误打印,并支持--debug只跑前 10 条。

5.3 Continuation-BLEU

Continuation-BLEU 衡量"生成的续写"与"原话语 ground-truth 后续文本"的 BLEU 相似度,直接评估 ULM 续写能力。命令:

python continuation_eval.py --asr-transcript $PATH_TO_ASR_OUTPUT/hypo.word-960h_scratch.pt-train.txt \ --manifest=$MANIFEST_DIR/train.tsv --prompts-description=data/ground_truth_continuation_dev.json

continuation_eval.py 的源码逻辑:

  • --take-shortest(默认 1000)控制参与评估的最短序列条数;同样断言所有序列时长 ≥ 6 秒;
  • 从 manifest 建立"行号 → 文件名"的映射(取文件名__前的 prompt id),把 ASR 转写按行尾的序列 ID 归组:sequence_id = int(line[-1].split('-')[1][:-1]),与 manifest 行号对应;
  • 同一 prompt 的多条生成候选放在一起,与该 prompt 的 ground-truth 续写文本(JSON 中original_continuations[k][1])计算sentence_bleu(candidates, ground_truth, weights=(0.5, 0.5), no_length_penalty=True, averaging_mode='geometric'),即几何平均、无长度惩罚的 BLEU2
  • 输出先打印平均续写词数Mean length of continuations, in words,再打印Median BLEU over n examples: 中位数 ± 标准误

5.4 AUC:流畅度-多样性权衡曲线

在 PPX(衡量流畅度)与 Self/Auto-BLEU(衡量多样性,越低越好)都已算出的前提下,可以对不同 ULM(或同一 ULM 不同采样设置/解码温度)的结果点,估计perplexity–diversity 权衡曲线下的 AUC:曲线上各点为 (diversity, PPX) 平面上的样本,AUC 越大表示能以更低困惑度获得更高分多样性,是 GSLM 论文中用于横向对比模型的总结性指标。官方文档提供了配套的 Colab 笔记本做可视化与 AUC 计算。实际使用时,把多个模型各跑一遍上述指标脚本,汇总成 (BLEU, PPX) 散点序列即可。

六、相关文件索引

文件作用
READMEASR-based 评估的官方流程文档(本文核心依据)
gslm/metrics/README.mdGSLM 指标总览(ASR 指标 / ABX 指标 / sWUGGY & sBLIMP)
convert_to_16k.pysox 批量降采样到 16kHz
cut_as.py按 ground-truth 时长截断对齐生成音频
ppx.pyWMT19 LM 打分得到 per-sentence perplexity 统计
self_auto_bleu.py8 种 Self/Auto-BLEU 多样性指标
continuation_eval.pyContinuation-BLEU2 中位数统计
bleu_utils.py支持关闭长度惩罚与算术平均的 NLTK BLEU 改造版
dict.ltr.txtLTR 字母表词典(--labels ltr解码配套)
wav2vec_manifest.py生成 wav2vec2 推理用 TSV manifest
infer.pywav2vec2 + KenLM 的 speech recognition 推理入口

七、注意事项与适用前提

  1. 依赖链较长:该流水线需要sox(16k 转换)、torchaudio(cut_as)、KenLM + Flashlight decoder(ASR 解码)、960h_scratch.pt检查点、LibriSpeechlexicon_ltr.lst以及 4-gram LM 文件;PPX 还需 GPU 与 fairseq hub 可加载的 WMT19 模型。
  2. 文件命名约定:UTS 输出音频必须命名为<prompt_id>__<...>.wavcut_as.py、manifest 行号映射与各指标脚本的序列 ID 解析(line[-1].split('-')[1][:-1])都依赖这一约定,命名不符会导致Cannot find {name}!断言或行号错位。
  3. 评估集固定:所有指标只在"≥6 秒的最短 1000 条 dev-clean 续写序列"上计算,JSON 描述文件与 manifest 必须来自同一评估集,6 秒下限在源码中是硬断言。
  4. 脚本名差异:README 中写的self_bleu.pydummy_asr_data.py在现仓库misc/中分别对应/缺失,调用前请以 asr_metrics 目录 实际文件为准。
  5. 这套指标与 GSLM 指标体系中并列的 ABX(音素类别可区分度,见 abx_metrics)及 ZeroSpeech 的 sWUGGY/sBLIMP 是相互补充的:ASR 指标评估文本层面的流畅度/多样性/续写正确性,ABX 评估量化表征本身的音位结构质量。

【免费下载链接】unilmLarge-scale Self-supervised Pre-training Across Tasks, Languages, and Modalities项目地址: https://gitcode.com/GitHub_Trending/un/unilm

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

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询