# MMS

## Visão geral

O modelo MMS foi proposto em [Scaling Speech Technology to 1,000+ Languages](https://huggingface.co/papers/2305.13516) por 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

O resumo do artigo é o seguinte:

*Expandir a cobertura de idiomas da tecnologia de fala tem o potencial de melhorar o acesso à informação para muitas mais pessoas. No entanto, a tecnologia de fala atual é restrita a cerca de cem idiomas, uma pequena fração dos mais de 7.000 idiomas falados ao redor do mundo. O projeto Massively Multilingual Speech (MMS) aumenta o número de idiomas suportados em 10 a 40 vezes, dependendo da tarefa. Os principais ingredientes são um novo dataset baseado em leituras de textos religiosos de domínio público e o aproveitamento eficaz do aprendizado auto-supervisionado. Construímos modelos pré-treinados wav2vec 2.0 cobrindo 1.406 idiomas, um único modelo multilíngue de reconhecimento automático de fala para 1.107 idiomas, modelos de síntese de fala para o mesmo número de idiomas, bem como um modelo de identificação de idioma para 4.017 idiomas. Experimentos mostram que nosso modelo multilíngue de reconhecimento de fala reduz mais pela metade a taxa de erro de palavras do Whisper em 54 idiomas do benchmark FLEURS, sendo treinado em uma pequena fração dos dados rotulados.*

Aqui estão os diferentes modelos de código aberto no projeto MMS. Os modelos e o código foram originalmente lançados [aqui](https://github.com/facebookresearch/fairseq/tree/main/examples/mms). Adicionamos-os ao framework `transformers`, tornando-os mais fáceis de usar.

### Reconhecimento Automático de Fala (ASR)

Os checkpoints dos modelos de ASR podem ser encontrados aqui: [mms-1b-fl102](https://huggingface.co/facebook/mms-1b-fl102), [mms-1b-l1107](https://huggingface.co/facebook/mms-1b-l1107), [mms-1b-all](https://huggingface.co/facebook/mms-1b-all). Para a melhor precisão, use o modelo `mms-1b-all`.

Dicas:

- Todos os modelos de ASR aceitam um array de float correspondente à forma de onda bruta do sinal de fala. A forma de onda bruta deve ser pré-processada com [Wav2Vec2FeatureExtractor](/docs/transformers/main/pt/model_doc/wav2vec2#transformers.Wav2Vec2FeatureExtractor).
- Os modelos foram treinados usando classificação temporal conexionista (CTC), portanto a saída do modelo precisa ser decodificada usando [Wav2Vec2CTCTokenizer](/docs/transformers/main/pt/model_doc/wav2vec2#transformers.Wav2Vec2CTCTokenizer).
- Você pode carregar pesos de adaptadores de linguagem diferentes para idiomas distintos por meio de [load_adapter()](/docs/transformers/main/pt/model_doc/wav2vec2#transformers.Wav2Vec2ForCTC.load_adapter). Os adaptadores de linguagem consistem em apenas cerca de 2 milhões de parâmetros e, portanto, podem ser carregados de forma eficiente sob demanda.

#### Carregando

Por padrão, o MMS carrega os pesos do adaptador para o inglês. Se você deseja carregar os pesos do adaptador de outro idioma, certifique-se de especificar `target_lang=<your-chosen-target-lang>` bem como `"ignore_mismatched_sizes=True`. A palavra-chave `ignore_mismatched_sizes=True` precisa ser passada para permitir que a cabeça do modelo de linguagem seja redimensionada de acordo com o vocabulário do idioma especificado. Da mesma forma, o processador deve ser carregado com o mesmo idioma de destino

```python
from transformers import AutoProcessor, Wav2Vec2ForCTC

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, device_map="auto")
```

Você pode ignorar com segurança um aviso como:

```text
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.
```

Se você deseja usar o pipeline de ASR, pode carregar o idioma de destino escolhido da seguinte forma:

```python
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})
```

#### Inferência

A seguir, vamos ver como podemos executar o MMS em inferência e alterar as camadas de adaptador depois de ter chamado `~PretrainedModel.from_pretrained` Primeiro, carregamos dados de áudio em diferentes idiomas usando o [Datasets](https://github.com/huggingface/datasets).

```python
from datasets import Audio, load_dataset

# 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"]
```

Em seguida, carregamos o modelo e o processador

```python

from transformers import AutoProcessor, Wav2Vec2ForCTC

model_id = "facebook/mms-1b-all"

processor = AutoProcessor.from_pretrained(model_id)
model = Wav2Vec2ForCTC.from_pretrained(model_id, device_map="auto")
```

Agora processamos os dados de áudio, passamos os dados de áudio processados para o modelo e transcrevemos a saída do modelo, da mesma forma que normalmente fazemos para [Wav2Vec2ForCTC](/docs/transformers/main/pt/model_doc/wav2vec2#transformers.Wav2Vec2ForCTC).

```py
inputs = processor(en_sample, sampling_rate=16_000, return_tensors="pt").to(model.device)

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'
```

Agora podemos manter o mesmo modelo em memória e simplesmente alternar os adaptadores de idioma chamando a conveniente função [load_adapter()](/docs/transformers/main/pt/model_doc/wav2vec2#transformers.Wav2Vec2ForCTC.load_adapter) para o modelo e [set_target_lang()](/docs/transformers/main/pt/model_doc/wav2vec2#transformers.Wav2Vec2CTCTokenizer.set_target_lang) para o tokenizer. Passamos o idioma de destino como entrada - `"fra"` para francês.

```py
processor.tokenizer.set_target_lang("fra")
model.load_adapter("fra")

inputs = processor(fr_sample, sampling_rate=16_000, return_tensors="pt").to(model.device)

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"
```

Da mesma forma, o idioma pode ser alterado para todos os outros idiomas suportados. Por favor, consulte:

```py
processor.tokenizer.vocab.keys()
```

para ver todos os idiomas suportados.

Para melhorar ainda mais o desempenho dos modelos de ASR, é possível utilizar a decodificação com modelo de linguagem. Consulte a documentação [aqui](https://huggingface.co/facebook/mms-1b-all) para mais detalhes.

### Síntese de Fala (TTS)

O MMS-TTS utiliza a mesma arquitetura de modelo que o VITS, que foi adicionado ao 🤗 Transformers na v4.33. O MMS treina um checkpoint de modelo separado para cada um dos mais de 1100 idiomas do projeto. Todos os checkpoints disponíveis podem ser encontrados no Hugging Face Hub: [facebook/mms-tts](https://huggingface.co/models?sort=trending&search=facebook%2Fmms-tts), e a documentação de inferência sob [VITS](./vits).

#### Inferência

Para usar o modelo MMS, primeiro atualize para a versão mais recente da biblioteca Transformers:

```bash
pip install --upgrade transformers accelerate
```

Como o modelo baseado em fluxo no VITS é não determinístico, é uma boa prática definir uma semente para garantir a reprodutibilidade das saídas.

- Para idiomas com alfabeto romano, como inglês ou francês, o tokenizer pode ser usado diretamente para
pré-processar as entradas de texto. O exemplo de código a seguir executa uma passagem direta usando o checkpoint em inglês do MMS-TTS:

```python
import torch

from transformers import VitsModel, VitsTokenizer, set_seed

tokenizer = VitsTokenizer.from_pretrained("facebook/mms-tts-eng")
model = VitsModel.from_pretrained("facebook/mms-tts-eng", device_map="auto")

inputs = tokenizer(text="Hello - my dog is cute", return_tensors="pt").to(model.device)

set_seed(555)  # make deterministic

with torch.no_grad():
   outputs = model(**inputs)

waveform = outputs.waveform[0]
```

A forma de onda resultante pode ser salva como um arquivo `.wav`:

```python
import scipy

scipy.io.wavfile.write("synthesized_speech.wav", rate=model.config.sampling_rate, data=waveform)
```

Ou exibido em um Jupyter Notebook / Google Colab:

```python
from IPython.display import Audio

Audio(waveform, rate=model.config.sampling_rate)
```

Para determinados idiomas com alfabetos não romanos, como árabe, mandarim ou hindi, o pacote perl [`uroman`](https://github.com/isi-nlp/uroman) é necessário para pré-processar os textos de entrada para o alfabeto romano.

Você pode verificar se precisa do pacote `uroman` para o seu idioma inspecionando o atributo `is_uroman` do `tokenizer` pré-treinado:

```python
from transformers import VitsTokenizer

tokenizer = VitsTokenizer.from_pretrained("facebook/mms-tts-eng")
print(tokenizer.is_uroman)
```

Se necessário, você deve aplicar o pacote uroman às suas entradas de texto **antes** de passá-las para o `VitsTokenizer`, pois, atualmente, o tokenizer não suporta a execução do pré-processamento por conta própria.

Para fazer isso, primeiro clone o repositório uroman para sua máquina local e defina a variável bash `UROMAN` para o caminho local:

```bash
git clone https://github.com/isi-nlp/uroman.git
cd uroman
export UROMAN=$(pwd)
```

Em seguida, você pode pré-processar a entrada de texto usando o seguinte trecho de código. Você pode usar a variável bash `UROMAN` para apontar para o repositório uroman, ou passar o diretório uroman como argumento para a função `uromanize`:

```python
import os
import subprocess

import torch

from transformers import VitsModel, VitsTokenizer, set_seed

tokenizer = VitsTokenizer.from_pretrained("facebook/mms-tts-kor")
model = VitsModel.from_pretrained("facebook/mms-tts-kor", device_map="auto")

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").to(model.device)

set_seed(555)  # make deterministic
with torch.no_grad():
   outputs = model(inputs["input_ids"])

waveform = outputs.waveform[0]
```

**Dicas:**

* Os checkpoints do MMS-TTS são treinados em texto em minúsculas e sem pontuação. Por padrão, o `VitsTokenizer` *normaliza* as entradas removendo qualquer capitalização e pontuação, para evitar passar caracteres fora do vocabulário para o modelo. Portanto, o modelo é agnóstico em relação à capitalização e à pontuação, então esses elementos devem ser evitados no prompt de texto. Você pode desabilitar a normalização definindo `normalize=False` na chamada ao tokenizer, mas isso levará a um comportamento inesperado e é desencorajado.
* A taxa de fala pode ser variada definindo o atributo `model.speaking_rate` para um valor escolhido. Da mesma forma, a aleatoriedade do ruído é controlada por `model.noise_scale`:

```python
import torch

from transformers import VitsModel, VitsTokenizer, set_seed

tokenizer = VitsTokenizer.from_pretrained("facebook/mms-tts-eng")
model = VitsModel.from_pretrained("facebook/mms-tts-eng", device_map="auto")

inputs = tokenizer(text="Hello - my dog is cute", return_tensors="pt").to(model.device)

# 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)
```

### Identificação de Idioma (LID)

Estão disponíveis diferentes modelos de LID com base no número de idiomas que podem reconhecer - [126](https://huggingface.co/facebook/mms-lid-126), [256](https://huggingface.co/facebook/mms-lid-256), [512](https://huggingface.co/facebook/mms-lid-512), [1024](https://huggingface.co/facebook/mms-lid-1024), [2048](https://huggingface.co/facebook/mms-lid-2048), [4017](https://huggingface.co/facebook/mms-lid-4017).

#### Inferência

Primeiro, instalamos o transformers e algumas outras bibliotecas

```bash
pip install torch accelerate datasets[audio]
pip install --upgrade transformers
````

Em seguida, carregamos alguns exemplos de áudio por meio de `datasets`. Certifique-se de que os dados de áudio sejam amostrados a 16000 kHz.

```python
from datasets import Audio, load_dataset

# 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"]
```

Em seguida, carregamos o modelo e o processador

```python

from transformers import AutoFeatureExtractor, Wav2Vec2ForSequenceClassification

model_id = "facebook/mms-lid-126"

processor = AutoFeatureExtractor.from_pretrained(model_id)
model = Wav2Vec2ForSequenceClassification.from_pretrained(model_id, device_map="auto")
```

Agora processamos os dados de áudio e passamos os dados de áudio processados para o modelo classificá-los em um idioma, da mesma forma que normalmente fazemos para modelos de classificação de áudio Wav2Vec2, como [ehcalabres/wav2vec2-lg-xlsr-en-speech-emotion-recognition](https://huggingface.co/harshit345/xlsr-wav2vec-speech-emotion-recognition)

```py
# English
inputs = processor(en_sample, sampling_rate=16_000, return_tensors="pt").to(model.device)

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").to(model.device)

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'
```

Para ver todos os idiomas suportados de um checkpoint, você pode imprimir os ids de idioma da seguinte forma:

```py
processor.id2label.values()
```

### Modelos pré-treinados de áudio

Modelos pré-treinados estão disponíveis em dois tamanhos diferentes - [300M](https://huggingface.co/facebook/mms-300m) , [1Bil](https://huggingface.co/facebook/mms-1b).

A arquitetura do MMS para ASR é baseada no modelo Wav2Vec2. Consulte a [página de documentação do Wav2Vec2](./wav2vec2) para mais detalhes sobre como fazer o ajuste fino com modelos para diversas tarefas de nível inferior.

O MMS-TTS usa a mesma arquitetura de modelo que o VITS; consulte a [página de documentação do VITS](./vits) para referência da API.

