人工知能に関する断創録

このブログでは人工知能のさまざまな分野について調査したことをまとめています(更新停止: 2019年12月31日)

Freesound General-Purpose Audio Tagging Challenge

最近、Kaggle始めました。登録自体は2年前にしてたのですが、興味起きなくてタイタニックやった後にずっと放置してました (^^;

f:id:aidiary:20180806164425p:plain

今回、取り組んだのはFreesound General-Purpose Audio Tagging Challengeという効果音に対して3つのタグをつけるコンペです。2秒ほどの音に対してギター、犬の鳴き声、チャイム、シンバルなどの41個のタグから3つを付与します。1つの音声に対する正解のタグは1つなのですが、3つのうち正解のタグが上位にあるほどスコアが高くなります。

Deep Learningで音を分類したり、生成したりする技術に興味があったので取り組んでみました。Private Leader Board上では比較的上位に食いこめたので参考までにアプローチをまとめておこうと思います!

Kaggleにはカーネルという実験をまとめたJupyter Notebookを公開できる仕組みがあり、Zafarさんという方がKerasを使って Beginner's Guide to Audio Dataというとてもよいチュートリアルをまとめています。このカーネルは @daisukelab さんが翻訳されてました。感謝!

入力特徴量

入力特徴量は、メルスペクトログラム (64次元)またはMFCC(64次元)です。

手前味噌ですが、MFCCは以前、自分で実装したことあります。

最近は、librosaという音を扱うのにとても便利なPythonパッケージができたため、自分で実装しなくても簡単に計算できます。以下の記事はlibrosaでメルスペクトログラムやMFCCを抽出する方法をlibrosaの実装にまで踏み込んで開設されていて参考になります。

アーキテクチャ

音の分類で使われるモデルアーキテクチャは、画像分類で使われるのと同じ畳み込みニューラルネットワーク(CNN)が一般的です。ただ、画像と違ってあまり深いネットワークは使われません。また音は時系列データでもあるためLSTMなどのRNN系のモデルもよく使われています。

画像は2次元の広がりを持つデータなのでの2次元のカーネルを使いますが、音声は2次元と1次元の両方のカーネルが使えます。どちらがよいかは対象タスクによるのでとりあえず全部試した方がよいと思います。今回は

  • 畳み込みニューラルネットワーク(2次元カーネル)
  • 畳み込みニューラルネットワーク(1次元カーネル)
  • CRNN (Convolutional Recurrent Neural Network)
  • ResNet(1次元カーネル)

の4種類を検討しました。CRNNは畳み込みの結果のあとにLSTMを使うモデルです。

上記の特徴量とアーキテクチャの組み合わせで複数のモデルをたくさん作り、最後にそれらの分類結果をアンサンブルします。多分、コンペの王道です。

その他の細かい工夫

データ標準化

メルスペクトログラムやMFCCの値を音声ファイルごとに平均0、標準偏差1になるように標準化しました。本来は、訓練データ全体で平均0、標準偏差1になるようにするのが好ましいかもしれませんが、音声ファイル単位で処理しています。また、メルスペクトログラムやMFCCの各次元ごとに標準化せずに全体で標準化しています。

Cyclic Learning Rateを導入

fast.aiでも推奨されてましたが、局所最適解に陥りにくくなるそうです。学習曲線がギザギザしているのはそのためです。

データ拡張

音声波形のランダムクロップのみです。雑音付与、音の高さ変更、音の長さ変更などいろいろ考えられますが試しませんでした。

Test Time Augmentation (TTA)

テスト時にデータ拡張してそれらの結果を平均化する手法です。今回はランダムクロップのみですが、導入することでLBスコアで2〜3ポイントほど改善しました。

学習曲線

f:id:aidiary:20180719180459p:plain

ギザギザしているのはCyclic Learning Rateを導入したせいです。

valid/accが高い順に並べると、

  1. ResNet (mfcc)
  2. CNN2d (mfcc)
  3. CNN1d (mfcc)
  4. CNN2d (mel spectrogram)
  5. CRNN (mfcc)
  6. CNN1d (mel spectrogram)
  7. CRNN (mel spectrogram)

となりました。ResNetはvalid/accが高いのですが、train/accが100%に達しており、過学習してる感じです。全体的にメルスペクトログラムよりMFCCの方が精度が高いという結果になっています。

スコア

学習時はTop-1の精度で求めていますが、Kaggle上ではTop-3のMean Average Precision (MAP@3) でスコアがつきます。

手法 val_acc Public LB 収束エポック TTA LB
cnn2d_mfcc 0.782 0.881 epoch 103 0.887
cnn1d_mfcc 0.744 0.849 epoch 121 0.853
cnn2d_melgram 0.731 0.826 epoch 118 0.843
cnn1d_melgram 0.665 0.784 epoch 141 0.815
crnn_mfcc 0.725 0.823 epoch 140 0.843
crnn_melgram 0.639 0.746 epoch 099 0.749
resnet_mfcc 0.788 0.871 epoch 105 0.888

上の全てのモデルの出力確率の幾何平均をとるアンサンブルを導入することで最終的なPublic LBのスコアは 0.937430 で38位/558チームでした。

最終的にPrivate LBのスコアは 0.892994 となり、61位/558チームまで下落してました(^_^;) おそらく、Validation Setに過学習してたのかなと思います。

一応、ブロンズメダルの範囲には入ってるみたいですが、このコンペはメダル出ないタイプでした。また何か面白そうなのは挑戦してみたいと思います!

その他のアイデア

他にも下のようなこと考えてましたが未達でした。

  • タグ付けの信頼度データを活用する
  • OpenSMILE の特徴量を活用する
  • Bi-directional RNNのようなより高度なアーキテクチャを使用する
  • さまざまなデータ拡張を導入する

あまり整理できてませんが、コードはこのリポジトリにあります。

Speech and Audio @ NIPS2017

PFN主催のNIPS2017読み会において Speech and Audio というテーマで発表してきました。

★初SlideShare★

今回は複数の論文をまとめたテーマ発表を入れると聴いたのでどのテーマにするか悩みました。最初は、コンピュータビジョン関連の面白い論文がいくつかあったのでそのテーマにしようと検討していたのですが、音声のキャリアが一番長く、かつMachine Learning for Audio Signal Processingワークショップに参加したこともあり、結局のところ「音」をテーマに選びました。本会議には音メインの研究が非常に少ない(音の研究はINTERSPEECH、ICASSP、ISMIRが中心)のでワークショップ中心です。

音関連の研究をまとめるにあたって下のような表を作って整理しました。

f:id:aidiary:20180126195954p:plain

音に関する研究を音声(Speech)、環境音などの一般的な音(Audio)、音楽(Music)に分け、さらにタスクを認識、生成、検出、その他に分けて整理しました。音の研究というと 音声認識音声合成 だけと思われるかもしれませんが、他にもいろいろな研究テーマやタスクがあることがわかります。

この表はまだまだ追記途中です。こんなタスクが抜けてるというのがあったらぜひコメントください。

個別論文は

を選びました。

Deep Voice2はBaiduの音声合成アーキテクチャに関する論文です。たぶん、参加者で音声合成を知ってる人はほとんどいないだろうと思ったのでなるべく基礎的なところから話しました。

主に取り上げた音声合成アーキテクチャはBaiduの Deep Voice とGoogleの Tacotron です。Deep Voiceはすでに3まで出ているし、比較実験で言及されているTacotronもすでに2まで出てるのですでに時代遅れという・・・まあarXivの時代では仕方がないですね。Tacotronの論文は始めて読んだのですが、実装のイメージがわかないので @r9y9 さんのPyTorch実装 など参考にさせていただきました。

Imaginary Soundscape は画像と音声のマルチモーダルに関する論文です。マルチモーダルなDeep Learningに興味があったのとアプリケーションとしてとても面白い!と思ったので取り上げました。Google Street Viewに音声をつけちゃおう という野心的な試みです。リンク先のデモも面白いのでぜひ試してみてください。著者の一人の徳井さん*1 がmediumで記事も書かれてます。

Imaginary Soundscapeは音を生成しているわけではなく、特徴量が似ている音を検索して再生しているのですが、音を生成する研究も出てきています。こちらも今度紹介したいですね。

Twitterを見てるとVQ-VAEはどこいった?というつぶやきがありました。WaveNetの著者の論文ということは気づいていたのですが、発表直前で指摘されて理解するのに時間がかかりそうだったので放置してました(^^;) というか、今回のNIPS2017ではCapsule Networkとともに有名な論文だったみたいなので誰かが取り上げるんじゃないかと思ってました。結局、誰も取り上げなかったけど(^^;) 興味はあるので読んでみようと思います!

実際のところ音声関連の研究開発をすでに7年ほどやっていて、音声はもういいやという感じだったのですが、けっこう知らないタスクやこれから面白そうな研究テーマを見つけたので少し興味がわいてきました。今後もちょくちょく実装などを紹介していきたいと思います。

*1:徳井さんのサイト Create with AI はAIと表現に関する論文・データセットなどがまとまっておりとても面白いです。こちらもおすすめ。

統計的声質変換 (7) GMMによる声質変換

統計的声質変換 (6) 声質変換モデルの学習の続き。今回が統計的声質変換シリーズの最終回です。

今回は、前回学習した声質変換モデルを使って本当に声が変換できるか試してみたい。前回やったGMMの学習で

 \displaystyle P(z_t|\lambda^{(z)}) = \sum_{m=1}^M w_m N(z_t; \mu_m^{(z)}, \Sigma_{m}^{(z)})

における各コンポーネント mw_m\mu_m^{(z)}\Sigma_m^{(z)} が学習データから推定された状態である。\mu_m^{(z)}\Sigma_m^{(z)} は、

\mu_m^{(z)} = \begin{bmatrix} \mu_m^{(x)} \\ \mu_m^{(y)} \end{bmatrix}

\Sigma_m^{(z)} = \begin{bmatrix} \Sigma_m^{(xx)} & \Sigma_m^{(xy)} \\ \Sigma_m^{(yx)} & \Sigma_m^{(yy)} \end{bmatrix}

のように分割できる。この学習結果は、

clb_slt.gmm
clb_slt.gmm_01.npy
clb_slt.gmm_02.npy
clb_slt.gmm_03.npy

の4つのファイルにダンプされている。

GMMによる声質変換

GMMによる声質変換は、x_tが与えられたときのy_tの期待値を求めることで行う。

\displaystyle (13) \hspace{50pt} \hat{y_t} = E[y_t|x_t] = \sum_{m=1}^M P(m|x_t, \lambda^{(z)}) E_{m, t}^{(y)}

ここで、

 \displaystyle (9) \hspace{50pt} P(m|x_t, \lambda^{(z)}) = \frac{w_m N(x_t; \mu_m^{(x)}, \Sigma_m^{(xx)})}{\sum_{n=1}^M w_n N(x_t; \mu_n^{(x)}, \Sigma_n^{(xx)})}

 \displaystyle (11) \hspace{50pt} E_{m, t}^{(y)} = \mu_{m}^{(y)} + \Sigma_m^{(yx)} \Sigma_m^{(xx)-1} (x_t - \mu_m^{(x)})

である。今回は導出は省いて、論文(PDF)の結果をそのまま借用しよう。

たとえば、Aさんの声をBさんの声に変換することを考える。Aさんの声から抽出したメルケプストラムパラメータ x_t を使って上の式で変換すると \hat{y_t} が求められる。この \hat{y_t} を使って分析合成すると元のAさんの声がBさんの声になっているというわけ。今回は、ピッチの変換モデルは学習していないので変換元のAさんから抽出したパラメータをそのまま使う。

f:id:aidiary:20150419092011p:plain

当たり前であるが変換モデルを学習するときにはAさんとBさんの両方の声が必要だったが、実際に声質を変換するときはAさんの声だけあればよい。上の式で本当にAさんの声がBさんの声になるかさっそく実装して試してみよう。

作成したスクリプト

上の式では、コンポーネントを表す変数に m を使っているが、スクリプトではメルケプストラムの次数に使ってしまったため代わりに K を使っているので注意。

先の式はすべてのフレーム t について計算する必要があるためそのまま実装すると非常に計算が重い。そこで、計算を高速化するためにいくつか工夫している。

  • 式 (11) のフレームtに依存しない項(共分散行列の積)を最初に計算して保存しておく
  • 式 (9) の分母を先に計算して保存しておき、分子は再計算しない
  • 式 (9) の多次元正規分布のオブジェクトをあらかじめ作成しておく

順に確かめたところ3つめが一番高速化に寄与していた。オブジェクト作成というのはけっこう重い処理のようだ。

声質変換例

さっそく上のスクリプトを使って音声を変換してみよう。今回は、clbさんの声をsltさんの声に変換する。aセットの最初の50文はGMMの学習に使用したのでそれ以外の文を使ってテストした。

python convert_voice.py wav/clb/arctic_b0001.wav clb_slt.gmm converted_b0001.wav

変換元(clb)の音声

変換先(slt)の音声

clbからsltへ変換した合成音声

別の例。

変換元(clb)の音声

変換先(slt)の音声

clbからsltへ変換した合成音声

GMMの学習に使用したa0028だと・・・

変換元(clb)の音声

変換先(slt)の音声

clbからsltへ変換した合成音声

今回は、ピッチの変換はしていないのでイントネーションはオリジナルのものがそのまま維持される。本来は声質変換したclbの音はsltと似ていなくてはいけないのだが、元の二人の声が似ていることもあり、本当に正しく変換されているのかよくわからない結果になってしまった・・・音質が悪いこともあるがむしろ似ていないように思える。

音質の改善は元のチュートリアル記事にあるようにWORLDという分析合成システムを使うとよさそう。あと学習データ数を増やしたり、GMMの数を調整したり、別の話者でも試してみるとよいかもしれない。今回の手法はかなり昔の基本技術のようで最新の技術はずっと進んでいるようだ。戸田さんの講演資料が参考になりそう。クッソムズそうだけどね。