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多种语言中提出。
论文的摘要如下:
扩展语音技术的语言覆盖范围有可能为更多人提供信息获取的途径。 然而,当前的语音技术仅限于大约一百种语言,这只是全球超过7,000种语言中的一小部分。 大规模多语言语音(MMS)项目将支持的语言数量增加了10到40倍,具体取决于任务。 主要因素是基于公开宗教文本阅读的新数据集以及有效利用自监督学习。我们构建了覆盖1,406种语言的预训练wav2vec 2.0模型, 一个支持1,107种语言的多语言自动语音识别模型,相同数量的语音合成模型, 以及一个支持4,017种语言的语言识别模型。 实验表明,我们的多语言语音识别模型在FLEURS基准测试的54种语言上将Whisper的词错误率降低了一半以上,同时仅使用了少量标注数据进行训练。
以下是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进行推理并更改适配器层。
首先,我们使用Datasets加载不同语言的音频数据。
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()
音频预训练模型
预训练模型有两种不同尺寸可供选择 - 300M , 1Bil.
ASR架构的MMS基于Wav2Vec2模型,有关如何使用模型进行各种下游任务的微调的更多详细信息,请参阅Wav2Vec2的文档页面。
MMS-TTS 使用与 VITS 相同的模型架构,请参考 VITS 的文档页面 获取 API 参考。