> 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-chu/text-to-speech-tts-fine-tuning.md).

# 音声合成（TTS）ファインチューニングガイド

Unsloth を使って TTS および STT の音声モデルをファインチューニングする方法を学びます。

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

〜を使えば [Unsloth](https://github.com/unslothai/unsloth)、ファインチューニングできます **any** 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未満のパラメータのモデルをファインチューニングするのが理想的なことが多く、私たちの主な例ではSesame-CSM（1B）と、Llamaベースの音声モデルであるOrpheus-TTS（3B）を使っています。

#### Sesame-CSM（1B）の詳細

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

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

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

#### Orpheus-TTS（3B）の詳細

Orpheusは大規模な音声コーパスで事前学習されており、笑い声やため息のような感情的な合図を内蔵サポートして、現実的な音声を生成するのに優れています。そのアーキテクチャにより、利用・学習が最も簡単なTTSモデルの1つであり、llama.cpp経由でエクスポートできるため、すべての推論エンジンで優れた互換性があります。未対応のモデルでは、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ビット精度を使用（QLoRA）
)
```

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

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

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

少なくとも、TTSファインチューニング用データセットは **音声クリップとそれに対応するトランスクリプト** （テキスト）から構成されます。 [*Elise* dataset](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では、これらのデータセットには次のようなフィールドがあります `音声` （波形） `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）がダウンロードされます。 `dataset` の各項目は少なくとも次を持つ辞書です：

* `"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用の入力を準備する必要があります。テキスト読み上げでは、1つの方法として、テキストと音声トークン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がこれを抽象化してくれるかもしれません**：モデルが音声の扱い方を知っている関連processorを持つFastModelであれば、データセット内の音声を自動的にトークンへエンコードするかもしれません。そうでなければ、各音声クリップを手動でトークンIDにエンコード（Orpheusのコードブックを使用）する必要があります。これはこのガイドを超える高度な手順ですが、テキストトークンだけではモデルに実際の音声は学習されないことを覚えておいてください。音声パターンに一致させる必要があります。

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

**ステップ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 by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

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

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

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.
