日本語の音声認識モデルと実行方法を整理した
はじめに
こんにちは!KGモーターズ株式会社でエンジニアをしている中村です!
KGモーターズは、広島を拠点に1人乗り小型 EV mibot
を開発しているスタートアップです。
最近東京日暮里にオフィスができました!
現在はmibotの量産に向けて絶賛開発中ですが、mibotの価値を上げるためにAIは重要な要素になります。
その中でも特に重要なものの一つに音声系のAIがあります。
私自身コンピュータービジョン(画像)のAIエンジニアをしていたので、うっすら知っていた日本語の音声認識AIについて整理をしようと思いました。
まずはどんなベンチマークがあるのか、よく使われる評価指標の意味、日本語の音声認識モデル、お試し推論の流れでまとめてみます。
ベンチマーク
CSJ
CSJ(Corpus of Spontaneous Japanese)は約7百万語、500時間の大規模日本語自発音声コーパスで、日常会話やビジネスシーンにおける音声認識モデルの訓練に適していると言われています。
こちらにいくつかサンプルがありますので、聞いてみましょう。(聞いてみるのが一番早いです)。結構フォーマルなイメージです。
学会講演
インタビュー音声
JNAS
JNAS(Japanese National Corpus)は、標準的な日本語を対象にした音声データセットで、特に新聞朗読音声が収録されています。発話のスピードや発音の正確さが求められるため、音声認識モデルの評価や訓練に有効です。また、異なる話者の音声が含まれているため、多様なアクセントやイントネーションを学習するためにも役立ちます。
こちらにサンプルあるので聞いてみましょう。かなりお堅いですね。
サンプル1
サンプル2
SPREDS-U1-ja
NICT(情報通信研究機構)が提供しているSPREDSシリーズの日本語のデータセットです。
中身は読み上げ形式の日本語音声データセットになっています。
CSJもそうですが、音声モデルの評価ベンチマークでよくお目にかかります。
このデータは以下からダウンロードができます。21言語含まれているので、jpn
が日本語です。
聞いてみるとわかりますが、相当しっかりしたデータです。さすがNICT...
Common Voice Japanese
クラウドソース型のオープン日本語音声データセットです。約4,000人以上の話者による読み上げ音声が収録されており、特徴的な点として、多様な年齢・性別・アクセントを含むという点が挙げられます。
音質や発音ばらつきも大きく、一部非母語話者も含まれるため、雑音環境や非一様な音声へのモデル耐性評価に有用だと言われています。
実はKaggleのDatasetsに入っているので簡単にサンプルを聞くことができます。
明らかに母国語でない人が日本語を話していることがわかると思います。
精度指標
WER
Word Error Rate、単語誤り率と呼ばれます。誤差なので小さい方が嬉しいということになります。
式で書くと以下です。
つまり、予測した文を手入れして正解に合わせたときにどういう操作を何回するかをカウントします。操作をすればするほど間違っているわけなので、誤差は大きくなっていきます。具体的には以下の操作をカウントします。
- 予測した単語が正解と比べて間違えていて置き換えた
- 予測したが正解に対して単語が不足しており追加した
- 予測した文が正解に対して余計な単語が含まれているので削除
CER
Character Error Rate、文字誤り率と呼ばれます。これも誤差なので小さい方が嬉しいということになります。
式で書くと以下です。
WERは単語ベースでしたが、CERは文字ごとに評価するということです。
モデル
では有名どころの日本語音声モデルをピックアップしてみます。
Whisper Large-v3
言わずと知れたOpenAIのモデル。2023年なのでちょっと古いが、日本語に強いモデルが少ないのでいまだに健在という印象。
2024年にLarge V3 Turboという速度が上がったモデルが出ていますが、今回はLarge V3を動かします。
Whisper自体のアーキテクチャはシンプルなE2Eなアプローチになっていて、EncoderとDecoderはザTransformerになっています。入力音声は30秒ごとに分割して、Log-Melスペクトログラムを通してTransformerに入力されます。
Log-Melスペクトログラムはメジャーな特徴量抽出器で、周波数の時間変化のヒートマップで表されるアレです。(人間の聴覚感性に近づけるためにMelスケールというものに変換しています)
またTransformerの登場でこれまたメジャーになった特殊トークンを使って、多言語・マルチタスクで学習をします
Robust Speech Recognition via Large-Scale Weak Supervision
kotoba-whisper-v2.2
同時翻訳で有名なKotoba Technologiesさんのkotoba-whisperシリーズ。
現在はv2となっていますが、もともとはWhisperを教師モデルとして知識蒸留により日本語特化にしています。
速度が格段に早く、Whisper Large v3に比べて推論速度が6.3倍速いと言われています[1]。
ここからv2.0→v2.1 ...と蒸留手法の最適化、句読点付与機能、話者分離などがアップデートされて、精度はWhisper Large-v3と同程度を保ちながら高速化が実現できています。
ReazonSpeech
Reazon Human Interaction Labから出ているReazonSpeechで、いくつかシリーズがあります。推論速度が速いのはNeMoの方です。
ReazonSpeech NeMo
ReazonSpeech ESPnet
実力を見てみよう
Hugging Face Datasetで推論しても面白くないので、より難易度をあげるため(?)に、以前noteで出した自分の所属を言っている音源を使ってみます。
Ground Truthがそもそも噛みまくっています。
SDV開発 車載 SDV開発 車載HM SDV開発 車載HMI開発 兼コネクトサービス開発チームリーダー
では行ってみましょう。
前提として動作環境は以下のような感じです。
- NVIDIA T4 16GB GPU
- GPUをマウントしたDocker Containerで実行
- 必要なライブラリ(CUDAに合わせたPytorch, transformers, hugging_face等)はコンテナ内の仮想環境にインストール済み
Whisper Large-v3
こちらを見ながら推論しました。
import sys, torch
from transformers import AutoModelForSpeechSeq2Seq, AutoProcessor, pipeline
audio_path = sys.argv[1] if len(sys.argv) > 1 else "audio.wav"
device = "cuda:0" if torch.cuda.is_available() else "cpu"
torch_dtype = torch.float16 if torch.cuda.is_available() else torch.float32
model_id = "openai/whisper-large-v3"
model = AutoModelForSpeechSeq2Seq.from_pretrained(
model_id,
torch_dtype=torch_dtype,
low_cpu_mem_usage=True,
use_safetensors=True,
attn_implementation="sdpa",
).to(device)
processor = AutoProcessor.from_pretrained(model_id)
pipe = pipeline(
"automatic-speech-recognition",
model=model,
tokenizer=processor.tokenizer,
feature_extractor=processor.feature_extractor,
torch_dtype=torch_dtype,
device=device,
)
result = pipe(audio_path)
print(result["text"])
結果は以下です。さすがWhisper。逐語的な文字起こしではなく、意味ベースで出力できています。
同じフレーズやノイズ、発音の揺らぎも同一として見なせています。
SDV開発 社債 HMI開発 県コネクトサービス開発チームリーダー
車載→社債、兼→県は、まぁ許してあげましょう。
kotoba-whisper-v2.2
実行前にHugging Face CLIでログインが必要です。
ちなみに環境構築でコケたのでこちらを参考にしたらできました。
import torch
from transformers import pipeline
model_id = "kotoba-tech/kotoba-whisper-v2.2"
torch_dtype = torch.float16 if torch.cuda.is_available() else torch.float32
device = "cuda:0" if torch.cuda.is_available() else "cpu"
model_kwargs = {"attn_implementation": "sdpa"} if torch.cuda.is_available() else {}
pipe = pipeline(
model=model_id,
torch_dtype=torch_dtype,
device=device,
model_kwargs=model_kwargs,
batch_size=8,
trust_remote_code=True,
)
audio_path = "sample.wav"
result = pipe(audio_path, chunk_length_s=15, add_punctuation=True)
for spk in result["speaker_ids"]:
print(f"{spk}: {result[f'text/{spk}']}")
結果は以下です。かなり逐語的に出力されています。
車載が書斎、SDVがSDBなどなど間違えていますが、HMI開発兼コネクトサービス開発チームリーダー
は完璧です。
SDV開発、書斎SDBが主催。HMISUV開社債、HMI開発兼コネクトサービス開発チームリーダー
CERは概ね0.33程度です。
ReazonSpeech NeMo
あまりに環境構築のメモがないので、記録として残しておきます。
前提としてCUDAのバージョン互換性のあるTorchがインストール済みであるとします。
# NVIDIA NeMo
pip install "nemo_toolkit[all]"
# ReazonSpeechのインストール
git clone https://github.com/reazon-research/ReazonSpeech
pip install ReazonSpeech/pkg/nemo-asr
では推論してみましょう。
from reazonspeech.nemo.asr import load_model, transcribe, audio_from_path
audio = audio_from_path("sample.wav")
model = load_model()
ret = transcribe(model, audio)
print(ret.text)
結果は以下です。あまり3つの中だと一番できてなさそうな気がする...
sdv開発v開発主催hmi開発健康ネクトサービス開発チームリーダー
CERは概ね0.58と、kotoba whisperより精度が低そうという直感とあっています。
最後に
どのような形でmibotに音声AIが使われるか?はここでは書いていませんが、その要素技術になりそうな日本語音声AIについてまとめました!
KGモーターズでは、AI開発だけでなくアプリ開発、クラウド開発などのエンジニアを募集しています!
カジュアル面談から可能なので、ぜひお気軽にご連絡ください!
Discussion