Некоторое время назад к нам пришел клиент – крупный металлургический комбинат. Продукцию комбината перевозят поезда. А во время железнодорожных грузоперевозок машинисты и диспетчеры должны переговариваться согласно регламенту. За переговоры не по регламенту - штраф. Поэтому “боль” клиента была сильной: получить систему автоматического контроля регламента переговоров по рации во избежание финансовых потерь и снижения риска катастроф.   Мы опрометчиво согласились. А когда получили аудиозаписи, поняли, что поторопились подписывать договор. Дело в том, что записи с раций сопровождаются огромным количеством шумов. Качество аудио было такое, что порой мы сами не могли ничего разобрать. В одной записи мы поначалу слышали только «во во во», а когда напряглись, различили «два вагона вагон». Потренировав ухо, мы разметили некоторое количество записей и загрузили их в свою универсальную модель. Результат был плохой: ошибка распознавания - 76,9% (вернее WER – 0,769). Решили прогнать записи на других решениях. Итог был не лучше: ошибка Google составила 92% (WER – 0,92), другие вендоры дали похожий результат. В принципе, еще можно было отказаться. Но мы решили «избрать путь самурая», а, как известно, путь самурая – это путь, ведущий к смерти. Шанс сделать из решения, которое почти ничего не распознает, решение, которое распознает почти все, стремится к нулю. А подписавшись на выполнение, мы рисковали попасть на большие штрафные санкции. Первый месяц, работая на старой end2end архитектуре, мы не смогли заметно продвинуться в качестве. Уже почти отчаявшись, мы решили пойти ва-банк и перестроить все свое решение. Что мы сделали:  Перешли от end2end архитектуры на гибрид. Для гибрида нужно меньше обучающих данных и он более робастный к изменениям аудио-среды. На гибриде мы стали ставить эксперименты, чтобы найти оптимальную конфигурацию. Транскрибировали около 50 часов записей (потом, правда, потребовалось оттекстовать еще). Собрали корпус текстов, характерных для железнодорожной сферы: инструкции машинистов, регламенты и т.д Иногда казалось, что улучшить результат не получится, кейс провальный. Но за неудачами следовали эксперименты, улучшающие метрику. В итоге нам удалось снизить WER почти в 3 раза и распознавать речь с раций достаточно качественно.  Что действительно помогло: Как ни удивительно, самый большой вклад внесли тексты для языковой модели. Только они обеспечили снижение WER на 0,3. Мы сами в это не сразу поверили, но объясняется данный факт довольно просто. При переговорах по рации на железнодорожном транспорте 200 самых употребимых выражений составляют порядка 90% от всех слов. Более того, если все слова распознавать как слово «вагон», вы получите около 15% качества :) Таким образом, сузив словарь до нескольких сотен слов (назовем его словарь Эллочки-людоедки) и правильно оценив вероятность их употребления, мы получаем максимальный прирост качества. Вторым фактором было дообучение акустики и работа с шумами. Основной прирост мы начали получать, разметив (транскрибировав) 40 часов записей. Остальная разметка (еще несколько десятков часов) дала буквально 3% в приросте метрики. Третий по значимости фактор – адаптация самой модели.  Вывод  №1 – львиная доля прироста качества пришлась на создание обучающего датасета, при этом основной прирост дала семантика и первые 40 часов аудио. Вывод №2 – иногда (правда не всегда), качество распознавания речи можно кардинально улучшить, имея нужный датасет и полгода на эксперименты;). Вывод №3 – нам повезло. Если бы не узкая вариативность употребления слов в записях, не видать нам такого качества как своих ушей. И путь самурая - это интересно, но лучше не подписываться под обязательства, когда велик риск их не выполнить. В следующий раз может так не повезти. Бонус для дочитавших: наш телеграм бот @AmVeraSpeechBot. В боте вы можете проверить качество работы нашего решения по распознаванию речи (Amvera Speech) (это универсальная модель, а не модель для ЖД) и просто безлимитно и бесплатно распознавать голосовые сообщения. Просто отправьте в бот короткую аудиодорожку или голосовое сообщение – и получите текстовую расшифровку.