# MMS

## Resumen

El modelo MMS fue propuesto en [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

El resumen del artículo es el siguiente:

*Ampliar la cobertura lingüística de la tecnología del habla tiene el potencial de mejorar el acceso a la información para muchas más personas. Sin embargo, la tecnología del habla actual se limita a unas cien lenguas, una pequeña fracción de las más de 7.000 lenguas que se hablan en el mundo. El proyecto Massively Multilingual Speech (MMS) aumenta el número de lenguas admitidas entre 10 y 40 veces, dependiendo de la tarea. Los ingredientes principales son un nuevo conjunto de datos basado en la lectura de textos religiosos de acceso público y el aprovechamiento eficaz del autoaprendizaje supervisado. Construimos modelos preentrenados de wav2vec 2.0 que cubren 1.406 lenguas, un único modelo multilingüe de reconocimiento automático del habla para 1.107 lenguas, modelos de síntesis del habla para el mismo número de lenguas, así como un modelo de identificación de lengua para 4.017 lenguas. Los experimentos muestran que nuestro modelo multilingüe de reconocimiento del habla reduce a menos de la mitad la tasa de error de palabra de Whisper en 54 lenguas del benchmark FLEURS, mientras se entrena con una pequeña fracción de los datos etiquetados.*

Estos son los diferentes modelos de código abierto del proyecto MMS. Los modelos y el código se publicaron originalmente [aquí](https://github.com/facebookresearch/fairseq/tree/main/examples/mms). Los hemos añadido al marco `transformers`, lo que facilita su uso.

### Reconocimiento automático del habla (ASR)

Los puntos de control del modelo ASR se pueden encontrar aquí: [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 obtener la mejor precisión, use el modelo `mms-1b-all`.

Consejos:

- Todos los modelos de ASR aceptan un array de float que corresponde a la forma de onda cruda de la señal de voz. La forma de onda cruda debe preprocesarse con [Wav2Vec2FeatureExtractor](/docs/transformers/main/es/model_doc/wav2vec2#transformers.Wav2Vec2FeatureExtractor).
- Los modelos se entrenaron usando clasificación temporal conexionista (CTC), por lo que la salida del modelo debe decodificarse usando [Wav2Vec2CTCTokenizer](/docs/transformers/main/es/model_doc/wav2vec2#transformers.Wav2Vec2CTCTokenizer).
- Puede cargar pesos de adaptadores de idioma diferentes para distintos idiomas mediante [load_adapter()](/docs/transformers/main/es/model_doc/wav2vec2#transformers.Wav2Vec2ForCTC.load_adapter). Los adaptadores de idioma constan de aproximadamente 2 millones de parámetros, por lo que pueden cargarse de manera eficiente bajo demanda cuando se necesiten.

#### Cargando

Por defecto, MMS carga los pesos del adaptador para el inglés. Si desea cargar los pesos del adaptador de otro idioma, asegúrese de especificar `target_lang=<your-chosen-target-lang>` así como `"ignore_mismatched_sizes=True`. La palabra clave `ignore_mismatched_sizes=True` debe pasarse para permitir que la cabeza del modelo de lenguaje se redimensione según el vocabulario del idioma especificado. De manera similar, el procesador debe cargarse con el mismo idioma objetivo

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

Puede ignorar con seguridad una advertencia 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.
```

Si deseas usar el pipeline de ASR, puedes cargar el idioma objetivo elegido de la siguiente manera:

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

#### Inferencia

A continuación, veamos cómo podemos ejecutar MMS en inferencia y cambiar las capas de adaptador después de haber llamado a `~PretrainedModel.from_pretrained`. Primero, cargamos datos de audio en diferentes idiomas usando [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"]
```

A continuación, cargamos el modelo y el procesador

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

Ahora procesamos los datos de audio, pasamos los datos de audio procesados al modelo y transcribimos la salida del modelo, tal como solemos hacer con [Wav2Vec2ForCTC](/docs/transformers/main/es/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'
```

Ahora podemos mantener el mismo modelo en memoria y simplemente cambiar los adaptadores de idioma llamando a la función conveniente [load_adapter()](/docs/transformers/main/es/model_doc/wav2vec2#transformers.Wav2Vec2ForCTC.load_adapter) para el modelo y [set_target_lang()](/docs/transformers/main/es/model_doc/wav2vec2#transformers.Wav2Vec2CTCTokenizer.set_target_lang) para el tokenizador. Pasamos el idioma objetivo como entrada: `"fra"` para el 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"
```

De la misma manera, el idioma puede cambiarse a todos los demás idiomas admitidos. Consulte:

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

para ver todos los idiomas admitidos.

Para mejorar aún más el rendimiento de los modelos de ASR, se puede utilizar la decodificación con modelos de lenguaje. Consulte la documentación [aquí](https://huggingface.co/facebook/mms-1b-all) para obtener más detalles.

### Síntesis de voz (TTS)

MMS-TTS utiliza la misma arquitectura de modelo que VITS, que se añadió a 🤗 Transformers en la v4.33. MMS entrena un punto de control de modelo separado para cada uno de los más de 1100 idiomas del proyecto. Todos los puntos de control disponibles se pueden encontrar en Hugging Face Hub: [facebook/mms-tts](https://huggingface.co/models?sort=trending&search=facebook%2Fmms-tts), y la documentación de inferencia bajo [VITS](./vits).

#### Inferencia

Para usar el modelo MMS, primero actualice a la última versión de la biblioteca Transformers:

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

Dado que el modelo basado en flujos de VITS es no determinista, es buena práctica establecer una semilla para garantizar la reproducibilidad de las salidas.

- Para idiomas con alfabeto latino, como el inglés o el francés, el tokenizador se puede usar directamente para
preprocesar las entradas de texto. El siguiente ejemplo de código ejecuta una pasada hacia adelante usando el checkpoint en inglés de 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]
```

La forma de onda resultante se puede guardar como un archivo `.wav`:

```python
import scipy

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

O se muestra en un Jupyter Notebook / Google Colab:

```python
from IPython.display import Audio

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

Para ciertos idiomas con alfabetos no romanos, como el árabe, el mandarín o el hindi, se requiere el paquete perl [`uroman`](https://github.com/isi-nlp/uroman) para preprocesar las entradas de texto al alfabeto romano.

Puedes comprobar si necesitas el paquete `uroman` para tu idioma inspeccionando el atributo `is_uroman` del `tokenizer` preentrenado:

```python
from transformers import VitsTokenizer

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

Si es necesario, debe aplicar el paquete uroman a las entradas de texto **antes** de pasarlas al `VitsTokenizer`, ya que actualmente el tokenizador no admite realizar el preprocesamiento por sí mismo.

Para hacer esto, primero clona el repositorio uroman en tu máquina local y establece la variable de bash `UROMAN` en la ruta local:

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

A continuación, puede preprocesar la entrada de texto con el siguiente fragmento de código. Puede usar la variable de bash `UROMAN` para apuntar al repositorio de uroman, o bien pasar el directorio de uroman como argumento a la función `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]
```

**Consejos:**

* Los puntos de control de MMS-TTS se entrenan con texto en minúsculas y sin puntuación. De forma predeterminada, `VitsTokenizer` *normaliza* las entradas eliminando cualquier distinción de mayúsculas y minúsculas y la puntuación, para evitar pasar caracteres fuera de vocabulario al modelo. Por lo tanto, el modelo no distingue entre mayúsculas/minúsculas ni entre la presencia o ausencia de puntuación, por lo que se debe evitar su uso en el texto de entrada. Puede deshabilitar la normalización estableciendo `normalize=False` en la llamada al tokenizador, pero esto provocará un comportamiento inesperado y no se recomienda.
* La velocidad de habla se puede variar estableciendo el atributo `model.speaking_rate` en un valor elegido. Del mismo modo, la aleatoriedad del ruido se controla mediante `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)
```

### Identificación de idioma (LID)

Están disponibles distintos modelos de LID según el número de idiomas que pueden reconocer: [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).

#### Inferencia

Primero, instalamos transformers y algunas otras bibliotecas

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

A continuación, cargamos algunas muestras de audio mediante `datasets`. Asegúrate de que los datos de audio estén muestreados 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"]
```

A continuación, cargamos el modelo y el procesador

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

Ahora procesamos los datos de audio y pasamos los datos de audio procesados al modelo para clasificarlos en un idioma, tal como solemos hacer con los modelos de clasificación de audio 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 los idiomas admitidos de un punto de control, puede imprimir los ids de idioma de la siguiente manera:

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

### Modelos preentrenados de audio

Hay modelos preentrenados disponibles en dos tamaños diferentes: [300M](https://huggingface.co/facebook/mms-300m) y [1Bil](https://huggingface.co/facebook/mms-1b).

La arquitectura de MMS para ASR se basa en el modelo Wav2Vec2; consulte la [página de documentación de Wav2Vec2](./wav2vec2) para obtener más detalles sobre cómo realizar el ajuste fino con modelos para diversas tareas de nivel inferior.

MMS-TTS utiliza la misma arquitectura de modelo que VITS; consulte la [página de documentación de VITS](./vits) para obtener la referencia de la API.

