SpeechBrainで音声の感情認識ができるようなので試してみました。
SpeechBrainでの感情認識のサンプル
SpeechBrainには各種タスクを実行するためのレシピが多数用意されています。今回は音声の感情認識を行いたいので以下のレシピを使います。IEMOCAPというデータセットを使って感情認識を行うレシピです。
speechbrain/recipes/IEMOCAP/emotion_recognition
今回はtrain_with_wav2vec2.pyのほうを使っていますが、train.pyでも同様に動くと思います。
データセットが入手できない
IEMOCAPは音声と表情のラベルがセットになったデータセットなのですが、こちらのダウンロードには審査があるようで、大学以外の人がダウンロードするのは難しそうです。今回は諦めて他のデータセットを使うことにしました。
利用するデータセット
今回はこちらのデータセットを使います。
The Ryerson Audio-Visual Database of Emotional Speech and Song (RAVDESS)
https://zenodo.org/record/1188976#.Y1493HbP0Q8
Livingstone, Steven R.; Russo, Frank A. (CC BY-NC-SA 4.0)
ライセンスがCC BY-NC-SA 4.0なので注意してください。
こちらのデータセットは8種類の感情がラベル付けされています。wavのファイル名の'-'で区切られた3番目の数値が感情のラベルです。
今回は以下のフォルダに展開しています。
cd speechbrain/recipes/IEMOCAP/dataset_test
curl -O 'https://zenodo.org/record/1188976/files/Audio_Speech_Actors_01-24.zip'
unzip Audio_Speech_Actors_01-24.zip
展開するとActor_01, Actor_02 と話者ごとにフォルダ分けされたwavファイルが入っています。
hparams/train_with_wav2vec2.yamlを修正
データフォルダを修正します。今回はglob.glob()を使うので以下の形式のパスにしています。
out_n_neuronsは感情ラベルの数です。元は4ですがデータセットに合わせて8に変更しました。
...
data_folder: ../dataset_test/**/*.wav
...
out_n_neurons: 8
iemocap_prepare.pyを修正
以下の部分を修正します。
# 追加
import glob
...
# 音声数の変更
NUMBER_UTT = 1440
...
def prepare_data(
data_original,
save_json_train,
save_json_valid,
save_json_test,
split_ratio=[80, 10, 10],
different_speakers=False,
test_spk_id=1,
seed=12,
):
...
#ここはコメントアウト
#data_original = data_original + "/Session"
def transform_data(path_loadSession):
...
# 話者の数が変わるので10 -> 24に変更
#speaker_dict = {str(i + 1): [] for i in range(10)}
speaker_dict = {str(i + 1): [] for i in range(24)}
# ここを今回のデータセットに合わせて変更
'''
speaker_count = 0
for k in range(5):
session = load_session("%s%s" % (path_loadSession, k + 1))
for idx in range(len(session)):
if session[idx][2] == "F":
speaker_dict[str(speaker_count + 1)].append(session[idx])
else:
speaker_dict[str(speaker_count + 2)].append(session[idx])
speaker_count += 2
return speaker_dict
'''
# path_loadSessionはtrain.yaml(train_with_wav2vec2.yaml)のdata_folderのパスが来る
# ../dataset_test/**/*.wav のようにAudio_Speech_Actors_01-24.zipを展開した先をしてする
wav_file_list = glob.glob(path_loadSession)
print('path_loadSession:', path_loadSession)
print('wav_file_list:', wav_file_list[:5])
for wav_file in wav_file_list:
dirname = os.path.dirname(wav_file)
dirname = dirname.split('/')[-1]
print('dirname:', dirname)
basename = os.path.basename(wav_file)
# フォルダ名のActor_10の10を取り出してspeaker名にする
speaker = str(int(dirname.replace('Actor_', '')))
# emotionは'-'区切りで3つ目の要素
# このデータセットでは8種類ある
emotion = basename.split('-')[2]
# utteranceはとりあえず空で
utterance = ''
speaker_dict[speaker].append([wav_file, emotion, utterance])
print('speaker_dict:', speaker_dict)
return speaker_dict
train実行
以下のコマンドで学習を実行すると途中で止まりました。wavファイルを読み込んだときにShapeの形が変わってしまうことがあるようです。
python train_with_wav2vec2.py hparams/train_with_wav2vec2.yaml
原因は一部のファイルのチャンネル数が2になっていた
こちらの記事を参考にしました。チャンネル数が1より大きい場合はmeanを使って平均を取るとよさそうです。
https://stackoverflow.com/questions/67508634/speechbrain-dataio-prepare-function-with-csv
train_with_wav2vec2.pyを修正します。
# この2つを追加
import torchaudio
import torch
def dataio_prep(hparams):
...
# Define audio pipeline
@sb.utils.data_pipeline.takes("wav")
@sb.utils.data_pipeline.provides("sig")
def audio_pipeline(wav):
"""Load the signal, and pass it and its length to the corruption class.
This is done on the CPU in the `collate_fn`."""
sig = sb.dataio.dataio.read_audio(wav)
# 2チャンネルの場合は平均をとって1チャンネルに変換
info = torchaudio.info(wav)
if info.num_channels > 1:
sig = torch.mean(sig, dim=1)
#print('sig shape:', sig.shape)
return sig
学習結果
最後まで学習が進みました。test lossとerror_rateが小さくなっているので学習は進んだようです。
speechbrain.utils.train_logger - Epoch: 30, lr: 3.14e-05, wave2vec_lr: 3.14e-06 - train loss: 5.87e-03 - valid loss: 1.37, valid error_rate: 1.60e-01
speechbrain.utils.checkpoints - Saved an end-of-epoch checkpoint in results/train_with_wav2vec2/1993/save/CKPT+2022-10-29+23-48-26+00
speechbrain.utils.checkpoints - Deleted checkpoint in results/train_with_wav2vec2/1993/save/CKPT+2022-10-29+23-47-33+00
speechbrain.utils.checkpoints - Loading a checkpoint from results/train_with_wav2vec2/1993/save/CKPT+2022-10-29+23-41-19+00
100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 36/36 [00:01<00:00, 18.11it/s]
speechbrain.utils.train_logger - Epoch loaded: 22 - test loss: 8.23e-01, test error_rate: 1.25e-01