使用f5-tts訓練自己的模型筆記

摘要

服務器都有了,這不得練練丹,有點說不過去啊。所以嘗試了從頭開始訓練一個模型,結果由于推理頁面好像有bug,不知道是不是失敗了,然后又嘗試微調一下模型。本篇文章主要記錄了三流調包俠嘗試煉丹過程中學習到的一些知識。

為什么要自己訓練或者微調模型

F5-TTS 的設計目標不是生成一個固定的、默認的(例如女聲普通話)語音。傳統的 TTS 模型,比如一些早期的端到端模型,確實可以直接輸入文本,然后生成一個預設音色的語音。它是一個“Text-to-Cloned-Voice”模型: F5-TTS 專注于從一小段參考音頻中提取說話人的音色、語調、說話風格等特征,然后將這些特征應用到你提供的文本上,生成帶有該音色的語音。

雖然 F5-TTS 強調零樣本語音克隆,需要參考音頻來工作,但訓練自己的模型(無論是從頭開始訓練還是在預訓練模型上進行微調)的意義在于:

提升特定音色的克隆質量和穩定性

  • 預訓練的 F5-TTS 模型可能在通用語音克隆方面表現良好,但對于特定目標音色(例如你想要克隆的某個人的聲音),其克隆質量和穩定性可能不是最佳。
  • 通過在包含目標音色的大量數據上進行微調 (fine-tuning),模型能夠更好地學習該音色的細微特征、語調模式和發音習慣,從而生成更自然、更像目標音色的語音。
  • 這對于需要高保真度語音克隆的應用(如虛擬主播、個人語音助手等)至關重要。

適應特定語言或口音

  • F5-TTS 原始模型可能主要在英文或中英文混合數據集上訓練。如果你需要為其他語言(例如粵語、日語、德語等)或特定口音(例如英式英語、美式英語的不同口音)生成高質量語音,那么在相應語言/口音的數據集上訓練或微調模型是必不可少的。

適應特定應用場景和數據特點

  • 不同的應用場景可能對語音有不同的要求。例如,有聲讀物可能需要更平穩的語速,而對話系統可能需要更自然的停頓和交互感。
  • 如果你的數據有特定的噪聲、錄音條件或說話風格,通過在類似數據上訓練,可以使模型對這些特點有更好的魯棒性或生成效果。
  • F5-TTS 論文提到,其模型訓練使用了 “in-the-wild multilingual speech dataset Emilia”,這意味著它處理的是真實世界中帶噪的數據。如果你希望在更干凈的數據上得到更清晰的語音,或者在更復雜的場景下有更好的表現,訓練可以幫助模型適應。

控制生成語音的特性(如情感、語速等):

  • 雖然 F5-TTS 自身就支持一定的情感和語速控制,但通過訓練自己的模型,并可能在數據中包含更多情感標簽或不同語速的樣本,可以進一步增強模型在這方面的表現和可控性。

官方訓練模型文檔如下
https://github.com/SWivid/F5-TTS/tree/main/src/f5_tts/train

接下來使用 F5-TTS來訓練個人的語音模型

環境準備

請先按照官方文檔部署并能夠正常文本轉語音,依賴應該就沒問題了

數據準備

數據集格式

官方文檔
https://github.com/SWivid/F5-TTS/discussions/57#discussioncomment-10959029

F5-TTS 采用的格式

datasets/
└── your-dataset/├── wavs/│   ├── 00001.wav│   ├── 00002.wav│   └── ...└── metadata.csv

metadata.csv 格式

wavs/00001.wav|這是第一條語音的文字
wavs/00002.wav|這是第二條語音的文字

網上的數據集

我本來想自己標注的,但好像好廢時間,就搜了搜看有沒有標注好的數據集,然后找到了
https://www.bilibili.com/opus/961351523556655128?spm_id_from=333.1387.0.0
B站up主 紅血球AE3803 分享的

解壓后文件中包含的文件如下
在這里插入圖片描述

  • .wav是語音文件
  • .lab是其對應的文本

編寫腳本處理數據集

建議使用項目自帶的 web ui的方式處理數據集,會對音頻切段,可能會訓練效果更好一些

import os
import csv
import wave
import contextlibdef process_files(directory):"""處理指定目錄中的wav和lab文件,生成metadata.csv文件,并統計語音文件總時長"""# 檢查目錄是否存在if not os.path.isdir(directory):print(f"目錄 {directory} 不存在!")return# 創建輸出目錄(如果需要)wavs_dir = os.path.join(os.path.dirname(directory), "wavs")if not os.path.exists(wavs_dir):os.makedirs(wavs_dir)print(f"創建目錄: {wavs_dir}")# 收集所有匹配的文件file_pairs = []lab_files = {}wav_files = []# 首先收集所有.lab文件for filename in os.listdir(directory):if filename.endswith('.lab'):base_name = os.path.splitext(filename)[0]lab_files[base_name] = filename# 然后檢查每個.lab文件是否有對應的.wav文件for base_name, lab_file in lab_files.items():wav_file = f"{base_name}.wav"if os.path.exists(os.path.join(directory, wav_file)):file_pairs.append((wav_file, lab_file))# 處理匹配的文件對metadata = []total_duration = 0  # 添加總時長統計變量for wav_file, lab_file in file_pairs:# 讀取文本內容with open(os.path.join(directory, lab_file), 'r', encoding='utf-8') as f:text_content = f.read().strip()# 構建目標wav路徑(如 wavs/audio_xxxx.wav)target_wav_path = f"wavs/{wav_file}"# 添加到元數據metadata.append((target_wav_path, text_content))# 獲取wav文件時長wav_path = os.path.join(directory, wav_file)try:with contextlib.closing(wave.open(wav_path, 'r')) as f:frames = f.getnframes()rate = f.getframerate()duration = frames / float(rate)total_duration += durationprint(f"文件 {wav_file} 時長: {duration:.2f}秒")except Exception as e:print(f"無法讀取文件 {wav_file} 的時長: {str(e)}")# 復制wav文件到wavs目錄(如果需要)source_wav_path = os.path.join(directory, wav_file)target_wav_full_path = os.path.join(os.path.dirname(directory), target_wav_path)if not os.path.exists(os.path.dirname(target_wav_full_path)):os.makedirs(os.path.dirname(target_wav_full_path))# 如果文件不在目標位置,可以復制它# import shutil# if not os.path.exists(target_wav_full_path):#    shutil.copy2(source_wav_path, target_wav_full_path)# 寫入metadata.csvoutput_file = os.path.join(os.path.dirname(directory), "metadata.csv")with open(output_file, 'w', encoding='utf-8', newline='') as f:for wav_path, text in metadata:f.write(f"{wav_path}|{text}\n")# 格式化總時長輸出hours, remainder = divmod(total_duration, 3600)minutes, seconds = divmod(remainder, 60)time_str = f"{int(hours)}小時{int(minutes)}{seconds:.2f}秒"print(f"處理完成! 共處理了 {len(metadata)} 對文件,輸出到 {output_file}")print(f"語音文件總時長: {time_str} ({total_duration:.2f}秒)")if __name__ == "__main__":import sys# if len(sys.argv) > 1:#     directory = sys.argv[1]# else:#     # 默認目錄,可以根據需要修改#     directory = input("請輸入包含wav和lab文件的目錄路徑: ")directory = "/Users/wy/wy/workspace/ios_app/黑天鵝"process_files(directory)

該腳本只是讀取文本然后拼接文件名,輸出metadata.csv文件, 文件是手動挪到指定目錄的。輸出內容如下:
在這里插入圖片描述

最后的數據集目錄結構如下
在這里插入圖片描述

txt目錄是多余的,沒有也沒所謂,我只是將剩余的lab文件放到里面好看一點而已.

數據集預處理

這里除了手動處理外,還可以使用web的方式來處理數據集,具體請看后面訓練模型章節里面的web ui訓練小節,沒有辦法,誰叫寫完前面這堆內容才發現有web可以用…

在這里插入圖片描述

腳本位置src/f5_tts/train/datasets/prepare_csv_wavs.py

prepare_csv_wavs.py腳本源碼

查看腳本可以看到正確的命令如下

在這里插入圖片描述

入口函數是prepare_and_save_set
在這里插入圖片描述

入口函數就調用了兩個函數

sub_result, durations, vocab_set = prepare_csv_wavs_dir(inp_dir, num_workers=num_workers)

調用 prepare_csv_wavs_dir 函數處理輸入目錄

  • 使用多線程并行處理音頻文件(獲取音頻時長)
  • 將文本轉換為拼音表示
  • 返回處理后的數據、音頻時長列表和詞匯集合
save_prepped_dataset(out_dir, sub_result, durations, vocab_set, is_finetune)

調用 save_prepped_dataset 函數保存處理結果

  • 將數據保存為Arrow格式(高效讀取)
  • 保存音頻時長信息為JSON
  • 根據is_finetune決定是復制現有詞匯表還是創建新詞匯表

其中跟音頻技術相關的是中文拼音轉換這步的處理,下面詳細看看拼音轉換的代碼。

中文拼音轉換函數詳解

convert_char_to_pinyin 函數是 F5-TTS 模型中的一個關鍵組件,它負責將中文文本轉換為拼音表示。這對于中文語音合成至關重要,因為模型需要處理拼音以正確發音。下面是詳細解析:
這個函數接收文本列表并將其中的中文字符轉換為帶聲調的拼音表示,同時保留非中文字符。這對于生成自然的中文語音至關重要。

def convert_char_to_pinyin(text_list, polyphone=True):if jieba.dt.initialized is False:jieba.default_logger.setLevel(50)  # CRITICALjieba.initialize()final_text_list = []custom_trans = str.maketrans({";": ",", """: '"', """: '"', "'": "'", "'": "'"})  # add custom trans here, to address oovdef is_chinese(c):return ("\u3100" <= c <= "\u9fff"  # common chinese characters)for text in text_list:char_list = []text = text.translate(custom_trans)for seg in jieba.cut(text):seg_byte_len = len(bytes(seg, "UTF-8"))if seg_byte_len == len(seg):  # if pure alphabets and symbolsif char_list and seg_byte_len > 1 and char_list[-1] not in " :'\"":char_list.append(" ")char_list.extend(seg)elif polyphone and seg_byte_len == 3 * len(seg):  # if pure east asian charactersseg_ = lazy_pinyin(seg, style=Style.TONE3, tone_sandhi=True)for i, c in enumerate(seg):if is_chinese(c):char_list.append(" ")char_list.append(seg_[i])else:  # if mixed characters, alphabets and symbolsfor c in seg:if ord(c) < 256:char_list.extend(c)elif is_chinese(c):char_list.append(" ")char_list.extend(lazy_pinyin(c, style=Style.TONE3, tone_sandhi=True))else:char_list.append(c)final_text_list.append(char_list)return final_text_list

為什么要轉換成拼音?

消除歧義

  • 中文是多音字密集的語言,一個漢字可能有多個讀音(如 “行” 可讀作 xíng 或 háng)。
  • 在沒有上下文的情況下,TTS 系統很難判斷正確讀音。拼音提供了明確的發音方式,便于后續處理。

與語音模型對接

  • 很多中文 TTS 系統的底層語音模型(如 Tacotron、FastSpeech、GPT-SoVITS)并不是直接以漢字為輸入,而是以拼音、聲調甚至音素(phoneme)為輸入。
  • 拼音是一個中間表示(intermediate representation),便于模型學習發音規律。

提升語音自然度

  • 精準的拼音/音素輸入能幫助模型合成更自然、連貫的語音,尤其是在聲調和語調變化方面。

1. 結巴分詞初始化

if jieba.dt.initialized is False:jieba.default_logger.setLevel(50)  # CRITICALjieba.initialize()
  • 初始化結巴分詞庫
  • 將日志級別設為 CRITICAL 以抑制不必要的輸出

2. 自定義轉換規則

custom_trans = str.maketrans({";": ",", """: '"', """: '"', "'": "'", "'": "'"})
  • 定義特殊字符的轉換規則,將一些特殊標點符號統一為標準形式
  • 這有助于減少詞匯表外(OOV)字符的出現
    在這里插入圖片描述

3. 中文字符識別

def is_chinese(c):return "\u3100" <= c <= "\u9fff"  # common chinese characters
  • 定義內部函數檢測字符是否為中文
  • 使用 Unicode 范圍 U+3100 至 U+9FFF,涵蓋常見中文字符

4.漢字轉為拼音

pypinyin是 Python 中最主流的中文轉拼音庫,示例代碼如下

from pypinyin import lazy_pinyin, Style
text = "你好,世界!"
# 默認風格,不帶聲調
print(lazy_pinyin(text))  
# 輸出: ['ni', 'hao', 'shi', 'jie']
# 帶聲調
print(lazy_pinyin(text, style=Style.TONE3))  
# 輸出: ['ni3', 'hao3', 'shi4', 'jie4']
# 首字母
print(lazy_pinyin(text, style=Style.FIRST_LETTER))  
# 輸出: ['n', 'h', 's', 'j']

5. 文本處理流程

對于每個輸入文本,函數執行以下步驟

  1. 應用自定義字符轉換規則
  2. 使用結巴分詞將文本分割為詞語片段
  3. 根據不同情況分別處理每個片段
a) 純字母和符號
if seg_byte_len == len(seg):  # if pure alphabets and symbolsif char_list and seg_byte_len > 1 and char_list[-1] not in " :'\"":char_list.append(" ")char_list.extend(seg)
  • 檢測片段是否只包含 ASCII 字符
  • 在必要時添加空格以確保正確分隔
  • 原樣保留字母和符號
b) 純中文
elif polyphone and seg_byte_len == 3 * len(seg):  # if pure east asian charactersseg_ = lazy_pinyin(seg, style=Style.TONE3, tone_sandhi=True)for i, c in enumerate(seg):if is_chinese(c):char_list.append(" ")char_list.append(seg_[i])
  • 檢測是否為純中文片段
  • 使用 lazy_pinyin 將整個片段轉換為拼音
  • 添加空格以確保拼音正確分隔
  • style=Style.TONE3 表示使用數字表示聲調(如 “ni3” 而非 “nǐ”)
  • tone_sandhi=True 啟用聲調變化規則(如"一"的變調)
c) 混合字符
else:  # if mixed characters, alphabets and symbolsfor c in seg:if ord(c) < 256:char_list.extend(c)elif is_chinese(c):char_list.append(" ")char_list.extend(lazy_pinyin(c, style=Style.TONE3, tone_sandhi=True))else:char_list.append(c)
  • 逐字符處理混合內容
  • ASCII 字符原樣保留
  • 中文字符轉換為拼音并添加空格
  • 其他字符(如日文、韓文等)原樣保留

開始預處理數據集

python src/f5_tts/train/datasets/prepare_csv_wavs.py /home/ubuntu/data-set /home/ubuntu/F5-TTS/data/heitiane --pretrain

在這里插入圖片描述

  • /home/ubuntu/data-set 數據集所在目錄
  • /home/ubuntu/F5-TTS/data/heitiane 處理好的數據集存放位置, F5-tts項目所在的data目錄, 是固定的, heitiane是你數據集的名稱,隨便填

還需要修改訓練用的配置文件中的數據集名稱為heitiane具體位置請看訓練腳本詳解章節中的分詞器設置小節。

數據集預處理完成后,就可以開始訓練模型了

訓練模型

官方文檔給出的命令如下:

# setup accelerate config, e.g. use multi-gpu ddp, fp16
# will be to: ~/.cache/huggingface/accelerate/default_config.yaml     
accelerate config# .yaml files are under src/f5_tts/configs directory
accelerate launch src/f5_tts/train/train.py --config-name F5TTS_v1_Base.yaml# possible to overwrite accelerate and hydra config
accelerate launch --mixed_precision=fp16 src/f5_tts/train/train.py --config-name F5TTS_v1_Base.yaml ++datasets.batch_size_per_gpu=19200

了解accelerate命令

accelerate 是 Hugging Face 提供的一個非常強大的工具,旨在幫助 PyTorch 用戶在不同的分布式訓練環境中(如多 GPU、多節點、TPU、混合精度等)輕松運行他們的訓練腳本,而無需編寫大量的樣板代碼。它讓你能夠專注于編寫 PyTorch 訓練循環本身,而把分布式訓練的復雜性交給 accelerate 來處理。

accelerate config命令

用于交互式地配置你的訓練環境。它會引導你通過一系列問題,根據你的硬件設置(CPU、單 GPU、多 GPU、TPU 等)和訓練需求(混合精度、DeepSpeed 等)生成一個配置文件。

下面是引導中的一些問題

  • 問題1
    在這里插入圖片描述

它讓你選擇:你的訓練是在一臺機器上,還是多臺機器上?如果是在一臺機器上,是只用 CPU 跑,還是用多個 GPU、TPU 或其他專用硬件來跑?

  • 問題2
Do you wish to optimize your script with torch dynamo?[yes/NO]:

PyTorch Dynamo 是 PyTorch 2.0 引入的一個核心功能,旨在顯著提高 PyTorch 模型的運行速度。
Dynamo 會在運行時動態地分析你的 PyTorch 代碼,將 Python 級別的操作圖轉換為底層的、更高效的、優化的計算圖。

  • 問題3
    在這里插入圖片描述

當你使用 PyTorch Dynamo 進行代碼編譯時,你希望使用哪種“后端(backend)”來實際執行編譯優化?你可以把 Dynamo 理解為一個“編譯器前端”,它負責分析你的 PyTorch 代碼,把它翻譯成一個中間表示。而這些后端,就是真正把這個中間表示編譯成高效機器代碼并運行在特定硬件上的“編譯器后端”。

inductor (通常為默認和推薦) 這是 PyTorch 2.0 默認和推薦的編譯后端,也是最常用的。它能夠將 PyTorch 代碼編譯成高度優化的 C++/CUDA 內核。inductor 是 PyTorch 團隊為提高性能而設計的,它能針對 GPU(特別是 NVIDIA GPU)生成非常高效的代碼。

  • 問題4
Do you want to customize the defaults sent to torch.compile? [yes/NO]:

當你在 accelerate config 中選擇啟用 torch dynamo 優化后,accelerate 會在內部調用 PyTorch 的 torch.compile() 函數來對你的模型和訓練循環進行編譯。accelerate 默認會為 torch.compile() 使用一組合理的默認參數。但是,通過這個問題,它給你一個機會去修改這些默認值,以更精細地控制編譯行為。只有在你了解 torch.compile 參數的作用,并且有特定需求(如追求極致性能或解決特定兼容性問題)時,才考慮選擇 yes 并進行自定義配置。

  • 問題5
Do you want to use DeepSpeed? [yes/NO]:

DeepSpeed 是微軟開發的一個深度學習優化庫,旨在讓訓練超大型模型(如大型語言模型)變得更容易、更高效、更節省資源。它提供了多種高級優化技術. 選擇 NO (默認和常見選擇)

  • 問題6
What GPU(s) (by id) should be used for training on this machine as a comma-seperated list? [all]:

在這臺機器上,您希望使用哪些 GPU 進行訓練?請以逗號分隔的列表形式提供 GPU 的 ID。默認是使用所有 GPU,回車即可。

  • 問題7
Would you like to enable numa efficiency? (Currently only supported on NVIDIA hardware). [yes/NO]:

是否希望啟用 NUMA 效率優化? 并且它明確指出,這項功能目前僅支持 NVIDIA 硬件。如果您使用的是 NVIDIA GPU,并且您的機器是較新的、用于深度學習訓練的服務器(通常是雙路或多路 CPU),那么選擇 yes 可能會帶來性能提升。如果是一般的家用或開發用臺式機,通常選擇 NO 即可,性能提升不明顯。

  • 問題8
    在這里插入圖片描述

你是否希望使用混合精度(Mixed Precision)訓練,以及如果使用,要選擇哪種浮點精度?
在訓練過程中,同時使用 32 位浮點數 (FP32)16 位浮點數 (FP16 或 BF16) 兩種精度。現代 GPU(尤其是 NVIDIA 的 Tensor Core)對 FP16/BF16 計算有專門的硬件加速,這可以顯著提高訓練速度。

accelerate lunch命令

無論你是在單 GPU、多 GPU、多節點服務器(多臺機器)、還是 TPU 上訓練模型,你都可以使用 accelerate launch 命令來運行你的 Python 訓練腳本,而不用去處理底層的分布式通信、設備管理等復雜細節。

具體怎么實現的,超綱了!忽視,我就一臺機子,沒有分布式環境。

了解F5-TTS 訓練腳本

這是 F5-TTS 的訓練入口腳本 train.py,用于配置和啟動文本到語音模型的訓練。下面是模型訓練中涉及的部分代碼的閱讀筆記

1. Hydra 管理配置文件

@hydra.main(version_base="1.3", config_path=str(files("f5_tts").joinpath("configs")), config_name=None)
def main(model_cfg):# ...訓練流程代碼
  • 使用 Hydra 管理配置文件
  • config_path 指向配置文件目錄
  • config_name=None 允許通過命令行指定配置文件
  • model_cfg 參數自動加載配置內容

配置文件目錄是src/f5_tts/configs
config_nameF5TTS_v1_Base.yaml,是在運行命令時提供的

在這里插入圖片描述

2. 模型配置和初始化

model_cls = hydra.utils.get_class(f"f5_tts.model.{model_cfg.model.backbone}")
model_arc = model_cfg.model.arch
tokenizer = model_cfg.model.tokenizer
mel_spec_type = model_cfg.model.mel_spec.mel_spec_typeexp_name = f"{model_cfg.model.name}_{mel_spec_type}_{model_cfg.model.tokenizer}_{model_cfg.datasets.name}"

具體的配置參數如下
在這里插入圖片描述

下面是上圖中出現的參數筆記,需要的時候再看

Transformer相關參數

arch 這一部分定義了模型內部的核心“語音處理器”——Transformer 的工作方式。Transformer 是一種非常強大的神經網絡結構,擅長處理序列數據,在這里就是把文字序列變成語音特征序列。

  • dim: 1024 (維度/尺寸)
    決定了模型內部處理信息的“通道”數量,影響模型的容量和表達能力。 想象這是工廠里傳送帶的“寬度”。寬度越大,每次能處理的信息量就越多,模型可能學到更豐富的特征,但也會更耗資源。

  • depth: 22 (深度)
    Transformer 模型的層數,層數越多模型越深,理論上學習能力越強。想象這是傳送帶的“層數”。層數越多,信息被處理和提煉的次數就越多,模型能進行更復雜的轉換和學習。

  • heads: 16 (注意力頭數)
    Transformer 中的多頭注意力機制,每個頭可以關注輸入序列的不同方面,提高模型捕捉復雜關系的能力。想象這是工廠里有 16 雙“眼睛”,每雙眼睛都從不同的角度去看輸入的信息,然后把各自的發現整合起來。這樣能更全面地理解信息的不同部分之間的關系。

  • ff_mult: 2 (前饋網絡乘數)
    決定了 Transformer 中前饋神經網絡的維度,通常是 dim 的倍數,影響模型的復雜度和學習能力。想象在每層傳送帶上,信息經過處理后會送入一個小“加工車間”,這個數字就是這個車間的“放大倍數”。放大倍數越大,車間能處理的細節就越多。

  • text_dim: 512 (文本維度)
    定義了模型在處理文本輸入時,每個字符或詞語被轉換成的向量表示的維度。想象這是文字信息進入工廠時的“初始規格”或者“編碼長度”。

  • text_mask_padding: True (文本填充掩碼)
    在處理變長文本序列時,對填充(padding)部分應用掩碼,防止模型關注到無意義的填充信息。想象文字輸入會有長短不一的情況,為了讓所有輸入都一樣長,我們會在短的后面“補齊”一些空白。這個設定就是告訴機器,在處理時要“忽略”這些補齊的空白,不要把它們當作真正的文字信息。

  • qk_norm: null (查詢鍵歸一化)
    控制是否對 Transformer 中的查詢(query)和鍵(key)向量進行歸一化操作,這可能會影響訓練的穩定性和性能。

  • conv_layers: 4 (卷積層數)
    指的是在 Transformer 模塊中包含的卷積層數量,用于提取局部特征。在 Transformer 的核心處理之前或之后,信息還會經過 4 道“精細篩選”的工序,這些工序能捕捉到一些局部的、細粒度的特征。

  • pe_attn_head: null (位置編碼注意力頭)
    如果不為 null,它會為注意力機制提供額外的位置編碼信息,幫助模型更好地理解序列中元素的順序。

  • checkpoint_activations: False (檢查點激活)
    一種節省顯存(內存)的優化策略,通過在反向傳播時重新計算激活值而非存儲所有激活值來減少內存消耗,但會增加計算量。想象工廠里信息處理的每一步都會產生中間結果。如果設置為 True,就是說每處理完一步,我們都把這一步的中間結果“暫時存起來”,而不是直接丟棄。這樣雖然處理速度會慢一點,但是能省下很多用來記錄的“工作臺空間”(內存)。False 就是不存。

mel_spec (梅爾頻譜設定)

mel_spec 這一部分定義了語音最終輸出的梅爾頻譜的特性。梅爾頻譜是一種模擬人類聽覺感知的語音特征表示,是語音合成中非常關鍵的中間產物。

  • target_sample_rate: 24000 (目標采樣率)
    決定了生成語音的采樣率,影響語音的質量和文件大小。24000 Hz(24 kHz)是高保真語音常用的采樣率。 想象這是最終語音的“清晰度”或“細膩度”。每秒鐘取 24000 個聲音樣本,數字越大,聲音就越細膩、逼真。

  • n_mel_channels: 100 (梅爾通道數)
    梅爾頻譜的維度,表示梅爾濾波器組的數量。更多的梅爾通道可以捕捉更豐富的語音細節。 想象這是把聲音分解成不同頻率成分時,“過濾器”的數量。過濾器越多,對聲音頻率的分析就越細致、越準確。

  • hop_length: 256 (跳躍長度)
    計算梅爾頻譜時,相鄰幀之間采樣的跳躍步長。每隔 256 個聲音樣本就“截取”一段聲音來分析。這個值越小,分析就越密集,時間分辨率越高。

  • win_length: 1024 (窗口長度)
    計算梅爾頻譜時,每個分析窗口的長度。想象每次“截取”聲音來分析時,我們截取多長的一段。截取 1024 個樣本長度。

  • n_fft: 1024 (FFT 點數)
    這是聲音從時間域轉換到頻率域時的一種數學計算方式的參數。快速傅里葉變換 (FFT) 的點數,通常等于或大于 win_length,影響頻譜分辨率。

  • mel_spec_type: vocos (梅爾頻譜類型)
    指定用于生成梅爾頻譜的特定聲碼器或梅爾頻譜提取方法。不同的類型可能有不同的實現細節和音質特點。粗略理解這是生成梅爾頻譜的“方式”或“算法標準”。這里可以選擇使用 vocos 還是 bigvgan 這種算法。

3. 分詞器設置

if tokenizer != "custom":tokenizer_path = model_cfg.datasets.name
else:tokenizer_path = model_cfg.model.tokenizer_path
vocab_char_map, vocab_size = get_tokenizer(tokenizer_path, tokenizer)
  • 設置文本分詞器路徑
  • 加載詞匯表映射和大小
  • 支持默認和自定義分詞器選項
    由于是默認的分詞器是"pinyin", 取的是配置文件中配置的datasets中的name
    在這里插入圖片描述

Emilia_ZH_EN是默認的數據集,此處要修改為你數據集預處理生成的數據集名稱heitiane(黑天鵝)

datasets:name: heitiane

4. 數據集加載和訓練啟動

train_dataset = load_dataset(model_cfg.datasets.name, tokenizer, mel_spec_kwargs=model_cfg.model.mel_spec)
trainer.train(train_dataset,num_workers=model_cfg.datasets.num_workers,resumable_with_seed=666,  # 數據集隨機打亂的種子
)
  • 加載處理過的訓練數據集
  • 調用訓練器的 train 方法開始訓練
  • 配置數據加載并行度
  • 設置固定種子確保可復現性

訓練代碼就不看了,超綱了!

開始訓練模型

命令行訓練模型

訓練命令如下

# .yaml files are under src/f5_tts/configs directory
accelerate launch src/f5_tts/train/train.py --config-name F5TTS_v1_Base.yaml

或者指定某個配置項的值

# possible to overwrite accelerate and hydra config
accelerate launch --mixed_precision=fp16 src/f5_tts/train/train.py --config-name F5TTS_v1_Base.yaml ++datasets.batch_size_per_gpu=19200

由于訓練時間較長,所以需要放在后臺訓練,下面是訓練命令示例,請根據自己需要調整參數,其實所有的參數都能在命令行中指定,其他參數可以參考web ui章節給出的命令

nohup accelerate launch --mixed_precision=fp16 src/f5_tts/train/train.py --config-name F5TTS_v1_Base.yaml ++datasets.batch_size_per_gpu=4800 ++optim.epochs=30 ++optim.earning_rate=9.375e-6 > train_log.log 2>&1 &

web ui訓練模型

f5-tts_finetune-gradio --port 7860 --host 0.0.0.0 

啟動的時候最好加上nohup放在后臺跑

nohup f5-tts_finetune-gradio --port 7860 --host 0.0.0.0 2>&1 &

經過前面訓練腳本的學習,再看web界面會清晰很多,下面是官方的web使用教程視頻,就是教如何用web完成所有操作(數據集處理、模型訓練/微調、模型測試等)

https://github.com/SWivid/F5-TTS/discussions/143

web訓練模型的截圖,能夠看到訓練進度、以及很方便調整參數和查看當前訓練的效果。值得注意的是,web對文件的位置是有要求的,具體請根據后臺報錯信息查看。
在這里插入圖片描述

在使用的過程中,各種因素可能會導致訓練中斷,web中可以指定checkpoint功能,就算掛了,也能續上繼續訓練。當然命令行也支持,可以參考下面的命令。

web實際上用的微調命令大致如下

accelerate launch --mixed_precision=fp16 /home/ubuntu/F5-TTS/src/f5_tts/train/finetune_cli.py --exp_name F5TTS_v1_Base --learning_rate 1e-05 --batch_size_per_gpu 4898 --batch_size_type frame --max_samples 64 --grad_accumulation_steps 1 --max_grad_norm 1 --epochs 100 --num_warmup_updates 100 --save_per_updates 500 --keep_last_n_checkpoints 5 --last_per_updates 100 --dataset_name heitiane --finetune --tokenizer pinyin --log_samples

訓練模型遇到的問題

顯存不足

在這里插入圖片描述

這里有幾個概念需要弄清楚

batch_size 它指的是每次模型參數更新(一次反向傳播)所使用的訓練樣本數。相當于背單詞,讓你一次背完單詞書,腦子不夠用(顯存不夠多),當然搞不了。
epochs 它的含義是整個訓練集被模型完整“看”一遍的次數,相當于背多少次單詞書。

假設你有 1000 個訓練樣本,設置 batch_size = 100,每一步訓練處理 100 個樣本,每個epoch
需要重復 1000 / 100 = 10次(步數)。

默認的batch_size_per_gpu=38400太大了,顯存放不下,改小就夠了。我的顯存是16G,調到4800才能夠正常跑下去。將 batch_size_per_gpu 從 38400 降低到 4800 時,這是一個非常顯著的減少(減少到原來的 4800/38400=1/8)。理論上,如果其他因素不變,顯存占用會下降到原來的 1/8。這應該能有效解決遇到的 CUDA out of memory 錯誤。

但是這種大幅度減小 batch_size 對訓練過程和模型質量有重要的影響,其他的參數也需要相應地進行調整。

學習率 (Learning Rate) 調整

batch_size 越小,每次梯度更新的噪聲越大。如果學習率保持不變,模型在損失函數空間中的跳動會非常劇烈,可能導致:

  • 無法收斂: 模型在最優解附近震蕩,無法穩定下來。
  • 梯度爆炸: 極端情況下,損失值變成 NaN
  • 收斂到次優解: 即使收斂,也可能不如使用大批量時找到的最優解。

如何調整
遵循學習率線性縮放規則,如果原始 batch_size 是 38400,對應學習率是 7.5×10?5。
新的 batch_size 是 4800,是原來的 1/8。那么,新的學習率應該調整為:

7.5×10?5×(4800/38400)=7.5×10?5×(1/8)=0.9375×10?5=9.375×10?6

訓練命令加上 ++optim.earning_rate=9.375e-6即可

總訓練步數與 Epochs

如果您保持 epochs 不變,由于 batch_size 減小到 1/8,那么每個 epoch 內的訓練步數會增加 8 倍。這意味著總訓練步數會大幅增加。

如何權衡
  • 增加 epochs 盡管總步數增加了,但由于每次更新的梯度估計質量下降,模型可能需要更多的 epochs 才能達到與大 batch_size 相似的收斂程度。您可以嘗試增加 epochs,例如增加 2-4 倍,但需要觀察驗證損失,防止過擬合。

  • 梯度累積 (Gradient Accumulation): 強烈推薦。這是一種更優雅的解決方案,可以在保持小 batch_size 的同時,模擬更大的有效批量大小。如果您將 batch_size_per_gpu 從 38400 降到了 4800 (1/8),您可以設置 gradient_accumulation_steps = 8。這意味著模型每 8×4800=38400 幀才執行一次權重更新。這相當于在每次權重更新時,使用了與原來 38400 幀相同的有效批量大小

什么是梯度累積

首先要理解兩個概念,

  • 物理批次大小 (Physical Batch Size): 這是您實際能夠裝入 GPU 內存的批次大小。在本例中,您將其設為 4800 幀/GPU。
  • 有效批次大小 (Effective Batch Size): 這是模型在執行一次權重更新時,所“看到”的數據總量。它等于 物理批次大小 × 梯度累積步數

沒有梯度累積時(原始設置):
batch_size_per_gpu = 38400 幀。每次處理 38400 幀的數據,就執行一次梯度計算和一次權重更新。假設總訓練數據是 Total_Frames。總的權重更新步數 = Total_Frames / 38400

使用梯度累積后:

  • batch_size_per_gpu = 4800 幀。
  • gradient_accumulation_steps = 8
    模型會處理第一個 4800 幀的批次,計算梯度,但不更新權重,而是累積梯度。接著處理第二個 4800 幀的批次,計算梯度,將其累積到之前的梯度上。這個過程重復 8 次。當處理完第 8 個 4800 幀的批次后,累積的梯度就相當于一個包含了 8×4800=38400 幀的超級批次所計算出的梯度。此時,模型才執行一次權重更新

所以,雖然您每次 GPU 處理的物理數據量變小了(4800 幀),但是模型進行一次實際的權重更新,依然是基于 38400 幀的數據(有效批次大小)。因此,總的權重更新步數又變回了:Total_Frames / 38400。

梯度累積的好處是,可以保持梯度估計的“平滑性”與大批量接近,同時又降低了單次前向/反向傳播的顯存占用。如果使用梯度累積,那么 epochs 和學習率的調整就更接近于原始大批量的情況。

生成的全是噪音(??)

最初訓練了4個小時左右,從頭訓練的一個模型,用推理頁面測試,結果出來全是噪音。懷疑是訓練時間不夠或者自己哪里操作、參數有問題。改微調模型,在微調的web ui上測試是正常的,但是在推理的web ui上就又全是噪音了。可能是推理web ui上代碼有bug。由于訓練了4個小時的模型已經刪了,已經無從考證了。本來想仔細讀讀代碼看是不是bug的,但是時間不夠了,gpu服務器時間到期了。。。

數據集的語音質量是可以的,但是這個數據集是否適合用來訓練。這得去看看論文了解模型算法,還有對應的訓練數據集。而我本意是想得到一個穩定的某個音色,所以還是選擇微調吧。

F5-TTS 作為一個零樣本語音克隆模型,其核心能力在于無需特定說話人的訓練數據,即可通過短時參考音頻克隆音色。微調的意義在于將這種通用克隆能力進一步特化和優化,以達到更高水平的質量、穩定性、適應性

查看gpu使用情況

watch -n 1 nvidia-smi
  • 推理單個句子時候,顯存使用情況
    在這里插入圖片描述

  • 使用web ui微調時候顯存使用情況
    在這里插入圖片描述

web實際調用的微調命令如下:

accelerate launch --mixed_precision=fp16 /home/ubuntu/F5-TTS/src/f5_tts/train/finetune_cli.py --exp_name F5TTS_v1_Base --learning_rate 5e-06 --batch_size_per_gpu 4800 --batch_size_type frame --max_samples 64 --grad_accumulation_steps 8 --max_grad_norm 1 --epochs 100 --num_warmup_updates 100 --save_per_updates 500 --keep_last_n_checkpoints 5 --last_per_updates 100 --dataset_name test-demo --finetune --tokenizer pinyin --log_samples

微調結果

損失曲線(Loss Curve)是深度學習訓練過程中,損失函數值隨訓練迭代次數(或 Epochs)變化的圖形表示。它是評估模型訓練狀態和診斷問題(如欠擬合、過擬合、學習率不當)的最重要工具之一。

在 TensorBoard 或其他監控工具中觀察訓練損失的變化。在web ui中可以看到,訓練模型的頁面有個日志選項是可以選擇TensorBoard的,所以代碼是已經集成了TensorBoard了的。

安裝相關的庫

pip install tensorboard

然后在F5-tts項目根目錄執行下面的命令然后訪問頁面即可

tensorboard  --host 0.0.0.0 --logdir runs/ --port 8000

下圖是測試微調時候的截圖

在這里插入圖片描述

第一張圖可以看到損失曲線整體呈現下降趨勢。雖然有波動,但平滑后的曲線(淺色線)從大約 0.75 附近下降到了 0.6787。這表明模型正在學習!損失的下降是積極的信號,意味著模型正在改進其預測能力。但是由于時間太短了,得加長訓練時間!

第二張圖是典型的余弦退火(Cosine Annealing)學習率調度器的曲線。余弦退火是一種非常有效的學習率調度策略。它在訓練初期保持較高的學習率以快速探索損失空間,然后在后期平滑地降低學習率,使模型能夠更精細地收斂到最優解,并且有助于跳出局部最優。至于圖上能看出什么。。。沒研究

命令行去使用微調得到的模型

f5-tts_infer-cli --model F5TTS_v1_Base \
--ckpt_file /home/ubuntu/F5-TTS/ckpts/test-demo/my.safetensors \
--vocab_file /home/ubuntu/F5-TTS/data/test-demo_pinyin/vocab.txt \
--ref_audio  /home/ubuntu/tests/chapter3_5_blackswan_154.wav \
--ref_text "這個方向,請跟我來."  \
--output_file  /home/ubuntu/tests/tests/infer_cli_basic.wav  \
--gen_text "可惡,這狗bug浪費了我不少時間"

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/82284.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/82284.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/82284.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

安全可控的AI底座:燈塔大模型應用開發平臺全面實現國產信創兼容適配認證

國產信創產品兼容適配認證是為了支持和推動國產信息技術產品和服務的發展而設立的一種質量標準和管理體系。適配認證旨在確保相關產品在安全性、可靠性、兼容性等方面達到一定的標準&#xff0c;以滿足政府和關鍵行業對信息安全和自主可控的需求。 北京中煙創新科技有限公司&a…

初識Vue【1】

1.什么是Vue&#xff1a; Vue (讀音 /vju?/&#xff0c;類似于 **view**) 是一套用于構建用戶界面的**漸進式框架**。與其它大型框架不同的是&#xff0c;Vue 被設計為可以自底向上逐層應用。Vue 的核心庫只關注視圖層&#xff0c;不僅易于上手&#xff0c;還便于與第三方庫或…

Jest入門

快速入門 Jest中文文檔 | Jest中文網 1.下載&#xff1a;npm install --save-dev jest 2.創建 sum.js 文件&#xff1a; function sum(a, b) { return a b; } module.exports sum; 3.創建sum.test.js 的文件 const sum require(./sum); test(adds 1 2 to equal 3,…

Spring Boot企業級開發五大核心功能與高級擴展實戰

前言 在企業級應用開發中&#xff0c;Spring Boot已成為事實上的Java開發標準。本文將從企業實際需求出發&#xff0c;深入剖析Spring Boot五大必用核心功能&#xff0c;并擴展講解三項高級開發技能&#xff0c;幫助開發者掌握構建健壯、高效、易維護的企業級應用的必備技術。…

2025電工杯數學建模B題思路數模AI提示詞工程

我發布的智能體鏈接&#xff1a;數模AI扣子是新一代 AI 大模型智能體開發平臺。整合了插件、長短期記憶、工作流、卡片等豐富能力&#xff0c;扣子能幫你低門檻、快速搭建個性化或具備商業價值的智能體&#xff0c;并發布到豆包、飛書等各個平臺。https://www.coze.cn/search/n…

LabVIEW開發FPGA磁聲發射應力檢測系統

工業級磁聲發射應力檢測系統&#xff0c;針對傳統設備參數固定、靈活性不足的痛點&#xff0c;采用 Xilinx FPGA 與 LabVIEW 構建核心架構&#xff0c;實現激勵信號可調、多維度數據采集與實時分析。系統適用于鐵磁性材料應力檢測場景&#xff0c;具備高集成度、抗干擾性強、檢…

Java IO流學習指南:從小白到入門

Java的IO&#xff08;Input/Output&#xff09;流是處理數據輸入和輸出的基礎。無論是讀取文件、寫入文件&#xff0c;還是通過網絡傳輸數據&#xff0c;IO流都無處不在。對于剛接觸Java的新手&#xff0c;理解IO流可能會有些困惑&#xff0c;但別擔心&#xff0c;今天我們將一…

【后端高階面經:微服務篇】1、微服務架構核心:服務注冊與發現之AP vs CP選型全攻略

一、CAP理論在服務注冊與發現中的落地實踐 1.1 CAP三要素的技術權衡 要素AP模型實現CP模型實現一致性最終一致性&#xff08;Eureka通過異步復制實現&#xff09;強一致性&#xff08;ZooKeeper通過ZAB協議保證&#xff09;可用性服務節點可獨立響應&#xff08;支持分區存活…

QNAP NEXTCLOUD 域名訪問

我是用docker compose方式安裝的&#xff0c;雖然不知道是不是這么個叫法&#xff0c;廢話不多說。 背景&#xff1a;威聯通container station安裝了nextcloud和lucky&#xff0c;lucky進行的域名解析和反代 先在想安裝的路徑、數據存儲路徑、數據庫路徑等新建文件夾。再新建…

高級SQL技巧:窗口函數與復雜查詢優化實戰

高級SQL技巧&#xff1a;窗口函數與復雜查詢優化實戰 開篇&#xff1a;數據庫開發中的挑戰 在現代企業級應用中&#xff0c;數據庫不僅是存儲數據的核心組件&#xff0c;更是處理復雜業務邏輯的重要工具。然而&#xff0c;隨著數據量和并發請求的不斷增長&#xff0c;傳統的S…

《STL--list的使用及其底層實現》

引言&#xff1a; 上次我們學習了容器vector的使用及其底層實現&#xff0c;今天我們再來學習一個容器list&#xff0c; 這里的list可以參考我們之前實現的單鏈表&#xff0c;但是這里的list是雙向循環帶頭鏈表&#xff0c;下面我們就開始list的學習了。 一&#xff1a;list的…

docker中使用openresty

1.為什么要使用openresty 我這邊是因為要使用1Panel&#xff0c;第一個最大的原因&#xff0c;就是圖方便&#xff0c;比較可以一鍵安裝。但以前一直都是直接安裝nginx。所以需要一個過度。 2.如何查看openResty使用了nginx哪個版本 /usr/local/openresty/nginx/sbin/nginx …

vscode包含工程文件路徑

在 VSCode 中配置 includePath 以自動識別并包含上層目錄及其所有子文件夾&#xff0c;需結合通配符和相對/絕對路徑實現。以下是具體操作步驟及原理說明&#xff1a; 1. 使用通配符 ** 遞歸包含所有子目錄 在 c_cpp_properties.json 的 includePath 中&#xff0c;${workspac…

【排序算法】典型排序算法 Java實現

以下是典型的排序算法分類及對應的 Java 實現&#xff0c;包含時間復雜度、穩定性說明和核心代碼示例&#xff1a; 一、比較類排序&#xff08;通過元素比較&#xff09; 1. 交換排序 ① 冒泡排序 時間復雜度&#xff1a;O(n)&#xff08;優化后最優O(n)&#xff09; 穩定性&…

多模態大語言模型arxiv論文略讀(八十七)

MG-LLaVA: Towards Multi-Granularity Visual Instruction Tuning ?? 論文標題&#xff1a;MG-LLaVA: Towards Multi-Granularity Visual Instruction Tuning ?? 論文作者&#xff1a;Xiangyu Zhao, Xiangtai Li, Haodong Duan, Haian Huang, Yining Li, Kai Chen, Hua Ya…

塔能節能平板燈:點亮蘇州某零售工廠節能之路

在蘇州某零售工廠的運營成本中&#xff0c;照明能耗占據著一定比例。為降低成本、提升能源利用效率&#xff0c;該工廠與塔能科技攜手&#xff0c;引入塔能節能平板燈&#xff0c;開啟了精準節能之旅&#xff0c;并取得了令人矚目的成效。 一、工廠照明能耗困境 蘇州該零售工廠…

數據庫事務的四大特性(ACID)

一、前言 在現代數據庫系統中&#xff0c;事務&#xff08;Transaction&#xff09;是確保數據一致性和完整性的重要機制。事務的四大特性——原子性&#xff08;Atomicity&#xff09;、一致性&#xff08;Consistency&#xff09;、隔離性&#xff08;Isolation&#xff09;…

8 種快速易用的Python Matplotlib數據可視化方法

你是否曾經面對一堆復雜的數據&#xff0c;卻不知道如何讓它們變得直觀易懂&#xff1f;別慌&#xff0c;Python 的 Matplotlib 庫是你數據可視化的最佳伙伴&#xff01;它簡單易用、功能強大&#xff0c;能將枯燥的數字變成引人入勝的圖表。無論是學生、數據分析師還是程序員&…

springboot 控制層調用業務邏輯層,注入報錯,無法自動裝配 解決辦法

報錯&#xff1a; 解決&#xff1a;愿意是業務邏輯層&#xff0c;即service層的具體實現類沒有加注解Service導致的&#xff0c;加上解決了&#xff01;&#xff01;

如何提高獨立服務器的安全性?

獨立服務器相對于其它服務器來說&#xff0c;整體的硬件設備都是獨立的同時還有著強大的服務器性能&#xff0c;其中CPU設備能夠決定著服務器的運算能力&#xff0c;所以獨立服務器的安全性受到企業格外的重視&#xff0c;嚴重的話會給企業造成巨大的資金損失。 那么&#xff0…