test(diarization): добавлен стенд сравнения CPU-моделей

- Зачем:
  - требовалось сравнить облегченные модели диаризации на старом CPU без изменения рабочей конфигурации.
- Что:
  - добавлен воспроизводимый и возобновляемый прогон матрицы Pyannote FP32/INT8 с WeSpeaker и TitaNet.
  - зафиксированы измерения 108 ячеек, ограничения эксперимента и решение сохранить модель по умолчанию.
  - локальные записи в каталоге tmp исключены из индекса Git.
- Проверка:
  - .venv/bin/python -m pytest.
  - /tmp/local-transcriber-ruff-bin/ruff check scripts/benchmarks/diarization_calibration.py tests/test_diarization_calibration.py.
This commit is contained in:
Dmitry Dementiev committed 2026-08-30 12:02:34 +03:00
1 parent 95f295c37c
commit 1e14f2687a
8 files changed
+2704 -234

No files matched your search

@@ -0,0 +1,188 @@
# Облегчённые модели диаризации на старом Intel Core i7
**Дата:** 2026-08-30
**Статус:** сравнительный CPU-тест. Конфигурация по умолчанию не менялась.
## Решение
Сохранить модель по умолчанию: Pyannote Segmentation 3.0 FP32, WeSpeaker
ResNet34 LM, общий порог автоматической кластеризации `0,89`. Новый прогон
подтвердил для этой связки точное число голосовых кластеров `3 / 2 / 2` на всех
трёх контрольных фрагментах.
Pyannote INT8 с WeSpeaker не заменяет FP32. Среднее ускорение составило только
2,1%, средний пиковый RSS по ячейкам снизился примерно на 4 МиБ, а средняя
чистота сопоставленных говорящих и число слов без говорящего стали хуже.
TitaNet small в среднем быстрее WeSpeaker на 24,3%, но требует примерно на
147–149 МиБ больше RSS и не находит правильное число кластеров ни в одной
проверенной точке общего автоматического порога. Его можно рассматривать только
как кандидата для режима с явно известным числом говорящих. Следующий эксперимент
должен завершиться отдельной слуховой проверкой. По этому тесту менять код,
модели или пороги нельзя.
## Границы вывода
Проверялись только четыре CPU-сочетания Pyannote FP32/INT8 ×
WeSpeaker/TitaNet на трёх пятиминутных русскоязычных рабочих созвонах из
[исходной калибровки](2026-08-14-diarization-calibration.md). Число говорящих в
них известно как `3 / 2 / 2`. Это сравнительный прогон моделей диаризации, а не
новая приёмка готовых транскриптов.
В частности:
- новой слуховой проверки не было;
- полные записи не прогонялись;
- у каждой ячейки один запуск, без повторов и случайного перемешивания порядка;
- влияние порядка, прогрева и температуры отдельно не измерено;
- ASR выполнен один раз на запись и не входит во время ячеек диаризации;
- параллельные ASR и диаризация, GPU, NPU и другие CPU не проверялись.
Происхождение, лицензии и закреплённые SHA-256 моделей описаны в
[исследовательской записке](../research/2026-08-29-lightweight-diarization-models.md),
а смысл `mapped speaker purity` и ограничения опорной разметки — в
[исходной калибровке](2026-08-14-diarization-calibration.md). Здесь эти сведения
не дублируются.
## Методика
Каждая измеряемая ячейка запускалась в новом дочернем процессе. До измеряемого
интервала загружались WAV, модели и сэмплы; полное время, CPU и пиковый RSS
считались вокруг одного вызова `diarizer.process(samples)`. Отладочный журнал
`sherpa-onnx` 1.13.5 дал время сегментации, извлечения эмбеддингов, кластеризации
и всего вызова.
Декодирование, загрузка моделей, сериализация и ASR во время не входят.
Автоматический перебор прямоугольный: каждый порог сочетания проверен на всех
трёх записях с `num_clusters=-1`. Для сочетания выбирался один общий порог.
Условие приёмки считалось выполненным только при полном совпадении общего числа
кластеров с
`3 / 2 / 2`; число содержательных кластеров оставалось диагностикой и не могло
оправдать лишний кластер. После выбора порога каждое сочетание ещё раз прошло
три записи с известным числом кластеров.
Итого сохранено 108 успешных ячеек без ошибок:
- 96 с автоматическим числом кластеров: по 18 для каждого сочетания с
WeSpeaker и по 30 для каждого сочетания с TitaNet;
- 12 с известным числом кластеров: по три для каждого из четырёх сочетаний.
Отдельно сохранены четыре результата выбора общего порога. Они описывают
агрегацию автоматических ячеек и в число 108 не входят.
Во всех 108 ячейках совпала последовательность 1853 распознанных слов после
удаления Unicode-пробелов. Инвариантность текста не нарушена.
## Оборудование и условия
- Intel Core i7-6820HQ, 4 ядра / 8 логических процессоров;
- Linux 7.0.0-30-generic x86_64;
- питание от сети, системный профиль `balanced`;
- Python 3.13.13, `sherpa-onnx` 1.13.5, `onnxruntime` 1.28.0,
NumPy 2.4.3;
- CPU provider и 8 потоков для segmentation и embedding;
- mono PCM16, 16 кГц, длительность каждого фрагмента 300 секунд.
Это тот же ноутбук, что в [предыдущей Intel-приёмке](2026-08-14-diarization-intel-i7.md),
но условия нельзя считать побайтовым повтором: там отдельно зафиксированы
governor `powersave` и урезанная доступная мощность, а версия ядра была
7.0.0-29. Во время нового перебора ночная пауза произошла до сохранения текущей
ячейки. Продолжение началось после возврата профиля `balanced`; ячеек,
измеренных в энергосберегающем профиле, в итоговом результате нет.
## Производительность полного автоматического перебора
Числа ниже — средние по всем автоматическим ячейкам сочетания. Это не повторы
одной ячейки. «Средний пиковый RSS» — среднее пикового RSS каждой ячейки;
соседний столбец показывает наибольший такой максимум во всём переборе.
| Сегментация + эмбеддинги | Ячеек | Время, с | RTF | CPU, ядер | Средний пиковый RSS, МиБ | Максимальный пиковый RSS, МиБ | Сегментация, с | Эмбеддинги, с |
|---|---:|---:|---:|---:|---:|---:|---:|---:|
| FP32 + WeSpeaker | 18 | 72,486 | 0,24162 | 6,84 | 254,55 | 265,61 | 15,295 | 56,837 |
| INT8 + WeSpeaker | 18 | 70,969 | 0,23656 | 6,94 | 250,40 | 263,00 | 17,094 | 53,524 |
| FP32 + TitaNet | 30 | 52,797 | 0,17599 | 6,80 | 401,80 | 428,11 | 14,724 | 37,723 |
| INT8 + TitaNet | 30 | 55,792 | 0,18597 | 6,70 | 399,10 | 419,71 | 17,125 | 38,278 |
INT8 ускорил сочетание с WeSpeaker на 2,1%, но сегментация стала медленнее, а
выигрыш возник на извлечении эмбеддингов. Такой результат не даёт практического
основания заменять FP32. У TitaNet FP32 оказался быстрее INT8. Относительно
соответствующей связки WeSpeaker ускорение TitaNet составило 27,2% для FP32 и
21,4% для INT8.
Среднее для двух вариантов точности — 24,3%.
Опубликованное ожидание ускорения от INT8 локально не подтвердилось. Вместо
18,9% с 3D-Speaker получено 2,1% с WeSpeaker, а с TitaNet INT8 оказался на 5,7%
медленнее FP32. Условия исходного примера и границы такого сравнения разобраны
в [исследовательской записке](../research/2026-08-29-lightweight-diarization-models.md).
За скорость TitaNet платит памятью: средний пиковый RSS выше WeSpeaker на 147,25
МиБ с FP32 и на 148,70 МиБ с INT8. Поэтому на слабом CPU его нельзя считать
безусловно облегчённым вариантом.
## Автоматический порог и диагностика качества
`Mapped speaker purity` усреднена только по T2 BDMA и Yantar, для которых есть
грубая опорная разметка. Это сравнительная прокси-метрика, не DER и не точность
по выверенной разметке.
| Сочетание | Выбранный порог | Приёмка `3 / 2 / 2` | Кластеры | Средняя purity | Слов без говорящего, из 1853 | Максимальный остаток сверх ожидаемых |
|---|---:|:---:|---|---:|---:|---:|
| FP32 + WeSpeaker | 0,85 | да | 3 / 2 / 2 | 0,82950 | 71 | 0% |
| INT8 + WeSpeaker | 0,85 | да | 3 / 2 / 2 | 0,81028 | 104 | 0% |
| FP32 + TitaNet | 1,10 | **нет** | 5 / 3 / 3 | 0,82287 | 76 | 3,89% |
| INT8 + TitaNet | 1,10 | **нет** | 3 / 2 / 3 | 0,79315 | 109 | 12,12% |
У FP32 + WeSpeaker условие приёмки проходит на плато `0,85–0,89`, у INT8 +
WeSpeaker — на `0,85–0,90`. Автоматический выбор дал `0,85` по общей
лексикографической оценке, но это не аргумент менять рабочий порог `0,89`:
новый перебор не содержит повторов или слуховой проверки, тогда как действующее
решение опирается также на предыдущую калибровку полных записей и слуховую
проверку плотного диалога.
TitaNet не прошёл условие приёмки ни в одной точке проверенной сетки `0,50–1,10`.
Порог `1,10` — лишь наименее плохая точка перебора; допустимой автоматической
конфигурацией она не является. Содержательные `3 / 2 / 3` кластера у FP32 TitaNet не отменяют
лишние голосовые кластеры: диагностический фильтр не заменяет условие приёмки.
«Максимальный остаток сверх ожидаемых» — наибольшая по трём записям доля слов,
которые попали в кластеры сверх известного числа говорящих. Метрика описывает
объём лишних кластеров, а не их количество: один крупный лишний кластер может
дать больший процент, чем несколько малых.
## Режим с известным числом говорящих
Ячейки с известным числом говорящих использовали тот же выбранный порог и
меняли только `num_clusters` на известные `3 / 2 / 2`. Все четыре сочетания
вернули точное число кластеров на всех трёх записях.
| Сочетание | Точное число кластеров | Точное число содержательных кластеров | Средняя purity |
|---|---:|---:|---:|
| FP32 + WeSpeaker | 3 / 3 записей | 3 / 3 записей | 0,82950 |
| INT8 + WeSpeaker | 3 / 3 записей | 3 / 3 записей | 0,81028 |
| FP32 + TitaNet | 3 / 3 записей | 2 / 3 записей | 0,83057 |
| INT8 + TitaNet | 3 / 3 записей | 3 / 3 записей | 0,79721 |
Близкая средняя purity FP32 TitaNet и FP32 WeSpeaker не доказывает равноценное
качество. У FP32 TitaNet на Data Test один из трёх принудительных кластеров не
достиг диагностического порога содержательности, а новой слуховой проверки не
было. Поэтому TitaNet остаётся только направлением будущего эксперимента с
обязательным известным числом говорящих.
## Ограничения и следующий шаг
- Три записи относятся к одному типу рабочих созвонов; результат не переносится
автоматически на другие языки, микрофоны и акустические условия.
- Две опорные разметки имеют секундную точность и не позволяют считать DER.
- Средние значения полного времени и RSS объединяют разные записи и пороги.
Без повторов они не оценивают дисперсию и не отделяют порядок, прогрев или
влияние температуры.
- Новый прогон не заменяет прежнюю слуховую проверку и не даёт слуховых данных
для TitaNet или INT8.
- Результат относится к последовательной CPU-диаризации на одном Core
i7-6820HQ и не предсказывает конкретный Core i5 11-го поколения.
Если возвращаться к TitaNet, следующий эксперимент должен заранее требовать
известное число говорящих, включать повторные прогоны с контролем порядка и
температуры и завершаться слуховой проверкой всех трёх записей. До этого
конфигурацию и модель по умолчанию не менять.