> For the complete documentation index, see [llms.txt](https://unsloth.ai/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://unsloth.ai/docs/jp/ji-ben/text-to-speech-tts-fine-tuning.md).

# Text-to-Speech（TTS）ファインチューニングガイド

TTSモデルをファインチューニングすることで、特定のデータセット、ユースケース、あるいは望ましいスタイルやトーンに適応させることができます。目標は、これらのモデルをカスタマイズして声をクローンし、話し方のスタイルやトーンを適応させ、新しい言語をサポートし、特定のタスクを処理できるようにするなどです。私たちはまた、 **Speech-to-Text (STT)** モデル、たとえば OpenAI の Whisper もサポートしています。

Unslothを使うと、 [Unsloth](https://github.com/unslothai/unsloth)、 **任意の** TTSモデル（`transformers` 対応）を、Flash Attention 2 を使った他の実装よりも50%少ないメモリで1.5倍高速にファインチューニングできます。

⭐ **Unslothは任意の `transformers` 互換性のあるTTSモデルをサポートしています。** まだノートブックやアップロードがなくても、サポート対象です。たとえば、Dia-TTS や Moshi のファインチューニングを試してみてください。

{% hint style="info" %}
ゼロショットのクローンはトーンは捉えますが、リズムや表現が欠けるため、しばしば機械的で不自然に聞こえます。ファインチューニングは、はるかに正確で現実的な音声再現を実現します。 [こちらで詳しく読む](#fine-tuning-voice-models-vs.-zero-shot-voice-cloning).
{% endhint %}

### ファインチューニング用ノートブック：

また、TTSモデル（元のモデルと量子化版）を私たちの [Hugging Faceページ](https://huggingface.co/collections/unsloth/text-to-speech-tts-models-68007ab12522e96be1e02155).

| [Sesame-CSM (1B)](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Sesame_CSM_\(1B\)-TTS.ipynb) | [Orpheus-TTS (3B)](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Orpheus_\(3B\)-TTS.ipynb) | [Whisper Large V3](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Whisper.ipynb) (STT) |
| ------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| [Spark-TTS (0.5B)](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Spark_TTS_\(0_5B\).ipynb)   | [Llasa-TTS (1B)](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Llasa_TTS_\(1B\).ipynb)     | [Oute-TTS (1B)](https://colab.research.google.com/github/unslothai/notebooks/blob/main/nb/Oute_TTS_\(1B\).ipynb)  |

{% hint style="success" %}
出力の長さが最大10秒に達する場合は、`max_new_tokens = 125` をデフォルト値の125より大きくしてください。125トークンは10秒の音声に相当するため、より長い出力にはそれ以上の値を設定する必要があります。
{% endhint %}

### TTSモデルの選択と読み込み

TTSでは、エンドユーザーにとって低レイテンシーで推論が速いことから、小さなモデルがよく好まれます。3Bパラメータ未満のモデルをファインチューニングするのが理想的なことが多く、私たちの主な例では、Llamaベースの音声モデルである Sesame-CSM (1B) と Orpheus-TTS (3B) を使用しています。

#### Sesame-CSM (1B) の詳細

**CSM-1B** はベースモデルであり、一方で **Orpheus-ft** は8人のプロの声優でファインチューニングされているため、声の一貫性が主な違いです。CSMは各話者に対して良好に動作させるために音声コンテキストを必要としますが、Orpheus-ftにはこの一貫性が組み込まれています。

CSMのようなベースモデルからファインチューニングするには一般により多くの計算資源が必要ですが、Orpheus-ftのようなファインチューニング済みモデルから始めると、すぐにより良い結果が得られます。

CSMを扱いやすくするために、新しいサンプリングオプションと、音声コンテキストを使って声の一貫性を改善する方法を示す例を追加しました。

#### Orpheus-TTS (3B) の詳細

Orpheusは大規模な音声コーパスで事前学習されており、笑いやため息のような感情的な手がかりを内蔵でサポートし、現実的な音声生成に優れています。そのアーキテクチャにより、llama.cpp経由でエクスポートできるため、すべての推論エンジン間で高い互換性を持ち、利用・学習しやすいTTSモデルの一つです。未対応のモデルでは、LoRAアダプターのsafetensorsのみ保存できます。

#### モデルの読み込み

音声モデルは通常サイズが小さいため、より高品質な結果が得られる可能性のあるLoRA 16-bitまたはフルファインチューニングFFTを使って学習できます。LoRA 16-bitで読み込むには：

```python
from unsloth import FastModel

model_name = "unsloth/orpheus-3b-0.1-pretrained"
model, tokenizer = FastModel.from_pretrained(
    model_name,
    load_in_4bit=False  # 4-bit精度を使用（QLoRA）
)
```

これを実行すると、Unslothはモデルの重みをダウンロードします。8-bitを使いたい場合は、 `load_in_8bit = True`を使えます。フルファインチューニングの場合は、 `full_finetuning = True` を設定してください（十分なVRAMがあることを確認してください）。また、モデル名を他のTTSモデルに置き換えることもできます。

{% hint style="info" %}
**注意：** Orpheusのトークナイザーには、音声出力用の特別なトークンがすでに含まれています（詳細は後述）。 *別* のボコーダーは必要ありません。Orpheusは音声トークンを直接出力し、それを波形にデコードできます。
{% endhint %}

### データセットの準備

最低限、TTSファインチューニング用データセットは **音声クリップとそれに対応する書き起こし** （テキスト）から構成されます。 [*Elise* データセット](https://huggingface.co/datasets/MrDragonFox/Elise) を使いましょう。これは約3時間の単一話者の英語音声コーパスです。2つのバージョンがあります：

* [`MrDragonFox/Elise`](https://huggingface.co/datasets/MrDragonFox/Elise) – **感情タグ** （例：\<sigh>、\<laughs>）が書き起こしに埋め込まれた拡張版です。山括弧の中のこれらのタグは表情（笑い、ため息など）を示し、Orpheusのトークナイザーでは特別なトークンとして扱われます
* [`Jinsaryko/Elise`](https://huggingface.co/datasets/Jinsaryko/Elise) – 特別なタグのない書き起こしを持つベース版。

データセットは、各エントリに1つの音声と1つの書き起こしが含まれる形で整理されています。Hugging Face上では、これらのデータセットには次のようなフィールドがあります `audio` （波形）、 `text` （書き起こし）、およびいくつかのメタデータ（話者名、ピッチ統計など）です。Unslothには音声-テキストのペアからなるデータセットを渡す必要があります。

{% hint style="success" %}
トーン、間合い、ピッチだけに注目するのではなく、データセットが完全に注釈され、適切に正規化されていることを優先すべきです。
{% endhint %}

{% hint style="info" %}
次のような一部のモデルでは **Sesame-CSM-1B**、speaker ID 0 を使った生成間で声が変動することに気づくかもしれません。これは **ベースモデル**だからです。固定された声のアイデンティティを持っていません。Speaker IDトークンは主に **会話内の一貫性**を保つのに役立ち、別々の生成間での一貫性にはあまり効きません。

一貫した声を得るには、 **文脈的な例**、たとえば少しの参照音声クリップや直前の発話を与えてください。これにより、モデルは望ましい声をより確実に模倣できます。これがなければ、同じspeaker IDでも変動は予想されます。
{% endhint %}

**オプション1：Hugging Face Datasetsライブラリを使う** – EliseデータセットはHugging Faceの `datasets` ライブラリを使って読み込めます：

```python
from datasets import load_dataset, Audio

# Eliseデータセットを読み込む（例：感情タグ付きの版）
dataset = load_dataset("MrDragonFox/Elise", split="train")
print(len(dataset), "samples")  # Eliseでは約1200サンプル

# すべての音声が24 kHzのサンプリングレートであることを確認（Orpheusが期待するレート）
dataset = dataset.cast_column("audio", Audio(sampling_rate=24000))
```

これにより、データセット（約1.2kサンプルで約328 MB）がダウンロードされます。 `データセット` の各アイテム

* `"audio"`は、音声クリップ（波形配列とサンプリングレートなどのメタデータ）と、
* `"text"`は、書き起こし文字列です

Orpheusは次のようなタグをサポートしています `<laugh>`, `<chuckle>`, `<sigh>`, `<cough>`, `<sniffle>`, `<groan>`, `<yawn>`, `<gasp>`など。たとえば： `"I missed you <laugh> so much!"`。これらのタグは山括弧で囲まれており、モデルでは特別なトークンとして扱われます（ [Orpheusが想定するタグ](https://github.com/canopyai/Orpheus-TTS) に一致し、 `<laugh>` のような `<sigh>`）。学習中、モデルはこれらのタグと対応する音声パターンを関連付けることを学びます。タグ付きのEliseデータセットには、これらの多くがすでに含まれています（たとえば、カードに記載されているように “laughs” が336回、“sighs” が156回など）。データセットにそのようなタグがないが取り入れたい場合は、音声にそれらの表現が含まれる箇所を手作業で書き起こしに注釈できます。

**オプション2：カスタムデータセットを準備する** – 自分の音声ファイルと書き起こしがある場合：

* 音声クリップ（WAV/FLACファイル）をフォルダに整理します。
* ファイルパスと書き起こしの列を持つCSVまたはTSVファイルを作成します。たとえば：

  ```
  filename,text
  0001.wav,こんにちは！
  0002.wav,<sigh> とても疲れています。
  ```
* を使って `load_dataset("csv", data_files="mydata.csv", split="train")` 読み込みます。音声パスをどう扱うかをデータセットローダーに伝える必要があるかもしれません。別の方法として、 `datasets.Audio` 機能を使ってオンザフライで音声データを読み込む方法があります：

  ```python
  from datasets import Audio
  dataset = load_dataset("csv", data_files="mydata.csv", split="train")
  dataset = dataset.cast_column("filename", Audio(sampling_rate=24000))
  ```

  その後、 `dataset[i]["audio"]` に音声配列が含まれます。
* **書き起こしが正規化されていることを確認してください** （トークナイザーが知らない可能性のある異常な文字は使わない。ただし、使用する場合の感情タグは除く）。また、すべての音声が一貫したサンプリングレートを持つようにしてください（必要なら、モデルが期待する目標レート、たとえばOrpheusなら24kHzにリサンプリングします）。

要するに、 **データセット準備**:

* には、 **（音声, テキスト）のリスト** のペアが必要です。
* HF `datasets` ライブラリを使って読み込みと任意の前処理（リサンプリングなど）を処理します。
* 学習させたいテキスト内の **特別なタグ** を含めてください（それらが `<angle_brackets>` 形式になっていて、モデルが別個のトークンとして扱うようにしてください）。
* （任意）複数話者の場合は、テキストにspeaker IDトークンを含めるか、別の話者埋め込み手法を使うこともできますが、それはこの基本ガイドの範囲を超えます（Eliseは単一話者です）。

### UnslothでTTSをファインチューニングする

それでは、ファインチューニングを始めましょう！Pythonコードを使って説明します（Jupyter notebook、Colabなどで実行できます）。

**ステップ1：モデルとデータセットを読み込む**

私たちのすべてのTTSノートブックでは、LoRA（16-bit）学習を有効にし、QLoRA（4-bit）学習を次のように無効にしています： `load_in_4bit = False`。これは、モデルが通常データセットをよりよく学習でき、精度が高くなるためです。

```python
from unsloth import FastLanguageModel
import torch
dtype = None # 自動検出ではNone。Tesla T4、V100ではFloat16、Ampere+ではBfloat16
load_in_4bit = False # メモリ使用量を減らすために4bit量子化を使用。Falseでも可。

model, tokenizer = FastLanguageModel.from_pretrained(
    model_name = "unsloth/orpheus-3b-0.1-ft",
    max_seq_length= 2048, # 長いコンテキストなら任意で選択！
    dtype = dtype,
    load_in_4bit = load_in_4bit,
    #token = "hf_...", # meta-llama/Llama-2-7b-hfのような制限付きモデルを使う場合は使用
)

from datasets import load_dataset
dataset = load_dataset("MrDragonFox/Elise", split = "train")
```

{% hint style="info" %}
メモリが非常に限られている場合、またはデータセットが大きい場合は、ストリーミングするかチャンクに分けて読み込めます。ここでは、3時間の音声はRAMに十分収まります。自分のデータセットCSVを使う場合も、同様に読み込んでください。
{% endhint %}

**ステップ2：高度な処理 - 学習用にデータを前処理する（任意）**

Trainer用の入力を準備する必要があります。テキスト読み上げでは、モデルを因果的に学習させる方法の一つとして、テキストと音声トークンIDをターゲット系列として連結します。ただし、Orpheusは音声を出力するデコーダ専用LLMなので、テキストを入力（コンテキスト）として与え、音声トークンIDをラベルにすることができます。実際には、モデルの設定がそれをtext-to-speechとして識別していれば、Unslothの統合がこれを自動で行うかもしれません。そうでなければ、次のようにできます：

```python
# テキストの書き起こしをトークン化する
def preprocess_function(example):
    # テキストをトークン化する（<laugh>のような特別なトークンはそのまま保持）
    tokens = tokenizer(example["text"], return_tensors="pt")
    # トークンIDのリストに平坦化する
    input_ids = tokens["input_ids"].squeeze(0)
    # モデルはこれらのテキストトークンの後に音声トークンを生成します。
    # 学習では、labelsをinput_idsと同じに設定できます（次のトークンを予測するように学習する）。
    # ただし、それでは次のテキストトークンまでしか扱えません（それが音声トークンや終了トークンになる可能性はある）。
    # より高度な方法：音声開始を示す特別なトークンを追加し、残りをモデルに生成させる。
    # 簡単のため、入力と同じものをラベルに使う（モデルは自分自身が与えられた系列の出力を学習する）。
    return {"input_ids": input_ids, "labels": input_ids}

train_data = dataset.map(preprocess_function, remove_columns=dataset.column_names)
```

{% hint style="info" %}
上記は簡略化です。実際にOrpheusを適切にファインチューニングするには、 *音声トークンを学習ラベルの一部として含める*必要があります。Orpheusの事前学習では、おそらく音声を離散トークン（音声コーデック経由）に変換し、その前のテキストに基づいてそれらを予測するよう学習していたはずです。新しい音声データでファインチューニングする場合も、各クリップの音声トークンを同様に取得する必要があります（Orpheusの音声コーデックを使用）。OrpheusのGitHubにはデータ処理用スクリプトがあり、音声を次のシーケンスにエンコードします `<custom_token_x>` トークン。
{% endhint %}

ただし、 **Unslothがこれを抽象化してくれるかもしれません**：モデルが音声の扱い方を知っている関連プロセッサ付きのFastModelなら、データセット内の音声を自動的にトークンへエンコードするかもしれません。そうでない場合は、各音声クリップを手動でトークンIDにエンコードする必要があります（Orpheusのコードブックを使用）。これはこのガイドを超える高度な手順ですが、テキストトークンだけでは実際の音声をモデルに教えられないことに注意してください。音声パターンに一致させる必要があります。

Unslothが音声を直接渡す方法を提供していると仮定しましょう（たとえば、 `processor` を設定し、音声配列を渡すことで）。Unslothがまだ自動音声トークン化をサポートしていない場合は、Orpheusリポジトリの `encode_audio` 関数を使って音声のトークン列を取得し、それをラベルとして使う必要があるかもしれません。（データセットのエントリには `phonemes` といくつかの音響特徴があり、パイプラインの存在を示唆しています。）

**ステップ3：学習引数とTrainerを設定する**

```python
from transformers import TrainingArguments,Trainer,DataCollatorForSeq2Seq
from unsloth import is_bfloat16_supported

trainer = Trainer(
    model = model,
    train_dataset = dataset,
    args = TrainingArguments(
        per_device_train_batch_size = 1,
        gradient_accumulation_steps = 4,
        warmup_steps = 5,
        # num_train_epochs = 1, # 1回の完全な学習実行にこれを設定します。
        max_steps = 60,
        learning_rate = 2e-4,
        fp16 = not is_bfloat16_supported(),
        bf16 = is_bfloat16_supported(),
        logging_steps = 1,
        optim = "adamw_8bit",
        weight_decay = 0.01,
        lr_scheduler_type = "linear",
        seed = 3407,
        output_dir = "outputs",
        report_to = "none", # これはWandBなどに使用します
    ),
)
```

処理を速くするために60ステップにしていますが、 `num_train_epochs=1` を設定して `max_steps=None`にすることもできます。 per\_device\_train\_batch\_size > 1 を使用すると、マルチGPU構成ではエラーが発生する場合があります。問題を避けるには、CUDA\_VISIBLE\_DEVICES を単一GPUに設定してください（例: CUDA\_VISIBLE\_DEVICES=0）。必要に応じて調整してください。

**ステップ4: ファインチューニングを開始する**

これで学習ループが開始されます。損失のログが50ステップごとに表示されるはずです（ `logging_steps`で設定したとおりです）。学習にはGPUに応じて時間がかかる場合があります。たとえば、ColabのT4 GPUでは、3時間分のデータに対する数エポックに1〜2時間かかることがあります。Unslothの最適化により、標準的なHF学習よりも高速になります。

**ステップ5: ファインチューニング済みモデルを保存する**

学習が完了した後（または十分だと感じた時点で途中停止した場合でも）、モデルを保存します。これはLoRAアダプタのみを保存し、完全なモデルは保存しません。16bitまたはGGUFで保存するには、下へスクロールしてください！

```python
model.save_pretrained("lora_model")  # ローカル保存
tokenizer.save_pretrained("lora_model")
# model.push_to_hub("your_name/lora_model", token = "...") # オンライン保存
# tokenizer.push_to_hub("your_name/lora_model", token = "...") # オンライン保存
```

これによりモデルの重みが保存されます（LoRAの場合、ベースが完全にファインチューニングされていなければ、アダプタの重みのみが保存されることがあります）。CLIで `--push_model` を使ったか、または `trainer.push_to_hub()`を使っていれば、Hugging Face Hubに直接アップロードできます。

これで、ディレクトリ内にファインチューニング済みのTTSモデルができているはずです。次のステップはそれをテストすることで、対応していれば llama.cpp を使ってGGUFファイルに変換できます。

### 音声モデルのファインチューニング vs. ゼロショット音声クローン

XTTSのようなモデルを使えば、たった30秒の音声で声をクローンできると言う人がいます。学習は不要です。技術的には正しいのですが、本質を見落としています。

OrpheusやCSMのようなモデルでも利用できるゼロショット音声クローンは、あくまで近似です。話者の **声色と音色** の一般的な特徴は捉えますが、表現の幅全体を再現するわけではありません。話す速さ、言い回し、声の癖、そして韻律の微妙なニュアンスといった、声に **個性と独自性**.

を与える要素が失われます。違う声が欲しいだけで、同じ話し方のパターンでも構わないなら、ゼロショットでたいてい十分です。しかし、発話は依然として **モデルのスタイル**に従い、話者のものにはなりません。

より個人的で表現豊かなものにしたいなら、誰かの話し方を本当に捉えるために、LoRAのような手法で学習する必要があります。


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://unsloth.ai/docs/jp/ji-ben/text-to-speech-tts-fine-tuning.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
