音声認識やってみたいのですが、ラベル付きデータを用意するのが大変です。
教師データなしで学習した後にファインチューニングする方法があるぞ
HuBERTは下記の論文で紹介されている手法です。
下記の論文
- HuBERT: Self-Supervised Speech Representation
Learning by Masked Prediction of Hidden Units : https://arxiv.org/pdf/2106.07447.pdf
教師なし学習の手法は下記の図で示されます。
- 音声データからMFCCで特徴量抽出
- MFCCのデータをK-meansでラベルを生成
- 音声データからCNNで特徴抽出
- CNNの特徴をランダムにマスク:マスクレートは変更可能でマスク部分はランダムに変更される
- マスクした部分のK-meansで生成したラベルを当てる

この手法の利点
- マスク部分を当てるだけなので、ロスが下がりやすくなります。音声データの場合、データ長が長くなりがちでタスクが難しくなりますがこの点が解消されている点です。
HuBERTの結果は下記です。
10分、1時間、10時間、100時間のラベルデータで評価しています。同様の教師なし学習のwav2vecより若干、性能が高いです。
wav2vecの記事は下記に記述しています。

Google Colabで動作確認をします。
必要なライブラリを導入します。
! pip install transformers datasets
下記コードで学習済みモデルを取得し、簡単な動作確認をします。
- HuBERTの前処理とモデルを設定します。
- ダミーデータを取得します。
- ダミーデータを前処理
- モデルに入力し、モデルで推論
- ターゲットラベルの前処理
- ターゲットラベルと推論したラベルでロスを計算
import torch
from transformers import Wav2Vec2Processor, HubertForCTC
from datasets import load_dataset
import soundfile as sf
processor = Wav2Vec2Processor.from_pretrained("facebook/hubert-large-ls960-ft")
model = HubertForCTC.from_pretrained("facebook/hubert-large-ls960-ft")
def map_to_array(batch):
speech, _ = sf.read(batch["file"])
batch["speech"] = speech
return batch
ds = load_dataset("patrickvonplaten/librispeech_asr_dummy", "clean", split="validation")
ds = ds.map(map_to_array)
input_values = processor(ds["speech"][0], return_tensors="pt").input_values # Batch size 1
logits = model(input_values).logits
predicted_ids = torch.argmax(logits, dim=-1)
transcription = processor.decode(predicted_ids[0])
target_transcription = "A MAN SAID TO THE UNIVERSE SIR I EXIST"
with processor.as_target_processor():
labels = processor(target_transcription, return_tensors="pt").input_ids
loss = model(input_values, labels=labels).loss
思ったより簡単に使用できました。日本語でも試してみたいです。
日本語で試すのはまた別の記事にするぞ