EmbeddingGemma2-Bashkir-CV25

Башкирская модель распознавания речи на основе аудиоэнкодера Google EmbeddingGemma 2 и CTC. Сначала обучена на синтетическом AigizK/bashkort_voice, затем дообучена на Common Voice 25 Train, с выбором чекпойнта по Dev. На полном Test: WER 9,63%, CER 2,41%. Ниже приведены архитектура, история обучения, результаты и воспроизводимый замер скорости на RTX 5090.

English: Bashkir offline speech recognition using the EmbeddingGemma 2 audio tower and a bidirectional Transformer CTC reader. Synthetic-data training followed by Common Voice 25 adaptation; full CV25 Test WER 9.63%, CER 2.41%. Complete safetensors weights, a standalone Python loader and batched inference are included.

Использование

Проверено: Python 3.12, PyTorch 2.8.0+cu128, Transformers 5.19.0, RTX 5090. Установите подходящую CUDA-сборку PyTorch; для CPU подходит обычная сборка.

pip install -r requirements.txt
import sys
from huggingface_hub import snapshot_download

directory = snapshot_download("AigizK/EmbeddingGemma2-Bashkir-CV25")
sys.path.insert(0, directory)
from bashkir_gemma import BashkirGemma

asr = BashkirGemma.from_pretrained(directory, device="cuda")
print(asr.transcribe("audio.wav"))

# Файлы автоматически группируются по длительности; порядок ответов сохраняется.
texts = asr.transcribe(["first.wav", "second.mp3"], batch_size=32)
print(texts)

# Массив mono float32 с явно указанной частотой:
# text = asr.transcribe(waveform, sample_rate=16000)
# CPU: BashkirGemma.from_pretrained(directory, device="cpu")

Скрипт из скачанного репозитория:

python transcribe.py --model . --device cuda --batch-size 32 first.wav second.mp3

Используйте приложенный загрузчик bashkir_gemma.py. Репозиторий содержит собственную CTC-архитектуру и не зарегистрирован как стандартная модель для transformers.pipeline. Все веса аудиоэнкодера и reader находятся в model.safetensors; после скачивания репозитория инференс работает без обращения к исходному чекпойнту Google. GPU использует BF16 autocast с FP32 весами; CPU — FP32. FP16 и ONNX для этого релиза не проверялись.

Входные файлы декодируются через soundfile, stereo усредняется в mono, частота пересчитывается в 16 кГц через soxr. Принимаются WAV/FLAC/MP3 и другие форматы, доступные в установленном libsndfile. Длинные записи разбиваются на фрагменты до 30 секунд по минимуму энергии около границы. Это простой способ обработки файлов: возможны ошибки на стыках; нет diarization, timestamps и потокового интерфейса. Reader двунаправленный.

Исходный код и связь с Gemma

Основа эксперимента — qnguyen3/gemma-asr, зафиксированный commit 343c86faab52fdd09c312945ad21b8f8f15e76ee. Идея эксперимента была взята из публикации @stablequan. Обучение запускалось на локальной адаптации этого кода для башкирского языка.

Предобученная модель — google/embeddinggemma-2, revision 914f7f89142e33e77833254d9c9b90c3cef7303b. Это мультимодальная embedding-модель Google DeepMind с модульным аудиоэнкодером семейства Gemma 4. В данном ASR используется ее аудиобашня и строки токеновых эмбеддингов для инициализации CTC-head. Полные текстовая и визуальная части при распознавании не нужны.

Из Gemma сделали ASR с CTC, добавив обучаемый reader, который преобразует последовательность аудиопризнаков в покадровые вероятности токенов. CTC loss обучает сопоставление аудио и текста без ручной разметки временных границ. При распознавании выбирается наиболее вероятный токен на каждом кадре, повторы схлопываются, blank удаляется. Внешняя языковая модель и beam search не используются.

mono 16 kHz
  → GPU log-mel, 128 bins
  → Gemma 4 audio encoder: 12 conformer layers, hidden 1024, ~25 frames/s
  → learned softmax mixture of 13 hidden states
  → LayerNorm + projection 1024→768 + depthwise convolution, kernel 15
  → 6 bidirectional Transformer reader blocks, width 768, 8 heads, FFN 3072
  → LayerNorm + projection 768→512
  → dot-product CTC head: 7576 units
  → greedy CTC decoding → Bashkir text

CTC-словарь: 7576 units = blank (0) + unk (1) + 7574 токена Gemma, встретившихся в синтетическом Train. Это подмножество исходного tokenizer, а не алфавит из отдельных букв. Строки head инициализированы нормализованными токеновыми эмбеддингами Gemma, затем обучались. Порядок units не менялся при дообучении на CV25.

Всего 352 435 141 параметр: аудиоэнкодер 304 824 608, reader с head 47 610 533. В обоих этапах обучались reader/head и верхние два слоя аудиоэнкодера — всего 97 971 109 параметров. Нижние десять слоев заморожены. Dropout аудиоэнкодера отключен при обучении; dropout reader — 0,1.

Основные изменения относительно исходного проекта: нормализация с сохранением башкирских букв, подготовка и проверка Bashkir-датасета, детерминированное разделение по нормализованному тексту, Bashkir CTC vocabulary, reader шириной 768, обучение двух верхних слоев энкодера, накопление градиентов, отдельный этап CV25 с новым optimizer/scheduler и неизменным словарем, полная валидация Dev, оценка всех исходных строк Test, проверка сохранности исходного чекпойнта и переносимый экспорт полных весов. Приложенный bashkir_gemma.py — отдельная реализация инференса с проверенным соответствием обученной архитектуре.

Данные

Этап 1: синтетическая башкирская речь

AigizK/bashkort_voice: синтетическая речь OmniVoice с башкирскими текстами, лицензия датасета CC BY 4.0. После подготовки:

Split Записей Часов
Train 903 111 1706,17
Valid 9 366 17,77
Test 9 382 17,86

Из 928 519 входных записей исключены 6660 с длительностью вне 0,5–30 секунд. Разделение примерно 98/1/1 основано на SHA256 нормализованного текста: одинаковый нормализованный текст не попадает в разные split. Это не гарантирует разделение по дикторам. Синтетический Test не является оценкой качества на живой речи.

Нормализация: Unicode NFC, нижний регистр, знаки пунктуации и дефисы заменяются пробелами, пробелы схлопываются. Башкирские ә ө ү ғ ҡ ң ҙ ҫ һ сохраняются. Для синтетических обучающих targets предусмотрено исключение строк с цифрами вместо автоматического озвучивания чисел.

Этап 2: Common Voice Scripted Speech 25.0, Bashkir

Использованы исходные train.tsv, dev.tsv, test.tsv Common Voice 25.0 Bashkir, без фильтров, ранее применявшихся в эксперименте GigaAM:

Split Записей Часов Роль
Train 119 133 143,12 Дообучение
Dev 14 527 19,47 Валидация и выбор чекпойнта
Test 14 572 19,89 Итоговая оценка

Для обучения/валидации аудио Train/Dev преобразовано в mono 16 кГц FLAC PCM16. Итоговый Test прочитан из исходных MP3, с пересчетом частоты в 16 кГц. Все строки каждого split сохранены. CV25-аудио и транскрипты не включены в этот репозиторий.

Как обучали

Оба этапа выполнены на одной NVIDIA GeForce RTX 5090 32 GB под tmux, PyTorch 2.8.0+cu128, Transformers 5.19.0, BF16 autocast. AdamW: betas=(0,9; 0,98), eps=1e-8, weight decay=0,01, gradient clipping=1. SpecAugment: две частотные маски шириной до 27 и десять временных масок шириной до 4% длительности. Размер microbatch ограничивался суммой паддированной длительности: max_duration × batch_size ≤ 240 секунд; число записей менялось с длительностью.

Настройка Синтетический этап CV25 дообучение
Optimizer steps 30 000 12 000
Reader/head learning rate 3e-4 1e-4
Верхние 2 слоя encoder LR 1e-5 1e-5
Warmup steps 1000 500
Scheduler cosine, min LR = 5% cosine, min LR = 5%
Microbatch budget 240 padded audio seconds 240 padded audio seconds
Gradient accumulation 4 2
DataLoader workers 8 8
Валидация каждые 500 steps 500 steps
Размер валидации фиксированные 1500 Valid полный Dev, 14 527
Лучший checkpoint 29 500 11 500

CV25 этап начат с лучшего синтетического чекпойнта: перенесены все обученные веса, включая верхние слои энкодера. Optimizer и scheduler созданы заново, счетчик шага сброшен. Предусмотрен early stopping с patience=8 проверок; он не сработал, выполнены все 12 000 шагов. Публикуется best step 11 500, выбранный по минимальному Dev WER, а не последний checkpoint. Исходный синтетический checkpoint сохранен отдельно; SHA256 проверен после завершения.

Test не использовался для градиентов или выбора чекпойнта. До дообучения уже была выполнена базовая оценка исходной модели на CV25 Train/Dev/Test; после дообучения Test оценен для выбранного по Dev checkpoint. Дополнительно Test используется для фиксированного performance benchmark, не для подбора весов.

Качество

WER/CER ниже приведены в процентах, на полных split, кроме явно обозначенной синтетической валидации. Нормализация refs и hyps одинакова: NFC, lowercase, пунктуация → пробелы, схлопывание пробелов; буквы, цифры и Latin сохраняются. WER считается по словам, CER — по символам нормализованного текста, с помощью jiwer 4.0.0.

Данные До CV25 дообучения: WER / CER После CV25 дообучения: WER / CER
Synthetic Valid, фиксированные 1500 5,38 / 2,29 не оценивалось
Synthetic Test, 9382 5,44 / 2,25 не оценивалось
CV25 Train, 119133 13,09 / 3,27 не оценивалось
CV25 Dev, 14527 16,00 / 4,32 9,96 / 2,56
CV25 Test, 14572 15,56 / 4,14 9,63 / 2,41

На CV25 Test WER снизился 15,56% → 9,63%, относительное уменьшение ошибки 38,11%. Итоговый Test: 89533 reference words, 6926 substitutions, 1072 deletions, 622 insertions; 13768 character errors на 570817 reference characters.

В начале CV25-цикла baseline на подготовленном Dev составил 15,909% WER, лучший — 9,957% на шаге 11500, последний — 9,969% на шаге 12000. Отличие baseline от 16,003% в исходной оценке связано с отдельным путем подготовки аудио и batching/численной точностью; это два разных запуска, приведены оба значения. Результаты после CV25 на синтетическом Test повторно не измерялись: сохранение качества на этом домене не утверждается.

WER during both training stages

Кривые имеют разные validation sets и масштабы шагов; значения между панелями не следует напрямую сравнивать. Все точки находятся в validation_history.json.

Скорость и batch inference

Повторный замер выполнен на публикуемых финальных весах на RTX 5090. Выбраны 256 равномерно распределенных по индексам записей CV25 Test, затем отсортированы по длительности. На каждый batch size: warmup, три повтора, CUDA synchronization. Время включает перенос waveform CPU→GPU, GPU log-mel, forward, greedy CTC и декодирование токенов. Не включает загрузку модели, чтение/ресемплинг файлов, CPU padding и warmup. × real time = длительность аудио / время обработки; это throughput, а не обещание задержки потокового распознавания.

Batch × real time Clips/s Batch p50 / p95, ms Peak GPU allocated, GB
1 122× 24.5 39.9 / 44.3 1.48
8 912× 183.6 42.6 / 46.5 1.90
32 2846× 572.8 49.4 / 93.2 3.35
64 2789× 561.3 95.3 / 198.8 5.28
128 2108× 424.2 300.5 / 437.2 9.13

Для коротких файлов этого benchmark batch 32 дает лучший либо близкий к лучшему throughput; batch 128 не обязательно быстрее из-за padding. API поддерживает batch_size и batch_seconds (по умолчанию 32 и 600 padded audio seconds). Для своего распределения длительностей подберите размер на реальных данных. Память в таблице — torch.cuda.max_memory_allocated, а не полный объем процесса по nvidia-smi.

При повторной проверке полного Test через подготовку с CPU-prefetch: 14572 файлов, 19.89 часа аудио за 26.58 секунды (2693× real time), из них 22.12 секунды суммарного inference (3236×). Batch cap 128, padded audio cap 600 s, 12 CPU decode workers, модель уже загружена; включает чтение, ресемплинг, padding, scoring и запись результатов. Это отдельный оптимизированный evaluation pipeline с предварительной загрузкой трех batches, а не замер Python API transcribe целиком. При первом итоговом Test до экспорта тот же checkpoint обработал 19,89 ч за 38,22 с; времена меняются между запусками.

CPU поддерживается для функционального инференса, его скорость не измерялась. Зависимость от дискового кеша, длительности файлов, CPU decoding и группировки может существенно менять end-to-end время.

Файлы и проверка экспорта

  • model.safetensors: полные FP32 веса аудиоэнкодера и CTC-reader, без optimizer и pickle.
  • bashkir_gemma.py, transcribe.py: переносимый Python API и CLI.
  • asr_config.json, audio_config.json, units.json, frontend/, tokenizer/: архитектура, признаки и словарь.
  • provenance.json: зафиксированные revisions, размеры и SHA256 чекпойнтов/экспорта.
  • validation_history.json, test_metrics.json, benchmark_rtx5090.json: машиночитаемые результаты.
  • export_verification.json: проверка точного совпадения весов и logits, batched API и метрик полного Test с обученным checkpoint.
  • TRAINING_RECIPE.md: настройки запуска и последовательность воспроизведения адаптации.

Экспорт включает и замороженные веса, и дообученные верхние слои. Одинаковый итоговый Test WER/CER проверен на всех 14572 записях. Выполнен отдельный smoke test CPU и проверка загрузки опубликованного snapshot.

Ограничения и атрибуция

Данные CV25 — преимущественно читаемая речь. Качество на разговорной речи, шуме, дальнем микрофоне, диалектах, код-свитчинге и длинных записях отдельно не измерялось. Выход в основном lowercase без восстановления пунктуации. Возможны замены и пропуски; значения WER не гарантируют точность каждой записи.

Базовые веса Google EmbeddingGemma 2 опубликованы под Apache 2.0; этот релиз весов и новый переносимый inference-код — Apache 2.0. Благодарности Google DeepMind за базовую модель, qnguyen3 за исходный ASR-подход и код, авторам/участникам Common Voice и датасета Bashkort Voice. Исходный upstream training repository остается по указанной ссылке и под его собственными условиями; его полная копия здесь не распространяется. Датасеты имеют собственные условия использования.

Downloads last month

-

Downloads are not tracked for this model. How to track
Safetensors
Model size
0.4B params
Tensor type
F32
·
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for AigizK/EmbeddingGemma2-Bashkir-CV25

Finetuned
(128)
this model

Dataset used to train AigizK/EmbeddingGemma2-Bashkir-CV25

Evaluation results