# 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 による [Scaling Speech Technology to 1,000+ Languages](https://huggingface.co/papers/2305.13516) で提案されました。

論文の抄録は以下の通りです。

*音声技術の対応言語を拡大することは、より多くの人々の情報へのアクセスを向上させる可能性があります。しかし、現在の音声技術は約100言語に限定されており、世界中で話されている7,000以上の言語のほんの一握りです。Massively Multilingual Speech (MMS) プロジェクトは、タスクによって異なりますが、対応言語数を10〜40倍に増加させます。その主な要素は、公開されている宗教文書の朗読に基づく新しいデータセットと、自己教師あり学習の効果的な活用です。1,406言語をカバーする事前学習済み wav2vec 2.0 モデル、1,107言語に対応する単一の多言語自動音声認識モデル、同じ数の言語に対応する音声合成モデル、そして4,017言語に対応する言語識別モデルを構築しました。実験により、FLEURS ベンチマークの54言語において、ラベル付きデータのほんの一部で学習しながら、Whisper の単語誤り率を半分以上に削減できることが示されました。*

MMSプロジェクトでオープンソース化されたモデルは以下の通りです。モデルとコードは元々[こちら](https://github.com/facebookresearch/fairseq/tree/main/examples/mms)で公開されています。`transformers`フレームワークに追加したことで、より簡単に利用できるようになりました。

### 自動音声認識（ASR）

ASRモデルのチェックポイントは、[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)として、こちらで確認できます。最高精度を得るには、`mms-1b-all`モデルを使用してください。

ヒント:

- すべてのASRモデルは、音声信号の生波形に対応するfloat配列を受け入れます。生波形は、[Wav2Vec2FeatureExtractor](/docs/transformers/main/ja/model_doc/wav2vec2#transformers.Wav2Vec2FeatureExtractor)で前処理する必要があります。
- モデルは接続主義的時間分類（CTC）を用いて学習されているため、モデルの出力は[Wav2Vec2CTCTokenizer](/docs/transformers/main/ja/model_doc/wav2vec2#transformers.Wav2Vec2CTCTokenizer)を使用してデコードする必要があります。
- [load_adapter()](/docs/transformers/main/ja/model_doc/wav2vec2#transformers.Wav2Vec2ForCTC.load_adapter) を使用して、異なる言語用の言語アダプター重みをロードできます。言語アダプターは約200万パラメータのみで構成されるため、必要に応じて効率的にオンザフライでロードできます。

#### 読み込み中

デフォルトでは、MMSは英語のアダプター重みをロードします。他の言語のアダプター重みをロードする場合は、`target_lang=<your-chosen-target-lang>`と`"ignore_mismatched_sizes=True`を指定してください。`ignore_mismatched_sizes=True`キーワードを渡すことで、指定した言語の語彙に合わせて言語モデルヘッドをリサイズできるようになります。同様に、プロセッサーも同じターゲット言語でロードする必要があります。

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

次のような警告は、安全に無視できます。

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

ASRパイプラインを使用する場合は、選択した対象言語を次のようにロードできます。

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

#### 推論

次に、`~PretrainedModel.from_pretrained`を呼び出した後にアダプター層を変更しながら、MMSを推論で実行する方法を見てみましょう。まず、[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"]
```

次に、モデルとプロセッサーを読み込みます

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

次に、音声データを処理し、処理済みの音声データをモデルに渡し、[Wav2Vec2ForCTC](/docs/transformers/main/ja/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'
```

これにより、メモリ内のモデルをそのまま維持したまま、モデルには便利な[load_adapter()](/docs/transformers/main/ja/model_doc/wav2vec2#transformers.Wav2Vec2ForCTC.load_adapter)関数を、トークナイザーには[set_target_lang()](/docs/transformers/main/ja/model_doc/wav2vec2#transformers.Wav2Vec2CTCTokenizer.set_target_lang)を呼び出すだけで、言語アダプターを切り替えることができます。対象言語を入力として渡します。ここではフランス語の`"fra"`を指定します。

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

同様に、他のサポートされている言語にも切り替えることができます。以下のページをご覧ください:

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

サポートされているすべての言語を確認するには、

ASRモデルの性能をさらに向上させるには、言語モデルデコーディングを使用できます。詳細については、[こちら](https://huggingface.co/facebook/mms-1b-all)のドキュメントを参照してください。

### 音声合成 (TTS)

MMS-TTSは、v4.33で🤗 Transformersに追加されたVITSと同じモデルアーキテクチャを使用しています。MMSでは、プロジェクトに含まれる1100以上の言語それぞれについて、個別のモデルチェックポイントを学習しています。利用可能なすべてのチェックポイントはHugging Face Hubの[facebook/mms-tts](https://huggingface.co/models?sort=trending&search=facebook%2Fmms-tts)で、推論に関するドキュメントは[VITS](./vits)の下で確認できます。

#### 推論

MMSモデルを使用するには、まずTransformersライブラリを最新バージョンに更新してください。

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

VITSのフローベースモデルは非決定論的であるため、出力の再現性を確保するためにシードを設定するのが良い慣行です。

- 英語やフランス語などのローマ字アルファベットを使用する言語では、トークナイザーを直接使用して
テキスト入力を前処理します。以下のコード例では、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]
```

生成された波形は、`.wav`ファイルとして保存できます。

```python
import scipy

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

Jupyter Notebook / Google Colab で表示された場合:

```python
from IPython.display import Audio

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

アラビア語、中国語、ヒンディー語などのローマ字以外の文字体系を持つ特定の言語では、テキスト入力をローマ字に前処理するために、[`uroman`](https://github.com/isi-nlp/uroman) perl パッケージが必要です。

`tokenizer` の事前学習済みモデルの `is_uroman` 属性を確認することで、お使いの言語に `uroman` パッケージが必要かどうかを調べることができます。

```python
from transformers import VitsTokenizer

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

必要に応じて、`VitsTokenizer`にテキストを入力する**前**に、uromanパッケージを適用する必要があります。現在、このトークナイザは前処理を自身で行うことをサポートしていないためです。

これを行うには、まずuromanリポジトリをローカルマシンにクローンし、bash変数`UROMAN`にローカルパスを設定します。

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

その後、以下のコードスニペットを使用してテキスト入力の前処理を行うことができます。`UROMAN` という bash 変数を使用して uroman リポジトリを指定するか、`uromanize` 関数に uroman ディレクトリを引数として渡すかのいずれかの方法が利用できます。

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

**ヒント:**

* MMS-TTSのチェックポイントは、小文字化され、句読点のないテキストで学習されています。デフォルトでは、`VitsTokenizer`は*正規化*によって入力を処理し、大文字・小文字の区別と句読点を除去します。これにより、モデルに語彙外の文字が渡されることを防ぎます。したがって、モデルは大文字・小文字や句読点の影響を受けません。そのため、テキストプロンプトではこれらを避ける必要があります。トークナイザーの呼び出しで`normalize=False`を設定することで正規化を無効にできますが、これにより予期しない動作が発生する可能性があるため、推奨されません。
* `model.speaking_rate` 属性に選択した値を設定することで、話速を調整できます。同様に、`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)
```

### 言語識別 (LID)

認識可能な言語の数に応じて、[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)のLIDモデルが利用可能です。

#### 推論

まず、transformers とその他のいくつかのライブラリをインストールします

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

次に、`datasets` を使用していくつかの音声サンプルを読み込みます。音声データが 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"]
```

次に、モデルとプロセッサーを読み込みます

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

次に、音声データを処理し、処理済みの音声データをモデルに渡して言語を分類します。[ehcalabres/wav2vec2-lg-xlsr-en-speech-emotion-recognition](https://huggingface.co/harshit345/xlsr-wav2vec-speech-emotion-recognition) などの Wav2Vec2 音声分類モデルで通常行っているのと同じ方法です。

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

チェックポイントがサポートしているすべての言語を確認するには、次のように言語IDを出力できます。

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

### オーディオ事前学習モデル

事前学習済みモデルは、[300M](https://huggingface.co/facebook/mms-300m) と [1Bil](https://huggingface.co/facebook/mms-1b) の2つのサイズで利用可能です。

ASR用のMMSアーキテクチャはWav2Vec2モデルに基づいています。さまざまな下流タスクでのモデルのファインチューニングの詳細については、[Wav2Vec2のドキュメントページ](./wav2vec2)を参照してください。

MMS-TTSはVITSと同じモデルアーキテクチャを使用しています。APIの参考として、[VITSのドキュメントページ](./vits)を参照してください。

