Files
local-transcriber/docs/benchmarks/2026-08-14-diarization-calibration.md
T
Dmitry Dementiev 99ddf77af3 perf(diarization): добавлен замер на старом Intel
- Зачем:
  - требовалось оценить стоимость опциональной диаризации на доступном слабом Intel baseline.
- Что:
  - зафиксированы ASR, RTFx и peak RSS на трёх контрольных записях.
  - замер peak RSS адаптирован для Linux и macOS.
  - недоступный Core i5 явно заменён Core i7-6820HQ с сохранением ограничения применимости.
- Проверка:
  - uv run ruff check .scratch/diarization/common.py.
  - uv run pytest -q: 243 passed, 1 skipped.
2026-08-14 13:37:07 +03:00

15 KiB
Raw Blame History

Калибровка модели эмбеддингов и порога диаризации

Дата: 2026-08-14

Статус: выбор конфигурации для проектирования. Производительность отдельно проверена на доступном старом Intel baseline.

Решение

Для автоматического определения числа участников использовать:

  • эмбеддинги wespeaker_en_voxceleb_resnet34_LM.onnx;
  • FastClusteringConfig.threshold=0.89;
  • num_clusters=-1 по умолчанию.

Если число участников известно, передавать его через num_clusters: это устраняет остаточные кластеры и служит страховкой от особенностей записи. На трёх проверенных фрагментах явное число участников не ухудшило прокси-метрику качества WeSpeaker.

Двуязычная 3dspeaker_speech_campplus_sv_zh_en_16k-common_advanced.onnx быстрее и при известном числе участников лучше на одной из двух записей с таймкодами, но для автоматического режима не нашлось общего порога без лишних кластеров или склейки реальных голосов. Поэтому она не выбрана по умолчанию.

Что проверялось

Свип выполнялся на трёх русскоязычных рабочих созвонах с известным составом:

Запись Участников Короткий фрагмент Полный прогон кандидата SHA-256
2026-07-10 Data Test внутренний статус.mp4 3 07:0012:00 25:59,9 1057616B42E8ADD00E0EB975B02BDEF0EC9F6CDFEC6DBF488E0C60423C9B7B87
2026-07-29 T2 BDMA уточнение задачи от Ильи.mp4 2 00:0005:00 14:50,9 51866D247FE3EDA134CDD884F707B1F1DB8855B492E8BD14D2B56B62476255ED
2026-08-12 Созвон с Максом Мерлином по T2 Forecast и Yantar.mp4 2 00:0005:00 20:22,2 4422F04E2771091A0648E5422D14A31DD7CA2C8EEF7ED9F4A5C63F43D8CA6400

Для первой записи число участников взято из согласованного MoM и не зависит от диаризации. Для двух остальных рядом с медиа лежат транскрипты Hypescribe с таймкодами и метками спикеров. Они получены другим инструментом и использованы как независимая грубая опорная разметка.

Hypescribe ставит метку только в начале реплики и не размечает точные границы, тишину и наложения голосов. Поэтому ниже считается не DER, а mapped speaker purity: лучший взаимно-однозначный маппинг кластеров на опорные метки по суммарному перекрытию. Метрика подходит для сравнения конфигураций на одной записи, но не является абсолютной оценкой диаризации.

Кластер считается содержательным, если в нём не меньше max(5 с, 2% длины записи) речи. Это только диагностический показатель: готовый CLI не должен молча отбрасывать малые кластеры без отдельного решения.

Модели

Во всех прогонах использовалась одна сегментация sherpa-onnx-pyannote-segmentation-3-0.

Роль Модель Языки обучения Размер SHA-256
выбранная wespeaker_en_voxceleb_resnet34_LM.onnx английский, VoxCeleb2 26 530 550 E9848563DA86F263117134DFD7AD63C92355B37DE492B55E325400C9D9C39012
многоязычная альтернатива 3dspeaker_speech_campplus_sv_zh_en_16k-common_advanced.onnx китайский + английский 28 281 164 AA3CFC16963A10586A9393F5035D6D6B57E98D358B347F80C2A30BF4F00CEBA2
дополнительная разведка 3dspeaker_speech_eres2net_base_sv_zh-cn_3dspeaker_16k.onnx китайский 39 593 761 1A331345F04805BADBB495C775A6DDFFCDD1A732567D5EC8B3D5749E3C7A5E4B
сегментация model.onnx из sherpa-onnx-pyannote-segmentation-3-0 5 992 913 220AD67CA923BEF2FA91F2390C786097BF305BCEB5E261D4AF67B38E938E1079

WeSpeaker сам помечает VoxCeleb-модель как английскую и распространяет её под CC BY 4.0. Репозиторий 3D-Speaker и модель CAMPPlus на ModelScope используют Apache 2.0; в исходниках 3D-Speaker модель явно описана как обученная на большом китайско-английском корпусе. ONNX-файлы брались из официального релиза k2-fsa/sherpa-onnx, а не из сторонних зеркал.

Источники:

Свип WeSpeaker

Порог сначала проверялся крупным шагом, затем уточнялся около переходов между числом кластеров. В ячейках — общее число кластеров; жирным выделено точное совпадение с известным числом участников.

Порог Data Test, 3 T2 BDMA, 2 Yantar, 2
0,85 3 2 3
0,87 3 2 3
0,88 3 2 3
0,89 3 2 2
0,90 2 2 2
0,95 2 2 1
явное num_clusters 3 2 2

0,89 — единственное проверенное значение, которое без знания числа участников дало правильное количество кластеров на всех трёх фрагментах. На двух записях с опорными метками purity составила 0,767 и 0,787. Явное число участников дало те же значения.

Сравнение с 3D-Speaker

CAMPPlus, китайский + английский

Порог Data Test, 3 T2 BDMA, 2 Yantar, 2
0,85 7 7 7
0,90 6 5 5
0,95 5 5 5
0,99 4 4 4
1,00 4 4 4
1,05 3 3 3
1,10 2 2 3
явное num_clusters 3 2 2

При 1,05 на двух записях остаётся по одному малому остаточному кластеру, а при 1,10 трёхсторонняя встреча уже склеивается до двух голосов. Общего автоматического порога нет.

При явном числе участников purity равна 0,801 на T2 BDMA и 0,911 на Yantar. Это лучше WeSpeaker на 0,034 и 0,124 соответственно. Однако на контрольной трёхсторонней записи один из трёх принудительных кластеров оказался меньше порога содержательности, поэтому улучшение по двум текстовым прокси нельзя обобщать на все записи.

ERes2Net base, китайский

Эта модель проверялась дополнительно, но не считается выполнением требования о многоязычной альтернативе. Даже на пороге 0,99 она дала 5 / 4 / 7 кластеров вместо 3 / 2 / 2. При явном числе участников purity составила 0,688 и 0,907: результат неоднородный и автоматический режим заметно хуже выбранного.

Полные прогоны выбранного кандидата

После свипа WeSpeaker + 0,89 прогнан на всех трёх записях целиком.

Запись Кластеры Содержательные Речь по кластерам, с Остаток сверх ожидаемых Purity Время RTF
Data Test 4 3 573,1 / 487,4 / 342,2 / 19,1 1,3% 189,0 с 0,121
T2 BDMA 2 2 748,7 / 52,3 0% 0,749 112,3 с 0,126
Yantar 2 2 733,2 / 259,8 0% 0,906 151,4 с 0,124

На полной контрольной записи остаётся ложный кластер на 19,1 с, но три содержательных кластера совпадают с известным составом. Повторный полный прогон на 0,9 дал тот же результат: JSON-массивы всех 340 интервалов на 0,89 и 0,9 совпали в точности, включая границы и номера кластеров. Поэтому к кандидату 0,89 непосредственно применима слуховая проверка отрезка 07:00–12:00, выполненная для результата из разведочного замера: три основных голоса стабильны, остаточный кластер ложный, есть небольшие пропуски второго голоса, а наложения голосов определяются не полностью. Новая калибровка не устраняет эти ограничения сегментации.

На двух полных разговорах purity отличается от короткого фрагмента: 0,749 против 0,767 и 0,906 против 0,787. Это подтверждает, что короткий свип годится для отсева конфигураций, а финальный кандидат надо проверять целиком.

Производительность

Условия: AMD Ryzen 7 8845H, Windows 11 build 26200, Python 3.13.13, sherpa-onnx 1.13.5, onnxruntime 1.28.0, NumPy 2.4.3, 8 потоков CPU. Загрузка моделей и декодирование медиа не входят в измерение.

Средний RTF на коротких фрагментах:

Модель RTF Относительно WeSpeaker
WeSpeaker ResNet34 LM 0,118 1,00×
CAMPPlus zh/en 0,083 0,70×
ERes2Net base zh 0,152 1,29×

CAMPPlus примерно на 30% быстрее WeSpeaker в этом эксперименте. Это плюс для варианта с известным числом участников. Производительность выбранной WeSpeaker отдельно проверена на доступном старом Intel Core i7.

Воспроизводимость

Свип выполняется скриптом scripts/benchmarks/diarization_calibration.py. Он принимает JSON-манифест с путями к моделям и записям, декодирует указанные фрагменты через ffmpeg, последовательно сохраняет каждый результат и может возобновить прерванный прогон.

Пример:

uv run python scripts/benchmarks/diarization_calibration.py `
  --manifest diarization-calibration.json `
  --output diarization-calibration-results.json `
  --work-dir .scratch/diarization-calibration `
  --threads 8

Сырые JSON содержат локальные пути к конфиденциальным рабочим записям и сами интервалы диаризации, поэтому в репозиторий не добавляются. Для проверки артефактов выше приведены SHA-256 медиа и моделей.

Ограничения и следующий шаг

  • Три записи принадлежат одному типу русскоязычных рабочих созвонов; это не репрезентативная выборка для всех микрофонов, шумов и акцентов.
  • Опорные метки двух записей грубые и не дают посчитать DER.
  • На слух проверен только фрагмент 07:00–12:00 контрольной записи; перед выпуском нужен слуховой контроль плотного диалога на финальной сборке.
  • Калибровка выбирает эмбеддинги и кластеризацию, но не решает ошибки границ и неполное распознавание наложений голосов.
  • Производительность принята на доступном старом Intel Core i7; конкретный Core i5 11-го поколения остаётся непроверенным, потому что такого устройства нет.

Для спецификации зафиксировать WeSpeaker + 0,89 как автоматический дефолт, отдельную опцию явного числа участников и отсутствие автоматического отбрасывания малых кластеров. CAMPPlus zh/en можно оставить кандидатом для будущего режима с обязательным num_clusters после расширенной слуховой проверки.