Nishika音声認識コンペに参加して2位になりました!🎉

はじめに

こんにちは、AIチームの大竹です。

今回は弊社AIチームがNishikaにて開催された音声認識コンペに参加したので、その参加報告をさせていただければと思います。

弊社は AI Messenger VoicebotAI Messenger Summary など、音声処理技術を活用したプロダクトを提供しています。しかし、弊社が持っている音声処理に関する技術力をアピールできる機会は少なく、現在のAIチームの技術力のアピールとさらなる技術力向上のために非常に良い機会でしたのでコンペに参加しました。

コンペ概要

主催者について

今回参加したコンペはNishika株式会社が主催したものになります。NishikaはAIモデルの開発、AI人材マッチング、AI研修サービスを提供するプラットフォームです。今回のようなコンペティションを通して高精度なAIモデルの開発、提供を可能にしています。

コンペの内容について

本コンペティションの内容は文学作品の文字起こし(音声認識)です。

学習・評価に利用されたデータセットは青空文庫の文章とそれを朗読した音声から構成されています。具体的には、「芥川龍之介の蜘蛛の糸」、「夏目漱石の吾輩は猫である」、「太宰治の走れメロス」などの著名な文学作品を朗読した音声と作品の文章が含まれています。

評価指標はCER(Character Error Rate)となっており、どれだけ正確に音声認識ができているかを文字単位で評価します。この値が低いほどスコア的には良いものになります。

本コンペは7月から8月末までおよそ2ヶ月間開催され、総勢252人が参加し、合計で427件の投稿がありました。

コンペの進行

本コンペには弊社AIチームのうち5人が参加し、協力して一つのアウトプットを出すというよりはそれぞれ違う解法を各自で試すという方針で臨みました。普段の業務と並行しながらの参加ということもあり、チュートリアルまで取り組んで終わってしまったというメンバーもいたため、結局、コンペにアウトプットを提出できたのは5人のうち私を含めて2人でした。

1人はWhisperを用いた音声認識に取り組み、コンペ期間の前半(7月末まで)でベスト3の成績を残していました。しかし、その方が都合により継続できなくなったため、コンペ期間後半からは私がメインで取り組むことになりました。

以下には、私が取り組んだ解法のみを記載したいと思います。

解法

モデル

本コンペで用いた音声認識システムのパイプラインは、まず、VAD (Voice Activity Detection)モデルで有声区間を検出し、抽出した有声区間に対してASR (Automatic Speech Recognition)モデルを用いて文字起こしを行うというものです。

それぞれ使用したモデルは以下のとおりです。

実行環境

下記の環境でモデルの学習および評価を行いました。

  • CPU: Google Compute Engineのn1-standard-8インスタンス (8 個の vCPU、30 GB RAM)
  • GPU: NVIDIA T4(メモリ16GB) 4枚 (推論はGPU1枚で十分です)
  • OS: Debian GNU/Linux 11 (bullseye)

ESPNetのレシピの実行

今回、ASRモデルの学習はespnetを用いて行いました。学習は基本的にはespnetの学習レシピに従い、以下のような流れで行いました。

  1. コンペデータのダウンロード
  2. データの前処理
    1. データの分割:訓練セット、検証セット、テストセットに分割
    2. 話速変化に基づくデータ拡張: 0.9, 1.0, 1.1倍の話速の音声データを生成し、データ量を3倍にする
    3. トークンリストの作成:トランスクリプトに含まれる文字集合でトークンリストを作成する
  3. 言語モデルの訓練
    • 音声認識モデルのデコーディング時に用いるLSTMベースの言語モデルをスクラッチから訓練します。
    • バッチサイズ384, エポック数40で訓練し、検証データの損失が最小のモデルを保存するようにしました。
    • 訓練に用いたハイパーパラメータの完全版はこちらに記載しています。
  4. ASRモデルの訓練
    • reazonspeech-espnet-v2をファインチューニングします。
    • エポック数15で訓練し、検証データに対する正解率ベスト3のモデルを保存し、それらの移動平均を取るようにしました。バッチサイズは音声長によって動的になるように設定しました。
    • 訓練に用いたハイパーパラメータ完全版はこちらを参照してください。

本来なら、この後に訓練したモデルを分割したテストセットを用いて評価するべきですが、追加の実装が必要になるため、今回はテストセットによる評価を省略しました。

追加データを用いた学習

今回のコンペでは機械学習モデルを学習する用途で外部データの使用が許可されていました。コンペ内でのトピックにおける議論によると青空文庫のデータを用いた言語モデルの学習も許可されるとのことでした。テストデータのリークの可能性に関する疑問を持ちながらも、ランキング上位の方々が使用する方針とのことだったので私もこちらのデータの活用を試みました。

追加データを用いることでオープンリーダーボードのスコアが1%程度改善しました。

推論時のハイパーパラメータのチューニング

ハイパーパラメータ一覧

今回のコンペでチューニングしたハイパーパラメータには以下のようなものがあります。

  • asr_beam_size: 音声認識のビームサイズ
  • asr_ctc_weight: 音声認識のデコーディングにおけるCTCモジュールの予測の重み
  • asr_lm_weight: 音声認識のデコーディングにおける言語モデルの予測の重み
  • vad_min_duration_off: この値未満の音声区間は無視する
  • vad_min_duration_on: この値未満の無音区間は音声区間として扱う
  • merge_segments: 短い音声セグメントを結合するかどうか

書き起こし結果に対する定性的な分析やオープンリーダーボード上のスコアを手がかりにこれらのハイパーパラメータを調整しました。

具体的には以下のような流れでハイパーパラメータを決めていきました。

リーダーボードのスコアに関係なく決定したハイパラ

merge_segments, vad_min_duration_on , vad_min_duration_off
  • merge_segmentsは短いセグメントを指定したセグメント長になるまで結合するのでASRモデルに与える音声セグメントが長くなります。その結果OOM(GPUメモリが溢れて推論できなくなってしまうこと)になったり、「ハルシネーション」や「繰り返し」が起きてしまったりする問題が発生しました。したがって、スコアに関係なく今回はmerge_sgements=Falseで固定しました。
  • vad_min_duration_onは短いセグメントを削除するためのもので、この値よりも小さい音声セグメントは無視されます。フィラーなどを無視するためには有効だと思いますが、今回扱うデータは朗読音声なので基本的にフィラーなどは存在しないだろうと考えてvad_min_duration_on=0.0に設定しました。
  • 一方でvad_min_duration_offは有声セグメント長が短く区切れすぎないようにするパラメータです。この値より小さいものは1つのセグメントとして区切れないようになります。セグメントが短くなりすぎると文脈を考慮した音声認識性能が低下してしまうのではないかと考えて書き起こし結果を観察しつつ、vad_min_duration_off=0.3としました。
asr_beam_size

asr_beam_sizeに関してespnetのライブラリのデフォルト値は20でしたが、値を少し減少させても定性的に音声認識結果が変わらない、かつ、値を大きくしすぎるとOOMになってしまうためスコアに関係なくasr_beam_size=5で固定しました。

asr_ctc_weight

ハイブリッドCTC/AttentionのASRモデルのアーキテクチャにおいて、どれだけCTCモジュールの予測を考慮するかどうかというパラメータになっています。CTCモジュールの予測確率を用いたビームサーチにより、音声系列とテキスト系列の単調なアライメントを導入でき、繰り返しや早期にend of sequence(系列の終了記号)を予測してしまう問題を防ぐことができます。
今回は直感ですがasr_ctc_weight=0.1に決め打ちしました。
ちなみに、コンペ終了後にasr_ctc_weight=0として提出したところスコアが顕著に悪化しました。やはり、Attentionを用いた音声認識において単調なアライメント制約を導入することは重要のようです。

asr_ctc_weight オープンリーダーボードスコア(↓)
0.1 0.105855
0.0 0.184982

リーダーボードのスコアを参照して決めたハイパラ

asr_lm_weight

デコーディングの際のビームサーチにおいて、言語モデルの予測をどれだけ考慮するかを決めます。これが大きいほど言語モデルの影響が大きくなります。
asr_lm_weightを0.1から増加させていった場合の提出結果を以下に示します。

asr_lm_weight オープンリーダーボードスコア(↓)
0.6 0.106495
0.5 0.105855
0.4 0.106425
0.3 0.110242
0.2 0.113428
0.1 0.118170

やはり、言語モデルの予測がスコアに与える影響は大きく、asr_lm_weightを大きくしていくとスコアが改善します。しかし、大きければ大きいほど良いわけではなく、ベストな値があり、ASRモデルと言語モデルの予測のバランスを取ることが重要だとわかりました。

最終結果

最終リーダーボードのスコアが0.1070362位の結果となりました!🎉
leaderboard

その時のハイパーパラメータの値は以下の通りです。

  • asr_beam_size: 5
  • asr_ctc_weight: 0.1
  • asr_lm_weight: 0.5
  • merge_segments: false
  • vad_min_duration_off: 0.3
  • vad_min_duration_on: 0.0

最終結果が出るまで色々ありましたが、最終的に2位になることができてよかったです。

最後に今回のコンペで工夫した点や難しかったと感じた点を私の所感とともに記述します。

工夫した点

ASRモデルに与える音声セグメントの音声に対して無音区間を付与した点

ReazonSpeechのissueで議論されている通り、Transformerベースの音声認識モデルは突然音声が始まったり終わったりするセグメントに対して、ハルシネーションや繰り返しが発生する可能性が高まります。こうした音声セグメントに対して、ReazonSpeechの実装に従って、冒頭の1秒間と末尾の0.5秒間に無音区間を挿入しました。このようにすることでVADモデルを用いて切り出したセグメントに対する音声認識のロバスト性が向上したと考えています。

ASRモデルをファインチューニングする際にトークン集合とトークン埋め込み層を初期化した点

文学作品へのドメイン適応性能を高めるため、ReazonSpeechのデコーダーのトークン埋め込み層のみ初期化してファインチューニングすることにしました。このようにすることで、汎用的な音声処理認識能力は維持しつつデコーダーのトークン出力のみを文学作品向けにカスタマイズできたと思います。また、言語モデルでも新たなトークン集合を扱うことができ、より文学作品に特化した音声認識が可能になったと考えられます。

難しかった点

文学作品という特殊な文字の扱い方がされている中での音声認識

普段ならひらがなで表現する文字が漢字になっていたり、見慣れない表現が頻発したり、送り仮名の使い方が普段のものと異なったりしていて、音声的には正解と言えるものでも、文学作品の文字起こしとしては正解とはならないものが多かった点が難しかったです。一方で、このような問題に対して、文学作品特化の言語モデルの予測を音声認識時に組み込むことで、ある程度カバーできることが確認できたのは良い学びでした。

音声認識モデルに対してベストな音声区間検出

音声区間が長すぎるとセグメントのデコーディング時にハルシネーションや繰り返しが発生する可能性が高まり、一方で音声区間が短すぎると文脈を考慮した音声認識による精度向上の可能性が低くなってしまうので、適切な長さで音声区間を検出できると良いのですが、その調整が難しかったです。

テストデータがリークしていると思われる中でどの手法を選択したらよいか

今回のコンペでは、テストデータが明示的に示されていないものの、青空文庫のデータに含まれていて、こちらのデータを言語モデルの学習資源として扱っていいという運営の方針がありました。さらに、このデータにはwhisperによる音声認識結果も付与されているため、その結果を入力とし正解テキストを予測するような言語モデルを学習すれば音声認識を工夫することなく、高スコアがとれるのではないかということも考えられました。個人的にそのような方法ではそのような方法では音声認識の新しい知見が得られないと思ったので、解法に示した方法で対策しました。しかし、私が選択した方法でも結局正解がリークしている可能性があるので、本来は避けたほうが良いのですが、言語モデルの予測を音声認識のデコーディング時に考慮することで、ある程度有用なドメイン適応が可能だという知見が得られたので良かったです。専門用語の多い音声認識などに対しては有効な手段だと思います。

最後に

今回は、弊社AIチームとして初めて国内の音声認識コンペに参加した報告をさせていただきました。コンペ終了までにいろいろなことがありましたが、チームの音声認識に関する知識レベルの底上げや今後参考になるような知見、また2位という名誉な結果となり、非常に良い機会だったなと思います!今後もこのような機会があれば積極的に参加し、音声認識技術の向上および対外的なアピールができたらと考えています。
なお、今回のコンペで使用したコードはこちらのリポジトリに保管してあるのでご参考までにご確認ください。

最後に、本コンペティションを主催していただいたNishika株式会社様には、心より感謝申し上げます。

PICK UP

TAG