- Зачем: - требовалось оценить стоимость опциональной диаризации на доступном слабом 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.
15 KiB
Калибровка модели эмбеддингов и порога диаризации
Дата: 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:00–12:00 | 25:59,9 | 1057616B42E8ADD00E0EB975B02BDEF0EC9F6CDFEC6DBF488E0C60423C9B7B87 |
2026-07-29 T2 BDMA уточнение задачи от Ильи.mp4 |
2 | 00:00–05:00 | 14:50,9 | 51866D247FE3EDA134CDD884F707B1F1DB8855B492E8BD14D2B56B62476255ED |
2026-08-12 Созвон с Максом Мерлином по T2 Forecast и Yantar.mp4 |
2 | 00:00–05: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;
- карточка
wespeaker-voxceleb-resnet34-LM; - исходники и лицензия 3D-Speaker;
- официальный релиз ONNX-моделей 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 после расширенной слуховой
проверки.