音声分類の前処理はメルスペクトログラムでOK？　従来のMFCCより高精度な画像分類ベースの論文の紹介

[2021年のディープラーニング論文を1人で読むAdvent Calendar](https://qiita.com/advent-calendar/2021/solo-dl-papers)17日目の記事です。今回の論文は音声分類の論文です。音声と画像は近い部分がありますが、これは「メルスペクトログラムを使い、画像の問題として人間の音声の感情分類をしたら精度がかなり出た」というわかりやすい内容です。

全般的に難しい概念や数式は出ず、初心者にも読みやすい論文です。ネットワークもそこまで重くなく、計算リソースの要件も高くありません。あたかもブログ記事のようですが、**ICCV2021のWorkshopに採択**されています（あなどれない！）。ここまでのアドカレ難しい論文が多かったので、ぜひ癒やされてみてください。著者はヤーコプス大学ブレーメンとドレクセル大学の方です。

* タイトル：**FSER: Deep Convolutional Neural Networks for Speech Emotion Recognition**
* URL：https://openaccess.thecvf.com/content/ICCV2021W/ABAW/html/Dossou_FSER_Deep_Convolutional_Neural_Networks_for_Speech_Emotion_Recognition_ICCVW_2021_paper.html
* 出典：Bonaventure F. P. Dossou, Yeno K. S. Gbenou; Proceedings of the IEEE/CVF International Conference on Computer Vision (ICCV) Workshops, 2021, pp. 3533-3538

## メルスペクトログラム（Mel Spectrogram）ってなんだっけ？
こういうの（論文の図表より）

![17_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232088/0f8dbd84-aa65-7fc5-42a8-0fffce2a8cd3.png)

横軸が時間軸、縦軸が周波数、値はパワーです。この図ではデシベルベースに変換しています（パワーが対数ベースのスペクトルです）。

## 音声分類だとMFCCで特徴量取得しなかったっけ？
そういう流れが定番でしたが、実はメルスペクトログラムで取ったほうが精度が上がることがこの論文で報告されています。

![17_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232088/9a7f5971-9db1-5913-235f-fc9429eb10bb.png)

本論文の結果からです。本論文ではドイツ語、イタリア語、イギリス英語などの**音声データの感情分析を分類問題**として行っています（例：喜び、悲しみ、怒り、恐怖、不快、驚き、ニュートラルなど）。

先行研究ではMFCCベースで特徴量を抽出していますが、実はメルスペクトログラムのほうが精度が出やすいとのことが定量的に検証されています。精度の欄の「＊」がメルスペクトログラムベース、「**」がMFCCベースですが、表2行目の先行研究で両者を比較したところ、MFCCでは3割以上悪化していることを報告しています。

本論文は先行研究で分類された、複数のデータセットに対し、**メルスペクトログラムによる画像分類モデルのみで挑み、MFCCベースを遥かに超える精度を出せた**とのことです。

私の意見ですが、音声界隈の論文でメルスペクトログラムを使うのは別に珍しいことではありません。例えば、Text to speechの論文だと、メルスペクトログラムベースで生成するのが定番になっています。音声分類の前処理でMFCCを使うのをたまに目にして「あれ？」と思っていましたが、やはりメルスペクトログラムのほうが良い、というのが論文になっているのを発見できました。

## メルスペクトログラムってどうやってとるの？
[librosaライブラリ](https://librosa.org/doc/main/generated/librosa.feature.melspectrogram.html)でできます。公式ドキュメントを追う形でおさらいしましょう。

### 音声ファイルの読み込み
まずは音声ファイルを読み込みます。librosaのサンプルにあるトランペットの音を使います。[こちら](https://librosa.org/data/audio/sorohanro_-_solo-trumpet-06.ogg)から聞けます

```python
import librosa
import librosa.display
import matplotlib.pyplot as plt
import numpy as np

y, sr = librosa.load(librosa.ex('trumpet')) # y.shape:(117601,) sr:22050 
```

ここで```y```は生の波形、```sr```はサンプリングレートです。ブラウザで開いたときの表示が5秒ですが、117601サンプルに22.05kHzなので、117601÷22050=5.33秒と計算できます。

### メルスペクトログラム（パワーがリニアスケール）への変換
メルスペクトログラムへの変換は次のようにします。

```python
S = librosa.feature.melspectrogram(y=y, sr=sr, n_fft=2048, win_length=512, hop_length=512)
```

ここで```S```は```(128, 230)```のshapeを持つ行列になります。1つ目の軸は周波数の軸です。2つ目は```hop_length```によって切り取られたウィンドウサイズです。2つ目の次元は```hop_length```によって決まります。今```hop_length=512```で指定したので、117601÷512=229.6→230次元あります。もし```hop_length=256```なら、459.3→460次元になります。

メルスペクトログラムでは、主に```n_fft, win_length, hop_length```の3つのパラメーターがありますが、特に```hop_length```は**スペクトログラムの横解像度に直結するため、かなり重要度の高いハイパーパラメーター**だと思われます。

本論文（FSER）では、```win_length, hop_length```いずれも512を利用していました。このハイパラは論文によって設定が変わるので注意が必要です。

ところで、ここで求めたスペクトログラムはパワーがリニアスケールで、そのままCNNに入れてもあまり精度が上がらないはずです。

```python
img = librosa.display.specshow(S, x_axis='time',
                        y_axis='mel', sr=sr)
plt.colorbar(img)
plt.show()
```

![17_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232088/f0afe7fb-0b97-6b37-b6f8-9d5e03bb761f.png)

これをパワーに関して対数スケールに変換する必要があります。

### メルスペクトログラムのパワーをdB単位に
音声のパワーを表す[dBは対数ベースの特徴量](https://ja.wikipedia.org/wiki/%E3%83%87%E3%82%B7%E3%83%99%E3%83%AB)です。スペクトログラムをdBベースに変換したほうが、ニューラルネットワークに与える値としては有用です。

```python
## dB単位に変換
S_dB = librosa.power_to_db(S, ref=np.max)
## プロット
img = librosa.display.specshow(S_dB, x_axis='time',
                        y_axis='mel', sr=sr)
plt.colorbar(img, format='%+2.0f dB')
plt.show()
```

![17_04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232088/0d5cfe16-0215-2014-69ac-7f0cbf653be0.png)

明らかにこちらのほうが分類しやすそうですね。

## 本論文についての疑問
本論文の大きな主張は「メルスペクトログラムベースで人間の声の感情分類したら、従来のMFCCより断然良かった」です。ただそれだけだと読み方としては雑なので、自分が読んでいて気になった部分を、Q&A形式でトピックを補足していきます。基本的にこの論文、他のアドベントカレンダーで紹介している論文よりも内容が簡単なので、流し読み程度でも理解できます。

### どんなデータ使ってるの？
→4種類のデータを使っています（感情×人数×感情ごとのデータ数が合計データ数と一致しないのはご愛嬌）

1. **Emodb**：ドイツ語音声。7個の感情があり、5人の男性と5人の女性のデータがある。感情ごとに10個のデータがあり、合計535個。
2. **Emovo**：イタリア語音声。7個の感情があり、3人の男性と3人の女性のデータがある。感情ごとに14個のデータがあり、合計588個。
3. **Savee**：イギリス英語の音声。7個の感情があり、4人の男性声優からなる。感情ごとに15個のデータがあり、合計480個。
4. **Ravdess**：言語は特に言及なし。8個の感情があり、12人の女性と12人の男性からなる。合計1440個。

これらの4つのデータを統合して分類しています。先行研究との比較時には別途データ単体で評価しています。統合されたデータは感情クラスごとに以下のサンプル数を持ちます。

![17_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232088/3725f4b3-6bb4-4a02-e2b1-e2d84b6e41e3.png)

各音声の長さは平均3～4秒です。メルスペクトログラムを取り、以下のように分割しました。

* 全体の8割の**2434個**の画像（音声）を訓練
    + うち8割の1947個を訓練
    + うち2割の487個をValidation
* 全体の2割の**609個**の画像（音声）テスト

### モデルはどんなの使ってるの？
AlexNetを想起するような古典的なCNNです。こんな単純なネットワークでも課題を選べば2021年の論文として通用します。

![17_06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232088/ebe27f28-d9fd-d9c8-da64-9de59c42aec3.png)

入力はメルスペクトログラムの画像を**64×64×3のカラー画像でそのまま与えています**。メルスペクトログラムの出力は1チャンネルなのに、librosaのカラーパレットを使ってマッピングしたと思われるスペクトログラム画像を使っているのが面白いです。もしかするとこのカラーマッピングが、何らかの特徴量エンジニアリングの役割を果たしている可能性はあります。

Kerasの実装で、論文の表記にある通りニューラルネットワークの**入力は固定解像度**を使っています。自分の中で「音声はファイルごとに長さが違うのに、解像度を固定してどうする推論するの？」という疑問がありました。ここは特に言及がなかったのですが、訓練は64×64でやって、推論はメルスペクトログラム全体を一気に通している可能性はあります。PyTorchだとこういうこと楽なんですが、Kerasでもできないことはないです。

Data Augmentationを使っているとの記述がありました。訓練解像度を64で固定することで、時間方向・周波数方向のAugmentationが効くと思われます。

### Data Augmentationはどうしてるの？
**高さのシフト、ズーム、Horizontal Flip**を使い、1つの画像に対し追加で20枚の画像を作るようData Augmentationしています。

Data Augmentationをオフライン（静的な画像を作ってしまう）でやるパターンは久しぶりに見ました。普通はジェネレーターの中でやります。「スペクトログラムに対するHorizontal Flipってどういう意味なんだろう？　音声逆再生？」と考えてしまいましたが、画像問題として捉えるのなら意味あるのかもしれません。

### 訓練リソースは？
**16GBのK80のGPUで、400エポック回すのに8日かかった**とのことです。

ただこれはData Augmentationを静的にやって、結果40887枚の訓練データを作ってしまったので、もし増強をオンライン（オンザフライ）でやればもっと少ない時間で訓練終わると思われます。

### なぜメルスペクトログラムを使おうと思ったの？
ただのFFTや振幅のヒストグラムだと一次元の値だから。時間と周波数の同期がとれているメルスペクトログラムが都合がいい（→でもそれMFCCでも一緒じゃない？）。

![17_07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232088/df79cd87-6a8a-78b7-20f8-6adb2b5694b1.png)

### 本論文でのテストデータに対する性能は？

![17_08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/232088/49b378c7-0890-4dbf-2dbd-dea9a29c436b.png)

→結構出てる

## まとめと感想
「音声分類やってみました」なブログ記事のような論文でしたが、ICCV2021のWorkshop通っているのがすごいです。librosaは[GPU対応のPyTorch版](https://github.com/qiuqiangkong/torchlibrosa)があり、**メルスペクトログラムを損失関数にすることもできる割とありがたい指標**なのです。従来のMFCCではなく、メルスペクトログラムを使って高精度を出せることを実験ベースで示していることが、なかなか汎用性が高く面白かったです。

librosaを使ってスペクトルをゴニョゴニョするだけでいいならほぼ画像分類と変わらないので、画像を扱える人にとって音声分類は身近な存在になりそうです。ぜひToy dataで試したくなるような読みやすい論文でした。

## 告知
このアドベントカレンダーが本になりました！
**https://koshian2.booth.pm/items/3595424**
Amazonでも扱いあります詳しくは👉　https://shikoan.com