SHEET MOS:TTS 与语音增强的开源 MOS 打分工具箱

做语音生成(TTS 文本转语音 / VC 音色转换 / SVS 歌声合成)或语音增强的人,多半绕不开一个问题:主观分怎么用一个自动脚本估出来。

MOS (Mean Opinion Score,主观听感均分)本身的定义就是无参考的------找一批 rater 听音频、按 1-5 打分取均值,评的就是"这段音频本身好不好听",跟有没有 clean 参考没关系。问题只是人工打分贵、慢、还漂(不同 rater、不同 session 均分能差 0.3-0.5 MOS),做迭代实验时根本扛不住。

自动化替代大致分两条路:

  • 有参考客观 metric (PESQ / POLQA / STOI / ViSQOL):本质是 degradation metric------衡量的是同一段音频经过某种处理后跟原始 clean 参考的距离,天然只适用于降噪 / AEC / 编解码 / 音效这类"有原始信号在手"的场景。放到 TTS / VC / SVS 上根本无参考可对
  • 无参考神经预测器(DNSMOS / NISQA / UTMOS / SSL-MOS 系列):直接从波形回归到 MOS 数值,不需要参考。逼近的是"如果找 rater 听这段,他们会打多少分"

本文的主题 SHEET(Speech Human Evaluation Estimation Toolkit)是第二条路里的最新代表------Nagoya University 与 NICT 的 Wen-Chin Huang 团队从 2022 年 SSL-MOS 开始持续迭代,最近把整套 pipeline 打包成 PyTorch 工具箱开源,配套 checkpoint 库 https://huggingface.co/unilight/sheet-models 覆盖 8 个训练数据集 × 多个 SSL 主干的多套权重。

一、从 SSL-MOS 到 SHEET

1.1 神经 MOS 预测器的演进

深度学习之前的 no-reference MOS 打分基本没有工业级方案------传统启发式规则跟主观分相关性长期在 0.5 以下。MOSNet (Lo et al., Interspeech 2019)用 CNN-BLSTM 从 STFT 端到端回归 MOS 开路;SSL-MOS (Cooper et al., ICASSP 2022 · https://arxiv.org/abs/2110.02635)把 wav2vec2 / HuBERT / WavLM 等 SSL 主干接一个池化 + 线性头做 fine-tune,成为后续几乎所有工作的骨架;同期 UTMOS(UTokyo-SaruLab · Saeki et al., Interspeech 2022 · https://arxiv.org/abs/2204.02152)走同一路线,在 VoiceMOS Challenge 2022 main + OOD 两个赛道多项指标居前。

但同分布数字漂亮不等于 OOD 稳。SHEET 论文(Huang et al., TASLP 2026 · https://arxiv.org/abs/2411.03715)提出 MOS-Bench :8 训练集 + 17 测试集覆盖 TTS / VC / SVS / 电话 / 增强 / 混杂噪声,系统对比多数据集训练策略后得到反直觉结论------简单 pooling 稳定不输 AlignNet 这类 domain-aware 方法 ,data variation 比 domain-aware modeling 重要。这直接决定了 SHEET 官方主推的 all8 pooling 权重。

1.2 SHEET 家族一览

SHEET 本身不是新算法------它把上面这条线的代码 + 训练配方 + 权重打包成一个可用工具箱:

组件 位置与规模
论文 https://arxiv.org/abs/2411.03715 · TASLP 2026(v1 2024-11 · v2 2026-04)
代码 https://github.com/unilight/sheet · PyTorch · 训练/推理/评测 recipe
权重 https://huggingface.co/unilight/sheet-models · 37 个 checkpoint
模型结构 3 种:SSL-MOS · SSL-MOS+MDF · AlignNet
SSL 主干 4 种:wav2vec2-small · wav2vec2-Large-LL60k · HuBERT-Large-LL60k · WavLM-Large
训练数据组合 8 个单集 + 2 种 pooling:all7(不含 urgent2024,用于 SSL-MOS+MDF / AlignNet 变体)· all8(含 urgent2024,用于 SSL-MOS-WavLM-Large 变体,官方默认推荐)

1.3 三种模型架构

论文 Fig. 1 一张图讲完 SHEET 覆盖的三种结构:

  • SSL-MOS(左) :SSL 主干 → 时间池化 → decoder(一个 linear head)→ MOS ∈ 1, 5。主干占大头(WavLM-Large 316M 参数),head 就一个 nn.Linear。fine-tune 时主干全参放开,学习率给 head 大一档、给 backbone 小一档是常规做法。下面 §三 横评用的 9 套权重全部是这个结构
  • AlignNet(中):多一个 dataset embedding 通道拼进 decoder,学 domain-specific 的 bias/scale。推理时如果知道输入属于某个训练域可以指定 embedding;不知道就走 AlignNet 原论文的"reference dataset"启发式(选一个训练集当默认,比如 NISQA)
  • Dataset embedding retrieval(右):SHEET 论文对 AlignNet 推理侧的改进------用测试样本的 SSL 表征去 datastore 做近邻检索,取最近邻训练样本的 dataset embedding 喂给 decoder。绕过"选 reference dataset"这个启发式

SSL-MOS+MDF (Multi-Domain Fine-tuning)不在这张图里------结构跟 SSL-MOS 一样,只是训练目标从单集扩到多集加权,跟 AlignNet 变体一起绑定 all7 pooling(不含 urgent2024)。SSL-MOS + WavLM-Large 单独绑定 all8 pooling(含 urgent2024),也是 HF 权重库里 all8 只有这一种架构的原因。

论文的实测数字说 AlignNet + retrieval 这套 domain-aware 组合没能稳定超过 直接 pooling:pooling 相当于隐式的 domain-agnostic regularization,多域数据本身把过拟合压住了。这就是为什么 SHEET 官方主推 all8 pooling + SSL-MOS-WavLM-Large 权重。

1.4 8 个训练集与天然适用场景

从论文 Table I(训练集详情)整理出来的核心信息:

训练集 fs (kHz) 语言 音频类型 规模(train+dev) 天然适用
BVCC 16 En TTS / VC 合成 + clean speech 4.9k + 1k TTS/VC 合成质量对比
SOMOS 24 En TTS clean speech(多系统) 14.1k + 3k TTS clean 精细排名
SingMOS 16 Ch/Ja SVS / SVC 唱声 2.0k + 544 唱声合成 / 转换
NISQA 48 En 模拟失真 + 真实通话 + clean 11.0k + 2.7k VoIP 通话质量
TMHINT-QI 16 Ch 噪声 + 增强 + clean(中文短句) 11.6k + 1.3k 中文降噪 / 增强
Tencent 16 Ch 模拟失真 + clean 10.4k + 1.2k 中文合成 / 通话失真
PSTN 8 En 电话线路 + 模拟失真 52.8k + 5.9k 电话质感
URGENT2024-MOS 8--48 En 混杂失真 + 增强 6.2k + 690 通用降噪 / 编解码
all8 pooling mix mix 全部 8 集混训 ~113k + 16k 官方默认推荐 · 未知域 fallback

关键 pattern:训练集自带 domain bias ------PSTN 见的都是 8 kHz 电话,pstn 权重对干净朗读打分会挤在很窄的高分段(后面 §三 横评里 σ<0.08 就是这个原因);SingMOS 只见过唱声,对说话打分不知道校准到哪儿。选对训练集匹配你的输入域,比选大主干重要得多

1.5 长音频处理

SSL 主干原则上接受任意长度输入,但实操里有两个坑:

  • WavLM-Large / HuBERT-Large 在长音频(> 30 s)上显存吃紧,24 GB 显存卡跑一段 60 s 音频容易 OOM
  • 极短音频(< 1 s)做完 pool 后 feature 太少,MOS 预测方差会明显变大

工程上常见处理是 patch 化 :切成 10 s / 30 s 无重叠段,各自过一遍模型,再对 patch 分数取 mean 或 median。SHEET 官方 predict.py 走的是直接送整段的路径,长音频要自己在上层切分(§2.4 会给一段最短实现)。

二、上手:装依赖到打分

2.1 装

本文横评没走 pip 安装,而是从 GitHub clone 一份 SHEET 源码(v0.2.5 tag),用 sys.pathsheet 包和 repo 顶层的 hubconf.py 加进 Python 搜索路径。理由:hubconf.Predictor 是 SHEET repo 顶层 hubconf.py 里的类,不在 sheet/ package 内------pip install sheet_sqa 完这文件也不会进 site-packages,只能靠 sys.path.insert 或走 torch.hub.load 的 cache 拿到。

复制代码
# 实跑
git clone https://github.com/unilight/sheet.git third_party/sheet_repo
cd third_party/sheet_repo && git checkout main   # v0.2.5 tag 的 hubconf.py 有一处漏逗号导致 SyntaxError · main 分支的 `6ce33c0 fix hubconf.py` 已修

# SHEET setup.cfg 里 install_requires 声明的:
#   librosa>=0.8.0 · soundfile>=0.10.2 · pyyaml · h5py>=2.9.0 · filelock ·
#   protobuf<=3.20.1 · scipy · s3prl · faiss-cpu
# 另外 torch / torchaudio / huggingface_hub 用户自己装
pip install librosa soundfile pyyaml h5py filelock 'protobuf<=3.20.1' \
    scipy s3prl faiss-cpu \
    torch torchaudio huggingface_hub

跑分脚本头部把 clone 出来的 repo 目录加进 sys.path

复制代码
# 实跑
import sys
from pathlib import Path

BLOG_ROOT = Path(".").resolve()
sys.path.insert(0, str(BLOG_ROOT / "third_party/sheet_repo"))   # 装 sheet.models.sslmos 和顶层 hubconf.Predictor

sheet 包和 hubconf.py 都在 clone 出来的 repo 顶层(main 分支已修复 v0.2.5 tag 的 SyntaxError),一条 sys.path 全覆盖。SHEET 官方也支持 torch.hub.load("unilight/sheet", ..., trust_repo=True) 走 hub cache 路径------本文横评为了控制版本、避免 tag 撞坑,走显式 clone + sys.path

首次运行会自动从 HF hub 下 config.yml + checkpoint-best.bin~/.cache/huggingface/hub/,主干(WavLM-Large / HuBERT-Large / wav2vec2-Large)走 s3prl 的 ~/.cache/s3prl/download/

2.2 加载 & 打分:hf_hub_download + SSLMOS + Predictor 三件套

本文横评的实跑脚本走的是三件套:hf_hub_downloadconfig.yml + checkpoint-best.bin → 按 config 构造 sheet.models.sslmos.SSLMOShubconf.Predictor 包装做统一的 wav 读取和推理。

复制代码
# 实跑(前面 2.1 的 sys.path 已经设好)
import yaml, torch
from huggingface_hub import hf_hub_download

def build_predictor(prefix: str):
    """Load SSLMOS from HF and wrap in Predictor from hubconf."""
    cfg_path  = hf_hub_download("unilight/sheet-models", filename=prefix + "/config.yml")
    ckpt_path = hf_hub_download("unilight/sheet-models", filename=prefix + "/checkpoint-best.bin")
    with open(cfg_path) as fh:
        cfg = yaml.load(fh, Loader=yaml.Loader)
    from sheet.models.sslmos import SSLMOS      # local import after sys.path
    m = SSLMOS(cfg["model_input"], **cfg["model_params"])
    sd = torch.load(ckpt_path, map_location="cpu", weights_only=False)
    if isinstance(sd, dict) and "model" in sd:
        sd = sd["model"]
    m.load_state_dict(sd)
    m.eval().cuda()
    from hubconf import Predictor                # from third_party/sheet_repo
    return Predictor(m, cfg)

prefix 就是权重在 https://huggingface.co/unilight/sheet-models 上的相对路径,恒为 <训练集>/<arch>-<backbone>/<seed> 三段------§3.1 表格列的 9 套横评权重都是这个格式。想核对当前加载到的到底是什么架构 / 主干,cfg["model_type"]SSLMOS)+ cfg["model_params"]["s3prl_name"]wavlm_large / hubert_large_ll60k / wav2vec2_large_ll60k)是唯一权威。

2.3 wav 预处理和调用

Predictor.predict() 只接受 16 kHz mono 一维 tensor 或本地路径(互斥,两个都给会报错)。横评走 tensor 路径,预处理是标准的三步------resample 到 16 kHz、downmix、峰值归一:

复制代码
# 实跑
import torchaudio

def load_wav(path):
    wav, sr = torchaudio.load(str(path))
    if sr != 16000:
        wav = torchaudio.transforms.Resample(sr, 16000)(wav)
    if wav.dim() > 1:
        wav = wav.mean(0)
    peak = wav.abs().max()
    if peak > 0:
        wav = wav / peak * 0.95
    return wav

wav = load_wav("/path/to/test.wav")
score = predictor.predict(wav=wav.cuda())
print(f"MOS: {score:.3f}")

传路径接口 predictor.predict(wav_path=...)hubconf.read_wav 内部做 resample + downmix + padding(补足到 MIN_REQUIRED_WAV_LENGTH = 1040 采样,否则 SSL 主干因序列过短崩),对短音频更省心;tensor 接口的优势是自己控制预处理和 GPU 分配------横评走 tensor 接口就是这个原因。

2.4 长音频的 patch mean

Predictor.predict() 走整段前向,长音频(> 30 s)在大主干上容易显存吃紧。横评脚本用 10 s 无重叠段各自打分再取均值:

复制代码
# 实跑
@torch.no_grad()
def score_one(predictor, wav, seg: int = 10 * 16000) -> float:
    n = wav.shape[-1]
    if n <= seg:
        return float(predictor.predict(wav=wav.cuda()))
    parts = [float(predictor.predict(wav=wav[i:i + seg].cuda()))
             for i in range(0, n - seg + 1, seg)]
    return sum(parts) / len(parts)

想更稳可以换 median 或改 30 s 窗口,本文横评没跑这两种变体,效果差异不评论。这段实现有个 caveat:无重叠切段 + 不补末尾,音频长度不是 10 s 整数倍时最后 <10 s 的尾巴会被丢弃(例如 25 s 音频只会打 2 段 = 20 s,末 5 s 不计入均值);本文横评语料段长基本在 8-16 s,最多丢一小段尾,不影响相对趋势。

三、9 套权重横评

SHEET 官方权重库 https://huggingface.co/unilight/sheet-models 一共 37 个 checkpoint 文件,分两批格式:9 个新 checkpoint-best.bin (seed=1337,段 2 全部是 sslmos-<backbone>,本文横评就是这 9 套)+ 28 个老 checkpoint-*steps.pkl (seed=2337 / 3337 / 4337,段 2 是 sslmos / sslmos+mdf / alignnet,跟旧 torch.hub.load("default") 那条 legacy 加载路径配对,本文没跑)。

  • .bin 系列覆盖:8 个单数据集 + 1 套 all8 pooling(含 urgent2024)
  • 主干覆盖 wav2vec2-Large-LL60k / HuBERT-Large-LL60k / WavLM-Large

实验口径 :所有权重跑同一批 75 条 16 kHz mono 干净朗读音频(LibriSpeech test-clean 45 条主说话人 + 30 条备选说话人;备选说话人从 test-clean 里剪一批不同 utterance 出来,用于观察同数据集内说话人间的漂移),单 GPU 一次 forward,9 套权重打完全批用时分钟级。分数写进 scores/sheet-all_weights.csv,675 行,按 file, domain, weight_slug, mos 索引。这是同一批干净朗读语音上的相对差异,不代表 zero-shot benchmark 上的绝对能力排序------SHEET 论文 Table 4-6 提供了正式的 OOD 评测数字。

3.1 挑出来的 9 套权重

.bin 系列每套都是 seed=1337 的 SSL-MOS best,各训练集覆盖一个主干配置:

权重 slug 训练域 主干 HF 相对路径(prefix
bvcc TTS/VC 合成 · 2010s 主流数据 WavLM-Large bvcc/sslmos-wavlm_large/1337
somos TTS 合成(Speech Only) HuBERT-Large-LL60k somos/sslmos-hubert_large_ll60k/1337
singmos 唱声合成 SVS wav2vec2-Large-LL60k singmos/sslmos-wav2vec2_large_ll60k/1337
nisqa VoIP / 通话失真 WavLM-Large nisqa/sslmos-wavlm_large/1337
tmhint-qi 增强/降噪(中文短句) wav2vec2-Large-LL60k tmhint-qi/sslmos-wav2vec2_large_ll60k/1337
tencent 通话失真(中文) wav2vec2-Large-LL60k tencent/sslmos-wav2vec2_large_ll60k/1337
pstn 电话线路 wav2vec2-Large-LL60k pstn/sslmos-wav2vec2_large_ll60k/1337
urgent2024 混杂噪声 + 混响 + 编解码 WavLM-Large urgent2024-mos/sslmos-wavlm_large/1337
all8 pooling 上面 8 个一起训 WavLM-Large bvcc+somos+singmos+nisqa+tmhint-qi+tencent+pstn+urgent2024-mos/sslmos-wavlm_large/1337

切权重 = 换 prefix 字符串 ------三件套接口不变,build_predictor(prefix) 直接返回新 predictor。

3.2 循环打 9 套权重的实跑代码

横评主循环的骨架,实际就是外层遍历 9 个 prefix、内层遍历 75 条 wav:

复制代码
# 实跑
WEIGHTS = [
    ("bvcc",       "bvcc/sslmos-wavlm_large/1337"),
    ("somos",      "somos/sslmos-hubert_large_ll60k/1337"),
    ("singmos",    "singmos/sslmos-wav2vec2_large_ll60k/1337"),
    ("nisqa",      "nisqa/sslmos-wavlm_large/1337"),
    ("tmhint-qi",  "tmhint-qi/sslmos-wav2vec2_large_ll60k/1337"),
    ("tencent",    "tencent/sslmos-wav2vec2_large_ll60k/1337"),
    ("pstn",       "pstn/sslmos-wav2vec2_large_ll60k/1337"),
    ("urgent2024", "urgent2024-mos/sslmos-wavlm_large/1337"),
    ("all8",       "bvcc+somos+singmos+nisqa+tmhint-qi+tencent+pstn+urgent2024-mos/sslmos-wavlm_large/1337"),
]

for slug, prefix in WEIGHTS:
    predictor = build_predictor(prefix)
    for path, domain in items:                 # items: [(Path, domain), ...] 共 75 条
        wav = load_wav(path)
        mos = score_one(predictor, wav)        # 内部走 patch mean(§2.4)
        writer.writerow([path.name, domain, slug, f"{mos:.4f}"])
    del predictor
    torch.cuda.empty_cache()                    # 每套跑完释放主干,避免 3 种 SSL 主干同时驻留显存

三个实测坑

  • 每换一个 SSL 主干(wavlm_large / hubert_large_ll60k / wav2vec2_large_ll60k)都要多下一次对应的预训练权重------本次横评 3 种主干各下一次,磁盘占用 ~1 GB。只关心其中 1-2 套权重时只装对应主干即可
  • 跨主干循环必须每套完了 del predictor + torch.cuda.empty_cache()------3 种 SSL 主干(含 WavLM-Large 316M)同时驻留显存很容易 OOM
  • HF 上还有 28 个 .pkl 老格式 checkpoint 跟旧 torch.hub.load("default") legacy 加载路径配对,不能用 SSLMOS 类直接装载(架构不同),本文横评没覆盖这批

3.3 测试语料

  • LibriSpeech test-clean 主组 45 条:全部来自说话人 6930 · 干净朗读 · 单声道 16 kHz · Public Domain
  • LibriSpeech test-clean 备选组 30 条 (下称 librispeech-alt):21 条来自另一说话人 1320 + 9 条仍来自 6930(chapter/utterance 跟主组无重叠)· 用来观察加入新说话人后 MOS 打分的偏移

共 75 条,全走同一段预处理(downmix + resample + peak norm),保证所有权重打分口径一致。原设计里还想放 VCTK 做多口音对比,2026 Q3 起 HuggingFace 上主流的 VCTK 加载脚本被 datasets 新版本废弃、Edinburgh 原始镜像 12 GB 不适合本次快速评测,暂时放弃这个变体;结论段会显式区分本 demo 语料下的相对差异与跨发布 benchmark 两个口径。

3.4 分数分布

三个观察值得单独拎出来:

  • 权重之间存在 1.4 分的系统性偏移 ------同一批干净朗读语音,somos 均值 3.21、tmhint-qi 均值 4.62,两者相差 1.40 MOS,几乎跨了一个 P.800 主观等级(Fair → Good)。跨权重比较绝对分毫无意义,业务侧要盯的是相对趋势(同权重下 A 版本 vs B 版本),不是绝对数字
  • 三套权重逼近饱和pstn(σ=0.054)、tmhint-qi(σ=0.073)、singmos(σ=0.077)在 LibriSpeech 上标准差 <0.08------训练分布只见通话线路(pstn)、增强/降噪场景(tmhint-qi)或唱声(singmos),遇到干净朗读时输出被聚在训练里对应的高分位段(均值分别在 4.20 / 4.62 / 4.46 附近),几乎给全批打同一个分,区分度接近零
  • 加入新说话人会拉高均分 0.4bvccnisqalibrispeech-alt 30 条上的均值分别为 4.18 和 4.30,比主组的 3.77 / 3.89 高出 0.41 / 0.41。但分组内细看:librispeech-alt 里那 9 条仍属主说话人 6930 的样本,均值分别是 3.92 / 3.67(跟主组接近),漂移几乎完全由 21 条新说话人 1320 的样本(均值 4.29 / 4.57)拉起来。换句话说这条差异是"新说话人 1320 被这两个权重打得更高",不是"任意换说话人都会漂"。而 pstn / tmhint-qi / singmos 因为已经饱和,反而看不到明显漂移------分不出来 不等于 稳定

3.5 权重之间的相关性

热力图里能读出三件事:

  • 通话/失真类权重高度扎堆pstntencent ρ=+0.78 · nisqatencent ρ=+0.65 · nisqaurgent2024 ρ=+0.63------四套权重的训练数据里都含电话失真 / VoIP 编解码。但注意 :分说话人复算后 nisqaurgent2024 在 spk 1320 那 21 条上 ρ 掉到 -0.055,说明 pooled 相关性的相当一部分来自"混合说话人"这个结构性差异,不是"对通话质感的一致排序"
  • 合成/唱声类的三套彼此低相关bvccsomos ρ=+0.43 · somossingmos ρ=+0.24------SOMOS 训练的都是同语言不同 TTS 系统对比,SingMOS 训练的是 SVS 唱声,BVCC 是 VMC 官方混合训练集;三者面对同一批干净朗读,各自锚在不同的质量子空间里,排出来的顺序对不上
  • all8 pooling 跟通话/失真类权重更贴近 :ρ(all8, nisqa) = +0.80 · ρ(all8, pstn) = +0.80 · ρ(all8, tencent) = +0.76 · 但 ρ(all8, somos) = +0.45 · ρ(all8, tmhint-qi) = +0.43。分说话人复算 all8pstn 在 spk 1320 上 ρ = -0.147------同样有很大一部分被说话人结构撑起来。至于是不是 pooling 时通话/失真类样本量占大头把 all8 拉过去,本文没做训练采样消融,不下结论

⚠️ 双峰陷阱 :上面三行 ρ 全是在 75 条混合样本上算的,包含"主组 45 条 · 备选组 30 条"这个说话人双峰------bvcc / nisqa 两组间均值差 0.4 分,pstn / tmhint-qi / singmos 已饱和(σ<0.08)两组均值几乎重合,pooled ρ 因此普遍偏高,nisqaurgent2024pstn/all8 一对分说话人复算后甚至翻符号。pooled ρ 只能说明权重对说话人分布差异读到的方向大体一致,说不上对某个质量因素排序一致------想下"合成派 vs 失真派"这类结论得叠训练分布消融 + 分层复算,本文没跑,不下。

3.6 选权重的经验规则

先把警戒写在前面:下面表格和三条建议是从上述 75 条干净朗读的分布观察外推出来的,不是场景选型结论------本文既没有主观 MOS 参考、也没做配对退化实验(同一段音频加不同强度失真的 A/B),SHEET 论文 §VI-A 里明确说过合成训练集并未普遍在合成测试集上占优。真要给业务选权重,请以论文 Table 4-6 的 zero-shot 结果、加你自己的 A/B 配对退化实验为准。

场景(仅参考) 从本 demo 分布看更贴近的权重 本 demo 观察到的对应现象
TTS / VC / SVS 合成质量 bvcc / somos 训练分布对齐 · 分布跟合成/唱声类扎堆低相关
通话/降噪/编解码 pstn / nisqa / urgent2024 都在通话失真类紧密相关簇里
唱声 SVS 单独评估 singmos 独一份 SVS 训练集 · σ 极低 · 别期望强区分度
不确定域 / 快速筛选 all8 pooling 论文 recommend · 稳定但含偏

三条使用建议:

  • 绝对分不可跨权重比 :报数字必带权重名------同样的 3.9 分,bvcc 的 3.9 跟 all8 的 3.9 业务含义完全不同
  • 同权重 A/B 版本的相对趋势值得信 · 但需要 anchor :饱和权重(pstn / tmhint-qi)在相同录音的前后对比上也能给出一致方向;前提是 A/B 音频的域与训练分布对齐,而且最好搭一批人工盲听 anchor 校准打分尺度------本 demo 只有跨说话人分布观察,不构成 A/B 可靠性证据
  • 同方向偏移不能靠合投消除 :本 demo 里 bvccnisqa 在加入说话人 1320 时同方向漂 +0.41 · +0.41 分,等权平均后仍差 +0.41------合投只能对冲相互独立的随机偏移,同方向的分布 shift 一起加权还是原样。多权重合投是否有稳定收益本文没验证,实际部署要看配对 A/B 结果

3.7 分布不匹配 → fine-tune 的入口

跑完 9 套权重发现全都不贴自己业务域,唯一的正路是拿自己的标注数据微调。SHEET repo egs/<dataset>/run.sh 已经把训练配方按 8 个训练集分好目录,直接照着最贴近自己域的那个 recipe 改数据 manifest 就能起步:

  • 架构改动几乎为零 :SSL-MOS = SSL 主干 + 时间池化 + 一个 nn.Linear head,egs/<dataset>/conf/*.yaml 里换 data: 段指到自己的 wav + MOS 标注就行;backbone 用 wavlm_large / hubert_large_ll60k / wav2vec2_large_ll60k 三选一,跟 §4.1 表格里的 9 套权重同源
  • 标注协议参考论文 §III:每条音频 ≥ 5 个 rater、按 1-5 打分、onboarding 用 rater 间一致性阈值(论文用 Pearson > 0.7 类似准则)筛人。业务侧做 in-house 标注按同一协议起步就够
  • 数据规模:8 个训练集里最小的 SingMOS 只有 train 2.0k + dev 544(论文 Table I),量级参考------in-domain 几百到几千条本域样本通常就能显著改善 in-domain 相关性
  • fine-tune 策略:主干全参 fine-tune 是标配,学习率给 head 大一档(1e-3 量级)、给 backbone 小一档(1e-5 量级)是 SSL-MOS 系列的常规做法;数据量少(< 1k)时可以冻结主干只训 head 起步

权重下载与推理脚本:见 https://huggingface.co/unilight/sheet-modelshttps://github.com/unilight/sheet 官方 README。本文没跑 fine-tune,具体流程按官方 README 走。

相关推荐
飞多学堂2 小时前
每日开源硬件精选简报 2026-09-11
驱动开发·开源·开源硬件·硬件开源·电子制作
辰域电子3 小时前
STM32项目开源:环境质量监测系统(代码+原理图+仿真)
stm32·单片机·嵌入式硬件·开源·毕业设计·proteus
Riwuarua4 小时前
从近似0基础开始FPGA开发 -- part.10 verilog-ethernet开源UDP协议栈工程学习
fpga开发·udp·开源
冬奇Lab6 小时前
一天一个开源项目(第215篇):Langflow - 可视化拖拽构建 AI 应用的低代码平台
人工智能·开源·资讯
GitCode官方6 小时前
本周 G-Star 开源项目推荐
开源·g-star·atomgit
ChampaignWolf6 小时前
YAAI 生态一周年:把 ABAP 变成 Agent 工具栈的开源组合拳
开源·abap·mcp·开源ai·yaai
MatrixOrigin7 小时前
Astra 正式开源了:面向长期复杂工作的企业级 Agent Runtime
开源·astra·矩阵起源·matrix origin·contextpipe
梦想的颜色8 小时前
【AI速览】2026 最新 开箱即用型开源成品 Agent :DeepSeek Harness 、Pi-Agent、 Opencode 横向 全面 对比
开源·agent·opencode·dsh·piagent
萧鼎9 小时前
safetensors 库的安装、核心语法与实战用法,安全保存模型权重
python·开源·教程·python库·safetensors