From 6cbc7da2631451b47e5dca288903be68c8d1453b Mon Sep 17 00:00:00 2001 From: zhifu gao Date: Sat, 5 Sep 2026 05:15:54 +0000 Subject: [PATCH] docs: add reproducible SER benchmark contract Signed-off-by: zhifu gao --- README.md | 2 + README_zh.md | 2 + benchmarks/ser/README.md | 36 +++++++++++ benchmarks/ser/evaluate.py | 121 ++++++++++++++++++++++++++++++++++++ tests/test_ser_benchmark.py | 61 ++++++++++++++++++ 5 files changed, 222 insertions(+) create mode 100644 benchmarks/ser/README.md create mode 100644 benchmarks/ser/evaluate.py create mode 100644 tests/test_ser_benchmark.py diff --git a/README.md b/README.md index 502aca3..fea358f 100644 --- a/README.md +++ b/README.md @@ -70,6 +70,8 @@ We compared the performance of multilingual speech recognition between SenseVoic Due to the current lack of widely-used benchmarks and methods for speech emotion recognition, we conducted evaluations across various metrics on multiple test sets and performed a comprehensive comparison with numerous results from recent benchmarks. The selected test sets encompass data in both Chinese and English, and include multiple styles such as performances, films, and natural conversations. Without finetuning on the target data, SenseVoice was able to achieve and exceed the performance of the current best speech emotion recognition models. +For a reproducible zero-shot CASIA or RAVDESS rerun, use the [SER evaluation contract](./benchmarks/ser/README.md). It reads the raw SenseVoice emotion tag and reports both UA and WA instead of deriving labels from formatted transcription text. +
diff --git a/README_zh.md b/README_zh.md index a5d00e2..dab20c9 100644 --- a/README_zh.md +++ b/README_zh.md @@ -71,6 +71,8 @@ SenseVoice 是具有音频理解能力的音频基础模型,包括语音识别 由于目前缺乏被广泛使用的情感识别测试指标和方法,我们在多个测试集的多种指标进行测试,并与近年来 Benchmark 上的多个结果进行了全面的对比。所选取的测试集同时包含中文 / 英文两种语言以及表演、影视剧、自然对话等多种风格的数据,在不进行目标数据微调的前提下,SenseVoice 能够在测试数据上达到和超过目前最佳情感识别模型的效果。 +需要复现零训练的 CASIA 或 RAVDESS 结果时,请使用 [SER 评测契约](./benchmarks/ser/README.md)。该脚本直接读取 SenseVoice 原始情感标签,同时输出 UA 和 WA;不要从富文本转写结果中用字符串切分推断情感标签。 +
diff --git a/benchmarks/ser/README.md b/benchmarks/ser/README.md new file mode 100644 index 0000000..d9b4a95 --- /dev/null +++ b/benchmarks/ser/README.md @@ -0,0 +1,36 @@ +# Reproducing SenseVoice SER Measurements + +The SER table in the project README reports zero-shot results. It is not a +promise that every dataset mirror, parser, or aggregate metric produces the +same number. In particular, the CASIA SenseVoiceSmall row is **70.0 UA / 70.0 +WA** for the six-label benchmark protocol shown in the table. + +Use `evaluate.py` to make a local evaluation reproducible. It accepts a JSONL +manifest; every non-empty line must contain an audio path or URL and one of the +following labels: + +```json +{"audio": "/data/CASIA/angry/example.wav", "label": "angry"} +``` + +The accepted canonical labels are `angry`, `fearful`, `happy`, `neutral`, +`sad`, and `surprised`. Dataset spellings `fear` and `surprise` are normalized +to `fearful` and `surprised`. + +```bash +python benchmarks/ser/evaluate.py casia.jsonl \ + --model iic/SenseVoiceSmall --device cuda:0 --output casia-results.json +``` + +The evaluator reads the raw `<|EMOTION|>` tag returned by SenseVoice before +calling rich-text post-processing. Do not infer the label by splitting the +formatted transcription: tags and display text have different contracts. + +`wa` is accuracy over all records. `ua` is the mean recall over labels present +in the manifest. The JSON result includes per-label recall and a confusion map; +unknown labels, missing emotion tags, and malformed manifest records fail the +run instead of being skipped. + +CASIA and RAVDESS distributions are controlled by their respective providers. +Keep the dataset version, manifest, model revision, package versions, and this +JSON result together when comparing a rerun with the README table. diff --git a/benchmarks/ser/evaluate.py b/benchmarks/ser/evaluate.py new file mode 100644 index 0000000..cc29b98 --- /dev/null +++ b/benchmarks/ser/evaluate.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python3 +"""Evaluate zero-shot SenseVoice emotion predictions from a JSONL manifest.""" + +import argparse +import json +import re +from collections import Counter, defaultdict +from pathlib import Path + + +CANONICAL_LABELS = ( + "angry", + "fearful", + "happy", + "neutral", + "sad", + "surprised", +) +LABEL_ALIASES = { + "angry": "angry", + "fear": "fearful", + "fearful": "fearful", + "happy": "happy", + "neutral": "neutral", + "sad": "sad", + "surprise": "surprised", + "surprised": "surprised", +} +EMOTION_TAG = re.compile(r"<\|(?P