Files
local-transcriber/docs/benchmarks/2026-08-30-lightweight-diarization-cpu.md
T
Dmitry Dementiev 1e14f2687a 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.
2026-08-30 12:02:34 +03:00

189 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Облегчённые модели диаризации на старом 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, следующий эксперимент должен заранее требовать
известное число говорящих, включать повторные прогоны с контролем порядка и
температуры и завершаться слуховой проверкой всех трёх записей. До этого
конфигурацию и модель по умолчанию не менять.