RVCの構造についてのメモ

2023/06/18に公開

はじめに

こんにちは、nadareです。
機械学習エンジニアで、普段はレコメンド・検索関連のお仕事をしています。いろんな競技プログラミングが好きです。

Retrieval-based-Voice-Conversion(以下RVC)という技術に関心を持ち、本家Retrieval-based-Voice-Conversion-WebUIddPn08さん版RVC-WebUIVC ClientにPR投げつつ勉強しています。

最近は自分でRVCのモデル構造弄って遊んでいます。最近勉強した技術の実験場みたいな感じなので本家にPRださないとは思いますが、その過程でRVCの学習回りについていろいろ分かってきたので自分用にまとめたいと思います。

RVCの構成

RVCはTTS(text to speech)とVC(Voice Convertaion)のモデルであるVITSをベースに、VCに特化させ『模倣対象の音声だけ』で学習ができるようにしたモデルです。パーツはざっくり以下の三つからなります。

  • 音声の変換を行うGenerator
    • 音声を特徴量に変換するEncoder
    • 話者の特徴量を明示的に与えるflow
    • 特徴量を音声に変換するSynthesizer
  • 音声が本物か合成化を見分けるDiscriminator

Generator

Generatorは以下の四つのパーツからできています。

  • 特徴量を抽出するEncoder
    • 予測時に用いるHuBERT-base + ANN + Transformer のenc_p
    • 学習時に用いるWaveNetのenc_q
  • 話者の特徴量を明示的に与えるflow
  • 特徴量を音声に変換するSynthesizer

Encoder

事前学習済みHuBERT

EncoderはWaveNetのenc_qをTeacher、Transformerのenc_pをStudentとして学習を行います。Studentの方がモデルの大きい珍しい形式ですが、学習時はTeacherの特徴量を用いたうえでkl_lossを用いてTeacherとStudentの出力を近づけています。RVC以前のVCが事前学習済みのHuBERTではなく別のものを使っていた名残な気がしていますが、これのおかげでEncoderのHuBERTのモデルを変えても後段が崩れずファインチューニングができていそうです。

Studentのenc_pは事前学習済みのHuBERTとTransformerから構成されています。事前学習済みのHuBERTに対し本家RVCではContentVecを用いており、ddPn08さん版RVC-WebUIではオプションとしてrinna社の公開している日本語HuBERTを用いています。事前学習済みのHuBERTはファインチューニングを行わずそのままの特徴量を使います。

  • ContentVecはLibriSpeechという約1000hの英語のデータセットで学習したHuBERT-baseを元に、話者性を除いた特徴量を得られるよう同データセットで学習しなおしたモデルです。HuBERTに比べてボイスチェンジャーの用途に特化させています。
  • 日本語HuBERTはReazonSpeechという約16000hの日本語の音声で学習したHuBERT-baseです。元のHuBERTに比べてより日本語に特化した特徴量を得ることができます。

近似近傍探索による特徴量の検索

HuBERTで作成した特徴量について、予測時は学習データから作ったHuBERTのembeddingから近いものを検索して混ぜます。これにより変換先の声質に合わせることができ、特に日本語HuBERTのような話者性を除かないHuBERTを用いたときに顕著に効果を発揮します。
検索対象のEmbeddingは学習データを全部用いるため、学習データの量が多くなるほど検索に時間と負荷がかかるのですが、ddPn08さんのRVC-WebUIではkmeansにより一定サイズに圧縮する機能を追加しています。全部そのまま使った場合よりも変換できる表現の幅は狭くなりますが、検索対象のindexのサイズを大きく減らし、検索速度もわずかに上げることができます。

相対位置を考慮したTransformer

後段のTransFormerはSelf AttentionのMultiHead Attentionを採用したTransformerを用いています。attentionの計算はdotproduct + relative positional encodingを用いています。(relative positional encodingでは10msec単位を基本として、前後100msecまでを特別な値として重みを与えます)

flow

WaveNetの各層で話者のembeddingから変換した特徴量を考慮します。学習時は話者の特徴量を追加し、推論時は話者の特徴量を除くようにしているのですが、このあたりは私の理解が追い付いていないです。

Synthesizer

SynthesizerはNSF-GANとHiFi-GANの要素が使われています。NSF-GANはピッチから周波数に合わせたノイズ付きのサイン波を合成して特徴量に使うもので、これとEncoderから作成した特徴量をアップサンプリングしていくHiFi-GANを組み合わせています。

Discriminator

Discriminatorは1DのWaveNetに似たDiscriminatorSとperiodを指定しperiodのmodごとに分ける複数のDiscriminatorPを合わせたMultiPeriodDiscriminator(MPD)が用いられています。RVC v2ではPeriodの数が増え、より精度よく識別ができるようになりました。Discriminatorは元の音声を1、合成音声を0として予測を出力するよう学習しますが、lossにおいてはsigmoidを使ってcross entropyをとるのではなく、元の音声は(1 - y)^2、合成音声は(y - 1)^2を最小化するように学習しています。これによりdiscriminatorが強くなりすぎて勾配が得られなくなってしまうのを防いでいます。(LSGANのテクニックっぽい)

その他学習のテクニック

特徴量の事前計算

RVCでは学習時にepoch毎に不変な特徴量は事前計算し保存しておくことで計算効率を上げています。具体的には音声の分割、ピッチの抽出、HuBERTの特徴量の抽出を事前に行い効率的に学習を進めています。

混合精度による学習

混合精度はモデルのパラメータをfloat32で保存し、訓練時は一部の計算をfloat16に置き換えることで高速化を行う技術です。float16なので若干計算が不安定になりますが、ファインチューニングの範囲ではうまくいくようです。

AI声づくり技術研究会

Discussion