ディープラーニング で音声データのノイズリダクション 〜 その②

公開日:2019-06-01
最終更新:2019-06-01

音声のノイズリダクション、その2です。

今回はRNNoiseを試してみました。
RNNoiseはJean-Marc ValinさんがMozillaにいた時に公開したオープンソースソストウェアで、ディープラーニングと昔ながらのDSP(デジタルシグナルプロセッシング)の手法を組み合わせているのが特徴です。

折角なので翻訳(意訳)してみることにします。

原文はこちら

RNNoiseとは

このデモはRNNoiseプロジェクトがどのようにディープラーニングを使って音声のノイズ除去を行っているのかを説明します。核となるアイデアは、従来からあるシグナルプロセッシングとディープラーニングを組み合わせることで、軽量かつ高速で、リアルタイムで使えるノイズ除去アルゴリズムを作ることです。GPUは必要ありません。Raspberry Piでも簡単に動作し、簡単でかつ従来のノイズ除去システムより良い結果を出します。

ノイズ除去とは

ノイズ除去とはずいぶんと古くからあるトピックで、少なくとも70年代から取り組まれています。名前が指し示す通り、スピーチそのものへの影響を抑えつつ、できる限りノイズを取り除くというのが目的です。

上記は従来型のノイズ除去アルゴリズムの概念図です。
アルゴリズムは、まず人が話している部分を見つけ(Voice Activity Detection)、そこからただのノイズの部分を割り出します。その後、ノイズ音声の特徴を抽出し、その分を元の音声データから引き算します。

上記の概念図を見ると、ノイズ除去は簡単そうに見えます。たった3つしかタスクはないですし。もう出来ているんでしょって感じですよね。でもそんな事はないんです。エンジニアリングを大学で学んだ方なら誰でもそこそこ機能するものは作れます。でも、高性能に機能するもの、どんなノイズにも使えるものを作るのは至難です。そのためには細かなチューニングとテストが必要なんです。どうしても問題を引き起こしてしまうような変なノイズがあって、それをカバーしようとするといままでOKだった部分がおかしくなってしまうんです。これは50%はサイエンスですが、50%はアートです。speedxdsp libraryにもノイズ除去アルゴリズムがありますが、うまく動いているようにみえて、全然完璧ではありません。

ディープラーニングとRecurrent Neural Network

ディープラーニングはArtificial neural networkと呼ばれていた昔からあるアイデアなのですが、新しい実装です。60年代からあったのですが、最近になって花開いたのは以下のような理由によります。

  1. 2層より深いネットワークの作り方がわかってきた
  2. 時系列データの扱い方がわかってきた
  3. 必要なコンピュータリソースが安くなってきた

RNN ( Recurrent neural network )はとても大切な概念です。これにより時系列のデータを扱うことができるようになりました。ノイズ除去は何がノイズかを推測するための時間が必要なので、RNNはとても重要です。長い間、RNNは長い時間を扱うことが苦手だったのですが、近年はLSTM(Long short time memory)やGRU( Gated Recurrent Unit )の登場により、長時間にわたるデータも扱えるようになっています。

RNNoiseはGRUを使っています。
*GRUの解説は割愛しました〜

ハイブリリッドアプローチ

近年のディープラーニングの成功から最近ではなんでもかんでもディープニューラルネットワークにぶっこむようになりました。このやり方はend-to-end(最初から最後まで)と呼ばれているのですが、スピーチ認識やスピーチ生成の分野にも応用されています。ですが、end-to-endのやり方はその力が証明されてきた一方で、マシンパワーをたくさん必要とするやり方であることも知られています。例えばノイズ除去のために何千というニューロンに物凄い数のパラメータを設定することも可能ですが、コードや(ディープラーニングのパラメーターの)重みだけでも何10メガにもなってしまいます。もちろんそれ以外のマシンパワーも必要です。

そのため、私たちは別のアプローチを取ることにしました。基本となる従来のシグナルプロセッシングの部分は(どの道必要にもなりますし)そのまま残し、人がアートとしてやらなければならなかったトリッキーな部分だけ、ディープラーニングに学習させることにしました。私たちは他の研究とは異なり、リアルタイムでの適用を目標としていましたから、そもそもそんなに長い時間を分析している時間的余裕もありませんでした。せいぜ10ミリ秒が限界でした。
※ かなり意訳。途中疲れてきて端折りました。

問題の定義

アウトプットが極端に大きなものにならないよう、結果として極端に多い数のニューロンを扱わなくても済むよう、音声の生データSpectrumのデータを直接扱うことは避けることにしました。代わりにBark scaleと呼ばれる周波数帯(freqency band)を扱うことを考えました。Bark scaleは人が実際に認識できる周波数帯のことです。Sectralの480の周波数帯と比べると少ない全部で22個の周波数帯で住むことになります。

上記の図はOpus band と Bark scaleの比較です。
ここの部分はよく意味がわかりませんでしたが、まぁ、Bark scaleとは微妙に異なるOpus bandの方が良さそうだったのでそっちを使うことにしましたっていう意味だと理解しています。Opusは音声系の別のプロジェクトの名前です。

もちろん、たった22個の周波数帯のエネルギー値から音声そのものを復元できるわけではありません。ですが、各周波数帯毎のエネルギーの増減は予測でき、それは適用可能です。周波数帯毎にエネルギーを調整することでノイズを除去し、必要なシグナルはそのまま通すことが可能になります。

周波数帯域毎に増減を行うこのやり方にはいくつかのメリットがあります。
まず、パラメータの数が22個と少ないので、シンプルで高速に動作します。また、音声そのものを再生成するわけではないので、元々存在しなかったノイズを謝って作り出してしまう危険はありません。実際、アルゴリズムを適用した結果ノイズがなかったところに新たなノイズが発生してしまうことほど馬鹿らしいことはありませんからね。

この方式の欠点は、ノイズとピッチ変化の違いを十分に検知できないことです。でもこの問題には簡単な解決方法があります。
まず、出力が22個のの周波数帯に対応した22個の0〜1の値なので、周波数帯の数そのものを増やすのは得策ではありません。
そこで22個の周波数帯のエネルギー値のログを取った値を入力データとすることにしました。これはMFCC ( Mel Frequendcy Cepstral Coefficients)と類似の概念で、より人の耳の機能に沿ったデータになっています。
※ ここの部分は正確には理解できていないのですが、MFCCは音声を分析する際によく使う形式で、ソツーのスピーチ認識エンジンでも使っています。MFCCでも良いような気もしますが、Bark scaleの値を元にMFCC的な指標を計算し、それを入力値に使うことにしたという意味だと理解しています。

22個の値に加え、以下のデータを入力値に加えています。

  • The first and second derivatives of the first 6 coefficients across frames
  • The pitch period (1/frequency of the fundamental)
  • The pitch gain (voicing strength) in 6 bands
  • A special non-stationarity value that's useful for detecting speech (but beyond the scope of this demo)

最初の6フレームの第一、第二デリバティブとか、6つの周波数帯の声の強さとか、特徴量として有用と思われるデータを追加し、入力値は合計で42個になっています。
※ ここの詳細は若干僕にはわかりませんが、音声関連の開発や研究を重ねてきた中で培われたベストプラクティスってことだと思います。

ディープラーニングのアーキテクチャ

このディープラーニングのデザインは従来型のノイズ除去システムのアプローチに影響を受けています。重要な部分は3つのGRUレイヤーです。下記の図は周波数帯域のエネルギーの増減をどう計算しているのか、どう従来型のステップと対応させているのかを説明しています。ディープラーニングの世界では。ネットワークのデザインが人の思考に沿っている必要な必ずしもないのですが、まあ、僕はその方がしっくりくるのでそうしました。
※ 意訳です

RNNoiseのディープラーニングネットワークのデザインです

全てはデータ次第

ディープニューラルネットワークも時に酷い結果を返します。彼らは知っていることは良くできるのですが、知らないことに関しては時にひっくりするような間違いを犯します。というか、彼らは怠け者の学生さんのようなもので、隙あらば過学習を行ってしまいます。そのため、データの質と量はとても重量です。

意訳おわり。

ここから先は、そもそもノイズの入ったデータとノイズの入っていないデータを揃えるのは難しいので、綺麗な音声を集めて、それに人工的にノイズを加えてデータセットを作った話とか、最終的なスピードの最適化のために元々Pythonで書かれていたコードをCで書き直した話などが載っています。個人的にはPythonは使うけどCは使わないので、ソースコードにPythonのコードも残しておいてほしかったなーと思いましたが、まぁ仕方がありませんね。

RNNoiseのソースコードはこちら

で、実際にためしてみた

短い文章で試すとうまくいっている感じもします。

元々の音声1
RNNoise適用後の音声1
まぁ、元の音声にノイズが入っていないので、変化は見て取れません。

元々の音声2
RNNoise適用後の音声2
クリック音のような微妙なノイズが一瞬入っているのですが、除去はできていません。暫く続くようなノイズでないと、除去できないのか、それとも同様のノイズがデータベースに入っていないから除去できなかったのでしょうか。

では、外の騒音はどうでしょうか。
元々の音声3
RNNoise適用後の音声3
こちらは割りと良い感じに除去できています。

上記はいずれも5秒程度の短い音声だったので、1時間に及ぶ音声でも試してみました。
下記は、大きなファイルをRNNoiseにかけた後、ファイルサイズを節約したいので、初めの1分だけ切り抜いてみたものです。
元々の音声4
RNNoise適用後の音声4
全データを解析して、周波数帯域毎に一律で増減をかけているからでしょうか。今まで無かったところにノイズがうまれ、バックグラウンドミュージックも変な感じになってしまっています。

まぁ、RNNoiseは元々、ブラウザを使ったオンライン会議の音声をリアルタイムにクリアにするようなことを想定して開発されているので、長い音声を処理するのには向かないようですね。
でも、短い音声で、スピーチ認識の前処理として使うなら良いかもしれませんね。

自分のデータでトレーニングくらいやってみたかったのですが、Cのソースコードがよくわからず、内部をちゃんと理解できる気がしなかったので、今回は断念しました。
誰か、python&最新のtensorflow向けに書き直してくれないかなー。

記事が少しでもいいなと思ったらクラップを送ってみよう!
32
+1
@kouohhashiの技術ブログです。 主にAI、特に会話AIについて記事を書こうと思っています。

よく一緒に読まれている記事

0件のコメント

ブログ開設 or ログイン してコメントを送ってみよう
目次をみる

技術ブログをはじめよう

Qrunch(クランチ)は、ITエンジニアリングに携わる全ての人のための技術ブログプラットフォームです。

技術ブログを開設する

Qrunchでアウトプットをはじめよう

Qrunch(クランチ)は、ITエンジニアリングに携わる全ての人のための技術ブログプラットフォームです。

Markdownで書ける

ログ機能でアウトプットを加速

デザインのカスタマイズが可能

技術ブログ開設

ここから先はアカウント(ブログ)開設が必要です

英数字4文字以上
.qrunch.io
英数字6文字以上
ログインする