使用 SpeechT5 進行語音合成、識別和更多功能

HuggingFace發表於2023-03-14

我們很高興地宣佈,SpeechT5 現在可用於 ? Transformers (一個開源庫,提供最前沿的機器學習模型實現的開源庫)。

SpeechT5 最初見於微軟亞洲研究院的這篇論文 SpeechT5: Unified-Modal Encoder-Decoder Pre-Training for Spoken Language Processing。論文作者釋出的 官方倉庫 可在 Hugging Face Hub 上找到。

如果您想直接嘗試,這裡有一些在 Spaces 上的演示:

介紹

SpeechT5 不是一種,也不是兩種,而是一種架構中的三種語音模型。

它可以做:

  • 語音到文字,用於自動語音識別或說話人識別;
  • 文字轉語音,用於合成音訊;
  • 語音到語音,用於在不同語音之間進行轉換或執行語音增強。

SpeechT5 背後的主要思想是在文字到語音、語音到文字、文字到文字和語音到語音資料的混合體上預訓練單個模型。這樣,模型可以同時從文字和語音中學習。這種預訓練方法的結果是一個模型,該模型具有由文字和語音共享的隱藏表示的 統一空間

SpeechT5 的核心是一個常規的 Transformer 編碼器 - 解碼器 模型。就像任何其他 Transformer 一樣,編碼器 - 解碼器網路使用隱藏表示對序列到序列的轉換進行建模。這個 Transformer 骨幹對於所有 SpeechT5 任務都是一樣的。

為了使同一個 Transformer 可以同時處理文字和語音資料,新增了所謂的 pre-netspost-nets。 per-nets 的工作是將輸入文字或語音轉換為 Transformer 使用的隱藏表示。 post-nets 從 Transformer 獲取輸出並將它們再次轉換為文字或語音。

下圖展示了 SpeechT5 的架構 (摘自 原始論文)。

SpeechT5 architecture diagram

在預訓練期間,同時使用所有的 per-nets 和 post-nets 。預訓練後,整個編碼器 - 解碼器主幹在單個任務上進行微調。這種經過微調的模型僅使用特定於給定任務的 per-nets 和 post-nets 。例如,要將 SpeechT5 用於文字到語音轉換,您需要將文字編碼器 per-nets 交換為文字輸入,將語音解碼器 per-nets 和 post-nets 交換為語音輸出。

注意: 即使微調模型一開始使用共享預訓練模型的同一組權重,但最終版本最終還是完全不同。例如,您不能採用經過微調的 ASR 模型並換掉 per-nets 和 post-nets 來獲得有效的 TTS 模型。 SpeechT5 很靈活,但不是 那麼 靈活。

文字轉語音

SpeechT5 是我們新增到 ? Transformers 的 第一個文字轉語音模型,我們計劃在不久的將來新增更多的 TTS 模型。

對於 TTS 任務,該模型使用以下 per-net 和 post-net:

  • 文字編碼器 per-net 。一個文字嵌入層,將文字標記對映到編碼器期望的隱藏表示。類似於 BERT 等 NLP 模型中發生的情況。
  • 語音解碼器 per-net 。這將對數梅爾頻譜圖作為輸入,並使用一系列線性層將頻譜圖壓縮為隱藏表示。此設計取自 Tacotron 2 TTS 模型。
  • 語音解碼器 post-net 。這預測了一個殘差以新增到輸出頻譜圖中並用於改進結果,同樣來自 Tacotron 2。
    微調模型的架構如下所示。

SpeechT5 architecture for text-to-speech

以下是如何使用 SpeechT5 文字轉語音模型合成語音的完整示例。您還可以在 互動式 Colab 筆記本 中進行操作。

SpeechT5 在最新版本的 Transformers 中尚不可用,因此您必須從 GitHub 安裝它。還要安裝附加的依賴語句,然後重新啟動執行。

pip install git+https://github.com/huggingface/transformers.git
pip install sentencepiece

首先,我們從 Hub 載入 微調模型,以及用於標記化和特徵提取的處理器物件。我們將使用的類是 SpeechT5ForTextToSpeech

from transformers import SpeechT5Processor, SpeechT5ForTextToSpeech

processor = SpeechT5Processor.from_pretrained("microsoft/speecht5_tts")
model = SpeechT5ForTextToSpeech.from_pretrained("microsoft/speecht5_tts")

接下來,標記輸入文字。

inputs = processor(text="Don't count the days, make the days count.", return_tensors="pt")

SpeechT5 TTS 模型不限於為單個說話者建立語音。相反,它使用所謂的 Speaker Embeddings來捕捉特定說話者的語音特徵。我們將從 Hub 上的資料集中載入這樣一個 Speaker Embeddings。

from datasets import load_dataset
embeddings_dataset = load_dataset("Matthijs/cmu-arctic-xvectors", split="validation")

import torch
speaker_embeddings = torch.tensor(embeddings_dataset[7306]["xvector"]).unsqueeze(0)

Speaker Embeddings 是形狀為 (1, 512) 的張量。這個特定的 Speaker Embeddings 描述了女性的聲音。使用 此指令碼CMU ARCTIC 資料集獲得嵌入 /utils/prep_cmu_arctic_spkemb.py,任何 X-Vector 嵌入都應該有效。

現在我們可以告訴模型在給定輸入標記和 Speaker Embeddings 的情況下生成語音。

spectrogram = model.generate_speech(inputs["input_ids"], speaker_embeddings)

這會輸出一個形狀為 (140, 80) 的張量,其中包含對數梅爾譜圖。第一個維度是序列長度,它可能在執行之間有所不同,因為語音解碼器 per-net 總是對輸入序列應用 dropout。這為生成的語音增加了一些隨機變化。

要將預測的對數梅爾聲譜圖轉換為實際的語音波形,我們需要一個 聲碼器。理論上,您可以使用任何適用於 80-bin 梅爾聲譜圖的聲碼器,但為了方便起見,我們在基於 HiFi-GAN 的 Transformers 中提供了一個。 此聲碼器的權重,以及微調 TTS 模型的權重,由 SpeechT5 的原作者友情提供。

載入聲碼器與任何其他 ? Transformers 模型一樣簡單。

from transformers import SpeechT5HifiGan
vocoder = SpeechT5HifiGan.from_pretrained("microsoft/speecht5_hifigan")

要從頻譜圖中製作音訊,請執行以下操作:

with torch.no_grad():
    speech = vocoder(spectrogram)

我們還提供了一個快捷方式,因此您不需要製作頻譜圖的中間步驟。當您將聲碼器物件傳遞給 generate_speech 時,它會直接輸出語音波形。

speech = model.generate_speech(inputs["input_ids"], speaker_embeddings, vocoder=vocoder)

最後,將語音波形儲存到檔案中。 SpeechT5 使用的取樣率始終為 16 kHz。

import soundfile as sf
sf.write("tts_example.wav", speech.numpy(), samplerate=16000)

輸出聽起來像這樣 (下載音訊)

這就是 TTS 模型!使這個聲音好聽的關鍵是使用正確的 Speaker Embeddings。

您可以在 Spaces 上進行 互動式演示

語音轉語音的語音轉換

從概念上講,使用 SpeechT5 進行語音轉語音建模與文字轉語音相同。只需將文字編碼器 per-net 換成語音編碼器 per-net 即可。模型的其餘部分保持不變。

SpeechT5 architecture for speech-to-speech

語音編碼器 per-netwav2vec 2.0 中的特徵編碼模組相同。它由卷積層組成,這些卷積層將輸入波形下采樣為一系列音訊幀表示。

作為語音到語音任務的示例,SpeechT5 的作者提供了一個 微調檢查點 用於進行語音轉換。要使用它,首先從 Hub 載入模型。請注意,模型類現在是 SpeechT5ForSpeechToSpeech

from transformers import SpeechT5Processor, SpeechT5ForSpeechToSpeech

processor = SpeechT5Processor.from_pretrained("microsoft/speecht5_vc")
model = SpeechT5ForSpeechToSpeech.from_pretrained("microsoft/speecht5_vc")

我們需要一些語音音訊作為輸入。出於本示例的目的,我們將從 Hub 上的小型語音資料集載入音訊。您也可以載入自己的語音波形,只要它們是單聲道的並且使用 16 kHz 的取樣率即可。我們在這裡使用的資料集中的樣本已經採用這種格式。

from datasets import load_dataset
dataset = load_dataset("hf-internal-testing/librispeech_asr_demo", "clean", split="validation")
dataset = dataset.sort("id")
example = dataset[40]

接下來,對音訊進行預處理,使其採用模型期望的格式。

sampling_rate = dataset.features["audio"].sampling_rate
inputs = processor(audio=example["audio"]["array"], sampling_rate=sampling_rate, return_tensors="pt")

與 TTS 模型一樣,我們需要 Speaker Embeddings。這些描述了目標語音聽起來像什麼。

import torch
embeddings_dataset = load_dataset("Matthijs/cmu-arctic-xvectors", split="validation")
speaker_embeddings = torch.tensor(embeddings_dataset[7306]["xvector"]).unsqueeze(0)

我們還需要載入聲碼器以將生成的頻譜圖轉換為音訊波形。讓我們使用與 TTS 模型相同的聲碼器。

from transformers import SpeechT5HifiGan
vocoder = SpeechT5HifiGan.from_pretrained("microsoft/speecht5_hifigan")

現在我們可以透過呼叫模型的 generate_speech 方法來執行語音轉換。

speech = model.generate_speech(inputs["input_values"], speaker_embeddings, vocoder=vocoder)

import soundfile as sf
sf.write("speech_converted.wav", speech.numpy(), samplerate=16000)

更改為不同的聲音就像載入新的 Speaker Embeddings 一樣簡單。您甚至可以嵌入自己的聲音!

原始輸入下載 (下載)

轉換後的語音 (下載)

請注意,此示例中轉換後的音訊在句子結束前被切斷。這可能是由於兩個句子之間的停頓導致 SpeechT5 (錯誤地) 預測已經到達序列的末尾。換個例子試試,你會發現轉換通常是正確的,但有時會過早停止。

? 您可以進行 互動式演示

用於自動語音識別的語音轉文字

ASR 模型使用以下 pre-nets 和 post-net:

  • 語音編碼器 per-net。這是語音到語音模型使用的相同預網,由來自 wav2vec 2.0 的 CNN 特徵編碼器層組成。
  • 文字解碼器 per-net。與 TTS 模型使用的編碼器預網類似,它使用嵌入層將文字標記對映到隱藏表示中。 (在預訓練期間,這些嵌入在文字編碼器和解碼器預網之間共享。)
  • 文字解碼器 post-net。這是其中最簡單的一個,由一個線性層組成,該層將隱藏表示投射到詞彙表上的機率。
    微調模型的架構如下所示。

SpeechT5 architecture for speech-to-text

如果您之前嘗試過任何其他 ? Transformers 語音識別模型,您會發現 SpeechT5 同樣易於使用。最快的入門方法是使用流水線。

from transformers import pipeline
generator = pipeline(task="automatic-speech-recognition", model="microsoft/speecht5_asr")

作為語音音訊,我們將使用與上一節相同的輸入,任何音訊檔案都可以使用,因為流水線會自動將音訊轉換為正確的格式。

from datasets import load_dataset
dataset = load_dataset("hf-internal-testing/librispeech_asr_demo", "clean", split="validation")
dataset = dataset.sort("id")
example = dataset[40]

現在我們可以要求流水線處理語音並生成文字轉錄。

transcription = generator(example["audio"]["array"])

列印轉錄給出:

a man said to the universe sir i exist

聽起來完全正確! SpeechT5 使用的分詞器非常基礎,是字元級別工作。因此,ASR 模型不會輸出任何標點符號或大寫字母。

當然也可以直接使用模型類。首先,載入 微調模型 和處理器物件。該類現在是 SpeechT5ForSpeechToText

from transformers import SpeechT5Processor, SpeechT5ForSpeechToText

processor = SpeechT5Processor.from_pretrained("microsoft/speecht5_asr")
model = SpeechT5ForSpeechToText.from_pretrained("microsoft/speecht5_asr")

預處理語音輸入:

sampling_rate = dataset.features["audio"].sampling_rate
inputs = processor(audio=example["audio"]["array"], sampling_rate=sampling_rate, return_tensors="pt")

最後,告訴模型從語音輸入中生成文字標記,然後使用處理器的解碼功能將這些標記轉換為實際文字。

predicted_ids = model.generate(**inputs, max_length=100)
transcription = processor.batch_decode(predicted_ids, skip_special_tokens=True)

播放 語音到文字任務 的互動式演示。

結論

SpeechT5 是一個有趣的模型,因為與大多數其他模型不同,它允許您使用相同的架構執行多項任務。只有 per-net 和 post-net 發生變化。透過在這些組合任務上對模型進行預訓練,它在微調時變得更有能力完成每個單獨的任務。

目前我們只介紹了語音識別 (ASR)、語音合成 (TTS) 和語音轉換任務,但論文還提到該模型已成功用於語音翻譯、語音增強和說話者識別。如此廣泛的用途,前途不可估量!


原文: Speech Synthesis, Recognition, and More With SpeechT5

作者: Mathijs Hollemans

譯者: innovation64 (李洋)

審校、排版: zhongdongy (阿東)

相關文章