MMS
概述
MMS 模型由 Vineel Pratap、Andros Tjandra、Bowen Shi、Paden Tomasello、Arun Babu、Sayani Kundu、Ali Elkahky、Zhaoheng Ni、Apoorv Vyas、Maryam Fazel-Zarandi、Alexei Baevski、Yossi Adi、Xiaohui Zhang、Wei-Ning Hsu、Alexis Conneau 和 Michael Auli 在 将语音技术扩展到 1,000 多种语言 中提出。
论文摘要如下:
扩展语音技术的语言覆盖范围有可能为更多人提供获取信息的途径。然而,目前的语音技术仅限于大约 100 种语言,而世界上使用的语言超过 7,000 种。大规模多语言语音 (MMS) 项目将支持的语言数量增加了 10-40 倍(取决于任务)。主要成分是基于公开可用宗教文本的阅读的新数据集,以及有效利用自监督学习。我们构建了涵盖 1,406 种语言的预训练 wav2vec 2.0 模型、针对 1,107 种语言的单个多语言自动语音识别模型、针对相同数量语言的语音合成模型以及针对 4,017 种语言的语言识别模型。实验表明,我们的多语言语音识别模型将 Whisper 在 FLEURS 基准的 54 种语言上的词错误率降低了一半以上,同时在标记数据的小部分上进行训练。
以下是 MMS 项目中开源的不同模型。这些模型和代码最初是在 这里 发布的。我们已将它们添加到 transformers
框架中,使其更易于使用。
自动语音识别 (ASR)
ASR 模型检查点可以在以下位置找到:mms-1b-fl102、mms-1b-l1107、mms-1b-all。为了获得最佳准确率,请使用 mms-1b-all
模型。
技巧
- 所有 ASR 模型都接受与语音信号的原始波形相对应的浮点数组。原始波形应使用 Wav2Vec2FeatureExtractor 进行预处理。
- 这些模型是在使用连接主义时序分类 (CTC) 进行训练的,因此必须使用 Wav2Vec2CTCTokenizer 对模型输出进行解码。
- 可以通过 load_adapter() 为不同的语言加载不同的语言适配器权重。语言适配器仅包含大约 200 万个参数,因此可以在需要时高效地动态加载。
正在加载
默认情况下,MMS 加载英语的适配器权重。如果要加载其他语言的适配器权重,请确保指定 target_lang=<你的目标语言>
以及 "ignore_mismatched_sizes=True
。必须传递 ignore_mismatched_sizes=True
关键字以允许语言模型头根据指定语言的词汇表进行调整大小。同样,处理器也应该使用相同的目标语言加载
from transformers import Wav2Vec2ForCTC, AutoProcessor
model_id = "facebook/mms-1b-all"
target_lang = "fra"
processor = AutoProcessor.from_pretrained(model_id, target_lang=target_lang)
model = Wav2Vec2ForCTC.from_pretrained(model_id, target_lang=target_lang, ignore_mismatched_sizes=True)
你可以安全地忽略以下警告
Some weights of Wav2Vec2ForCTC were not initialized from the model checkpoint at facebook/mms-1b-all and are newly initialized because the shapes did not match: - lm_head.bias: found shape torch.Size([154]) in the checkpoint and torch.Size([314]) in the model instantiated - lm_head.weight: found shape torch.Size([154, 1280]) in the checkpoint and torch.Size([314, 1280]) in the model instantiated You should probably TRAIN this model on a down-stream task to be able to use it for predictions and inference.
如果你想使用 ASR 管道,你可以加载你选择的目标语言,如下所示
from transformers import pipeline
model_id = "facebook/mms-1b-all"
target_lang = "fra"
pipe = pipeline(model=model_id, model_kwargs={"target_lang": "fra", "ignore_mismatched_sizes": True})
推理
接下来,让我们看看如何在调用 ~PretrainedModel.from_pretrained
之后,如何在推理中运行 MMS 并更改适配器层。首先,我们使用 数据集 加载不同语言的音频数据。
from datasets import load_dataset, Audio
# English
stream_data = load_dataset("mozilla-foundation/common_voice_13_0", "en", split="test", streaming=True)
stream_data = stream_data.cast_column("audio", Audio(sampling_rate=16000))
en_sample = next(iter(stream_data))["audio"]["array"]
# French
stream_data = load_dataset("mozilla-foundation/common_voice_13_0", "fr", split="test", streaming=True)
stream_data = stream_data.cast_column("audio", Audio(sampling_rate=16000))
fr_sample = next(iter(stream_data))["audio"]["array"]
接下来,我们加载模型和处理器
from transformers import Wav2Vec2ForCTC, AutoProcessor
import torch
model_id = "facebook/mms-1b-all"
processor = AutoProcessor.from_pretrained(model_id)
model = Wav2Vec2ForCTC.from_pretrained(model_id)
现在我们处理音频数据,将处理后的音频数据传递给模型并转录模型输出,就像我们通常对 Wav2Vec2ForCTC 做的那样。
inputs = processor(en_sample, sampling_rate=16_000, return_tensors="pt")
with torch.no_grad():
outputs = model(**inputs).logits
ids = torch.argmax(outputs, dim=-1)[0]
transcription = processor.decode(ids)
# 'joe keton disapproved of films and buster also had reservations about the media'
现在我们可以将同一个模型保留在内存中,只需通过调用模型的便捷 load_adapter() 函数和标记器的 set_target_lang() 函数来切换语言适配器。我们将目标语言作为输入传递 - "fra"
表示法语。
processor.tokenizer.set_target_lang("fra")
model.load_adapter("fra")
inputs = processor(fr_sample, sampling_rate=16_000, return_tensors="pt")
with torch.no_grad():
outputs = model(**inputs).logits
ids = torch.argmax(outputs, dim=-1)[0]
transcription = processor.decode(ids)
# "ce dernier est volé tout au long de l'histoire romaine"
同样,语言可以被切换为所有其他支持的语言。请查看
processor.tokenizer.vocab.keys()
以查看所有支持的语言。
为了进一步提高 ASR 模型的性能,可以使用语言模型解码。有关更多详细信息,请参阅 此处 的文档。
语音合成 (TTS)
MMS-TTS 使用与 VITS 相同的模型架构,该架构已在 🤗 Transformers v4.33 中添加。MMS 为该项目中 1100 多种语言中的每种语言都训练了单独的模型检查点。所有可用的检查点都可以在 Hugging Face Hub 上找到:facebook/mms-tts,以及 VITS 下的推理文档。
推理
要使用 MMS 模型,请首先更新到最新版本的 Transformers 库
pip install --upgrade transformers accelerate
由于 VITS 中的基于流的模型是非确定性的,因此最好设置一个种子以确保输出的可重复性。
- 对于使用罗马字母的语言,例如英语或法语,可以直接使用标记器来预处理文本输入。以下代码示例使用 MMS-TTS 英语检查点运行前向传递
import torch
from transformers import VitsTokenizer, VitsModel, set_seed
tokenizer = VitsTokenizer.from_pretrained("facebook/mms-tts-eng")
model = VitsModel.from_pretrained("facebook/mms-tts-eng")
inputs = tokenizer(text="Hello - my dog is cute", return_tensors="pt")
set_seed(555) # make deterministic
with torch.no_grad():
outputs = model(**inputs)
waveform = outputs.waveform[0]
生成的波形可以保存为 .wav
文件
import scipy
scipy.io.wavfile.write("synthesized_speech.wav", rate=model.config.sampling_rate, data=waveform)
或在 Jupyter Notebook/Google Colab 中显示
from IPython.display import Audio
Audio(waveform, rate=model.config.sampling_rate)
对于某些使用非罗马字母的语言,例如阿拉伯语、普通话或印地语,需要使用 uroman
perl 包将文本输入预处理为罗马字母。
你可以通过检查预训练的 tokenizer
的 is_uroman
属性来查看你的语言是否需要 uroman
包
from transformers import VitsTokenizer
tokenizer = VitsTokenizer.from_pretrained("facebook/mms-tts-eng")
print(tokenizer.is_uroman)
如果需要,你应该在将文本输入传递给 VitsTokenizer
之前将 uroman 包应用于文本输入,因为目前标记器本身不支持执行预处理。
为此,首先将 uroman 存储库克隆到你的本地机器,并将 bash 变量 UROMAN
设置为本地路径
git clone https://github.com/isi-nlp/uroman.git
cd uroman
export UROMAN=$(pwd)
然后,你可以使用以下代码片段预处理文本输入。你可以选择使用 bash 变量 UROMAN
来指向 uroman 存储库,或者你可以将 uroman 目录作为参数传递给 uromanize
函数
import torch
from transformers import VitsTokenizer, VitsModel, set_seed
import os
import subprocess
tokenizer = VitsTokenizer.from_pretrained("facebook/mms-tts-kor")
model = VitsModel.from_pretrained("facebook/mms-tts-kor")
def uromanize(input_string, uroman_path):
"""Convert non-Roman strings to Roman using the `uroman` perl package."""
script_path = os.path.join(uroman_path, "bin", "uroman.pl")
command = ["perl", script_path]
process = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# Execute the perl command
stdout, stderr = process.communicate(input=input_string.encode())
if process.returncode != 0:
raise ValueError(f"Error {process.returncode}: {stderr.decode()}")
# Return the output as a string and skip the new-line character at the end
return stdout.decode()[:-1]
text = "이봐 무슨 일이야"
uromanized_text = uromanize(text, uroman_path=os.environ["UROMAN"])
inputs = tokenizer(text=uromanized_text, return_tensors="pt")
set_seed(555) # make deterministic
with torch.no_grad():
outputs = model(inputs["input_ids"])
waveform = outputs.waveform[0]
技巧
- MMS-TTS 检查点是在小写、不带标点的文本上训练的。默认情况下,
VitsTokenizer
通过删除所有大小写和标点符号来规范化输入,以避免将词汇表外的字符传递给模型。因此,模型对大小写和标点符号不敏感,因此在文本提示中应避免这些符号。你可以在调用标记器时将normalize=False
设置为禁用规范化,但这会导致意外行为,不建议这样做。 - 可以通过将属性
model.speaking_rate
设置为选定的值来改变语速。同样,噪声的随机性由model.noise_scale
控制
import torch
from transformers import VitsTokenizer, VitsModel, set_seed
tokenizer = VitsTokenizer.from_pretrained("facebook/mms-tts-eng")
model = VitsModel.from_pretrained("facebook/mms-tts-eng")
inputs = tokenizer(text="Hello - my dog is cute", return_tensors="pt")
# make deterministic
set_seed(555)
# make speech faster and more noisy
model.speaking_rate = 1.5
model.noise_scale = 0.8
with torch.no_grad():
outputs = model(**inputs)
语言识别 (LID)
根据它们可以识别的语言数量,提供了不同的 LID 模型 - 126、256、512、1024、2048、4017。
推理
首先,我们安装 transformers 和其他一些库
pip install torch accelerate datasets[audio] pip install --upgrade transformers
接下来,我们通过 datasets
加载一些音频样本。确保音频数据采样到 16000 kHz。
from datasets import load_dataset, Audio
# English
stream_data = load_dataset("mozilla-foundation/common_voice_13_0", "en", split="test", streaming=True)
stream_data = stream_data.cast_column("audio", Audio(sampling_rate=16000))
en_sample = next(iter(stream_data))["audio"]["array"]
# Arabic
stream_data = load_dataset("mozilla-foundation/common_voice_13_0", "ar", split="test", streaming=True)
stream_data = stream_data.cast_column("audio", Audio(sampling_rate=16000))
ar_sample = next(iter(stream_data))["audio"]["array"]
接下来,我们加载模型和处理器
from transformers import Wav2Vec2ForSequenceClassification, AutoFeatureExtractor
import torch
model_id = "facebook/mms-lid-126"
processor = AutoFeatureExtractor.from_pretrained(model_id)
model = Wav2Vec2ForSequenceClassification.from_pretrained(model_id)
现在我们处理音频数据,将处理后的音频数据传递给模型以将其分类为一种语言,就像我们通常对 Wav2Vec2 音频分类模型(例如 ehcalabres/wav2vec2-lg-xlsr-en-speech-emotion-recognition)所做的那样
# English
inputs = processor(en_sample, sampling_rate=16_000, return_tensors="pt")
with torch.no_grad():
outputs = model(**inputs).logits
lang_id = torch.argmax(outputs, dim=-1)[0].item()
detected_lang = model.config.id2label[lang_id]
# 'eng'
# Arabic
inputs = processor(ar_sample, sampling_rate=16_000, return_tensors="pt")
with torch.no_grad():
outputs = model(**inputs).logits
lang_id = torch.argmax(outputs, dim=-1)[0].item()
detected_lang = model.config.id2label[lang_id]
# 'ara'
要查看检查点支持的所有语言,可以按如下方式打印语言 ID
processor.id2label.values()
音频预训练模型
用于 ASR 的 MMS 架构基于 Wav2Vec2 模型,有关如何使用模型对各种下游任务进行微调的更多详细信息,请参考 Wav2Vec2 的文档页面。
MMS-TTS 使用与 VITS 相同的模型架构,有关 API 参考,请参考 VITS 的文档页面。