# Облегчённые модели диаризации на старом 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-пробелов. Инвариантность текста не нарушена. ## Воспроизведение Стенд [`diarization_calibration.py`](../../scripts/benchmarks/diarization_calibration.py) закрепляет корпус и матрицу задачи #25. Файл manifest, ASR-sidecar, интервалы и полный результат содержат приватные данные и хранятся отдельно от Git. Относительные пути в manifest считаются от каталога самого файла, поэтому приватный набор можно перенести на другую машину целиком. Готовый файл результата при этом не переносится: продолжение допустимо только на той же платформе, CPU и том же числе логических ядер. Перед дорогим запуском нужно проверить набор без декодирования и моделей: ```bash uv run python scripts/benchmarks/diarization_calibration.py \ --manifest /path/to/manifest.json \ --validate-only ``` Полный запуск и его продолжение используют одну команду и один файл результата: ```bash uv run python scripts/benchmarks/diarization_calibration.py \ --manifest /path/to/manifest.json \ --output /path/to/results.json \ --work-dir /path/to/work ``` Совместимый файл продолжится с первой незавершенной ячейки. Код возврата 0 означает, что завершены все автоматические ячейки и ячейки с известным числом говорящих. Число кластеров и инвариантность текста нужно сверить с условиями конкретного исследования. Полный контракт аргументов и режим подготовки ASR-sidecar описаны в `--help`. Результат включает исходный manifest, приватные пути и интервалы. Поэтому его нельзя добавлять в Git или передавать внешнему ревьюеру. ## Оборудование и условия - 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, следующий эксперимент должен заранее требовать известное число говорящих, включать повторные прогоны с контролем порядка и температуры и завершаться слуховой проверкой всех трёх записей. До этого конфигурацию и модель по умолчанию не менять.