前言
本筆記參考的課程是李宏毅老師的自然語言處理
課程Link:https://aistudio.baidu.com/aistudio/education/lessonvideo/1000466
Voice Conversion
什麼是語音轉換?
語音轉換就是将一段語音轉換成另一段語音,内容保持不變。
比如,最常見的應用是變聲器。此外,也可以實作語音降噪,語音加噪等其它應用場景。
Categories
語音資料可分為兩個種類:Parallel Data和Unparallel Data
Parallel Data即一對對的資料集,兩段相同内容的語音由不同音源來發出。
Unparallel Data即不同内容的語音。
Parallel Data比較難擷取到足夠的資料,是以,後續模型采用的均是Unparallel Data。
Methods
語音轉換的主要方法分兩大類:Feature Disentangle 和 Direct Transformation
Feature Disentangle
Feature Disentangle,顧名思義是将特征進行提取分離。
例如,下圖中,将兩段語音分别提取内容資訊和說話人的特征資訊,将提取出的資訊進行結合,就達到了替換聲音的說出相同内容的效果。
想法很美好,但是要提取得非常幹淨是比較困難的。
那麼,下面就要訓練兩個編碼器,因為是非對稱的資訊,沒有GroundTruth無法訓練,是以就直接用一段語音進行訓練。
圖中,輸入一段語音,經過Encoder和Decoder之後,将重塑的語音和之前的語音比較,越接近越好,這樣就能訓練。然而,存在的一個問題是,怎麼保證Content Encoder和Speaker Encoder能夠提取出對應的内容呢,因為像這樣兩個Encoder的地位是一樣的,提取的特征肯定會出現混雜。
有一種解決方式是不用Speaker Encoder,輸入對應說話人的獨熱向量。
這種方法必須提前知道所有語音庫中有多少個說話人,并且每一段輸入的語音必須單獨隻有一個說話人。是以,仍然有局限性。
另一種解決方式是保持Speaker Encoder不變,在Content Encoder後面加上一個Speaker Classifier作為鑒别器(Discriminator)。在訓練Content Encoder的過程中,同時訓練Speaker Classifer,形成對抗結構。如果Content Encoder的效果好,那麼Speaker Classifer的效果就越差。利用Speaker Classifer的效果來反推Content Encoder的效果,是以目标是Speaker Classifer的準确率越低越好。
在這個思路的基礎上,還能做進一步改進,在Content Encoder後面加一層instance normalization,如下圖所示:
IN的作用就類似于圖像領域的BN層,下圖中,對于一段語音信号,使用一維卷積進行特征提取,經過IN後,将每個Filter提取出資訊減去均值并除以方差,這樣就将每個channel标準化,均值為0,方差為1。
為什麼這樣做可以過濾說話人的特征資訊呢?舉個例子,比如男生的聲音普遍是低頻信号,女生的聲音普遍是高頻信号,這樣标準化之後,就将兩者放在同一個範圍内,有效濾除了說話者的聲音特征。
利用Content Encoder的分類器,可以來判斷這樣操作是否有效,如圖所示,有IN層的準确率為37.5%,沒有IN層的準确率為65.8%,前面說過,這個準确率要越小,代表Content Encoder越有效。資料說明,加入IN層是work的。
當然,還能進一步優化,比如,在Decoder後面加一層AdaIN。
AdaIN的步驟是先将Decoder出來的結果标準化(IN),然後再将Speaker Encoder的結果用下圖中的公式進行添加。
這樣操作的原因也不難了解,因為直接将兩個Encoder的結果混雜輸出,效果不一定好,這樣處理能夠優化輸出的結果。
這套方法在訓練階段似乎是可行的,但在測試時,會産生一個新的問題。
如圖所示,訓練時兩個Encoder是采用的相同的說話人或者是同一段音頻,但是在測試時,我們需要的目的是用A的語音來替換B的内容,這和訓練時的場景并不一緻,進而會出現導緻結果不好(Low Quality)
于是,為解決這一問題,就有了2nd Stage Training方法。
2nd Stage Training是保持訓練場景和測試場景一緻,即Content Encoder和Speaker Encoder是不同的說話人(下圖中Speaker Encoder簡化成了獨熱碼)。然而,前面也提到過,這樣做的話Decoder出來的結果是沒有Groundtruth的,無法直接進行監督訓練。
那麼,2nd Stage Training的辦法是在Decoder後面添加一個判别器(Discriminator)和一個分類器(Speaker Classifier),判别器用來判斷輸出的語音是否像真人,分類器用來判斷輸出語音屬于哪個說話人。但是這樣仍然容易造成模型輸出不穩定的情況,是以給Decoder打上一個更新檔(Patcher),Patcher輸入輸出和Decoder一樣,這樣将兩者的輸出加在一起,可以增強模型的穩定性。
Direct Transformation
除了分離特征的方法外,還有一種思路是借鑒圖像領域的生成對抗網絡(Gan),進而直接進行轉換。
Cycle GAN
Cycle GAN的結構如下圖所示:
圖中藍色代表說話人X的語音信号,紅色代表說話人Y的語音信号。
首先輸入X到判生成器Gx->y中,生成器會将X的信号轉換成Y,然後将該信号和真實的Y信号來一起輸入到判别器Dy中,讓其分辨輸入的語音是否真正屬于Y,假如判别器無法正确判别,說明生成器的效果不錯,能夠“騙過”判别器。
值得注意的是,在生成器Gx->y後又加了一個生成器Gy->x,重新将信号還原成X,再比較輸入輸出X的接近程度。這樣做的目的是確定生成器Gx->y是正常工作的。如果沒有這個步驟,可能生成器Gx->y會“偷懶”,一直生成同一個Y語音,這不是我們想要的。
其次,Gx->y下面還有一對信号,輸入Y,之後再輸出Y,然後比較兩者的接近程度,正常情況下,不應該發生變化,這樣做是為了模型訓練的穩定性。
Cycle GAN中的X和Y是對稱的,也就是說,将其互換,也可以work。
StarGAN
CycleGAN能夠比較好得處理兩個說話者的情況,如果說話者增多,假如有N個說話者,每兩個人之間就需要2個生成器,總共需要N x (N-1)個生成器。
StarGAN的主要思想是把每個說話者轉變成一個向量的形式,這樣就可以在同一個模型中來表示多個說話者。它的結構如圖中下半部分所示:
從圖中可以看出StarGAN的結構和CycleGAN幾乎一樣,不同之處僅在于輸入的speaker向量可以選擇多個。
Blow
還有另一種思路不是利用Gan,而是利用流模型(flow-based model)來做語音轉換,這裡不作詳細展開。