从Llasa到Llasagna 🍕:微调LLaSA以生成意大利语和其他语言的语音

社区文章 发布于 2025年2月11日

LLaSA(“基于LLaMA的语音合成”)是一个最初为使用LLaMA进行大规模文本到语音合成而设计的框架。正如其文章中所述,该项目始于zhenye234开发的训练管道。在SebastianBodza的一个显著分支中,我们对脚本进行了一些进一步的修改,最近对模型进行了微调,以生成自然听起来的意大利语德语语音。

1. 背景:Llasa,一个基于统一LLM的TTS框架

Llasa 是一个基于 Transformer 的文本到语音系统,旨在与 Llama 等LLM范式完全对齐。与依赖独立声学模型、韵律预测器和声码器的传统TTS系统不同,Llasa 使用单个 Transformer自回归下一令牌预测框架中进行训练——类似于LLM处理文本的方式。这使得它具有更简单、更可扩展高度灵活的架构,可以针对各种语音合成任务进行微调。

1.1 Xcodec2在Llasa中的作用

Llasa背后的关键创新之一是其语音分词器,即 Xcodec2。该组件将原始音频波形转换为离散的语音令牌,使 Transformer 能够像处理文本一样建模语音。与使用多层向量量化 (VQ) 的传统音频编解码器不同,Xcodec2 采用单层向量量化器,用于高效、因果和自回归语音令牌建模。这种方法确保了所有语音特征——包括内容、韵律和音色——都捕获在令牌化表示中,从而实现高质量的语音合成。

如果您对Xcodec感兴趣,我写了一篇简短的X主题贴,详细介绍了其架构和基准。

1.2 扩展训练时间计算:更大的模型,更好的语音

Llasa 具有不断增长的模型大小(1B → 3B → 8B 参数),这些模型通过不断增加的数据大小(80k → 250k 小时)进行训练,从而更好地与类人语音模式对齐。更大的模型能够捕获更深层次的语义理解,从而生成更具情感表达力和上下文准确性的语音。

2. 使用xcodec2进行预处理和音频标记化

2.1 要求

要开始使用预处理管道,只需使用以下命令克隆存储库:

git clone https://github.com/Deep-unlearning/LLaSA_training.git
  • Python 包

    torch
    transformers
    wandb
    datasets
    accelerate>=0.26.0
    deepspeed
    xcodec2==0.1.3
    flash-attn
    liger_kernel
    bitsandbytes
    

2.2 硬件要求:

GPU 显存: 建议微调较小模型(例如,1B 参数)至少需要 24 GB 显存,而较大模型(例如,3B 或 8B)可能需要更多显存。

  1. 使用 `create_dataset.py` 进行预处理

    一个专门的预处理脚本 `create_dataset.py` 自动化了原始音频文件到标记化表示的转换。该脚本处理以下任务:

    • 音频转换:它加载原始录音并应用 xcodec2 编解码器(推荐版本 `xcodec2==0.1.3`)将波形压缩成简洁的令牌序列。在此阶段,编解码器提取重要的声学特征——例如音高、音调和节奏——确保保留音频信号的基本特征。
    • 数据对齐和格式化:音频标记化后,脚本会将这些标记与相应的文本数据对齐。通过将语音标记与文本标记(使用特殊标记表示边界,如 <|TEXT_GENERATION_START|><|SPEECH_GENERATION_START|>)结合,管道会创建一个统一的数据集。这种集成至关重要,因为它允许模型以无缝、端到端的方式学习文本输入与其相应语音输出之间的映射。

您可以使用自己的数据集

python create_dataset.py \\
--dataset_name your_dataset \\ # Load any dataset from Huggingface!
--output_dir output \\
  1. 使用 xcodec2 进行音频标记化

    xcodec2 编解码器是标记化过程的核心

    • 压缩和编码: xcodec2 通过将连续的语音波形转换为离散的令牌序列来有效地压缩音频。这种编码过程以紧凑的形式捕获显著的声学细节,减少了训练期间的计算负担,同时保留了原始音频的质量。
    • 统一令牌表示:编码后,通过向其数值添加偏移量来重新映射生成的语音令牌。此偏移量通常设置为文本词汇量的大小加上一些额外的特殊令牌。通过这样做,文本和语音令牌都集成到一个单一的令牌空间中。这种统一的表示使模型能够有效地学习跨模态相关性,因为它可以处理包含文本输入和关联语音输出的单个序列。

3. 微调Llasa

我们在更新的脚本中进行了一些改进,包括切换到 AutoLigerKernelForCausalLM 并集成 8 位 Adam 优化器。这对动态组合不仅提升了性能——这得益于诸如 Flash Attention 等功能——还有助于充分利用您的硬件效率。

model = AutoLigerKernelForCausalLM.from_pretrained(
    model_args.llm_model_name_or_path,
    cache_dir=model_args.cache_dir,
    attn_implementation="flash_attention_2",  # Fast, efficient attention computation
    torch_dtype='bfloat16'
)

# The optimizer setup using bitsandbytes' 8-bit Adam saves memory and speeds up training.
adam_8bit_optim = bnb.optim.Adam8bit(
    optimizer_grouped_parameters,
    betas=(training_args.adam_beta1, training_args.adam_beta2),
    eps=training_args.adam_epsilon,
    lr=training_args.learning_rate,
)

所以,即使你的 GPU 预算看起来有点“拮据”,这些增强功能也能确保你在不破产的情况下获得顶级性能!

我们使用 CML-TTS 意大利语子集进行微调。我们使用 CML-TTS 意大利语子集来微调我们的 Llasagna!您可以使用 Python 简单地运行训练脚本 train_tts.py,如果您有多个 GPU,则可以使用 torchrun。所有关键超参数都在 config.json 文件中指定,您可以随意调整它们以适应您的设置。

来试试这个模型吧!

您可以在这里尝试Llasagna:https://huggingface.co/spaces/Steveeeeeeen/Llasagna-1b-tts
以及在这里尝试Kartoffel:https://huggingface.co/spaces/SebastianBodza/Kartoffel-1B-v0.1-llasa-1b-tts

下一步是什么?

随着 Llasa-1b-multilingual 模型的发布,可能性是无限的!您还希望看到哪些其他语言、功能或改进?我们诚挚邀请您分享您的想法,并与我们一起探索文本到语音合成的新领域。让我们共同构建多语言 TTS 的未来!

致谢

  • SebastianBodza 对此项目的宝贵贡献。他在简化训练过程方面的改进在增强我们的 LLaSA 微调管道方面发挥了关键作用。

社区

写得真棒!

此评论已被隐藏

太棒了!!!我想知道您训练演示 Kartoffel 需要多少数据小时,我看到该模型可以讲短句。这个问题通常在其他模型中出现,即使我在使用德语测试 Llasa Multilanguage 时也是如此。

·

我使用了自己的自定义数据集,该数据集包含经过 Emilia 管道处理的许可音频 (cc-by-(sa))。主要是播客、开放教育资源讲座和新的 LibriVox 数据集。

总共有 250 万条记录,大约 7 千小时。

啊,错过了链接!干得好

📻 🎙️ 嘿,我为这篇博客文章制作了一个播客,快来听听吧!

该播客由 ngxson/kokoro-podcast-generator 生成,使用了 DeepSeek-R1 和 Kokoro-TTS

你好,非常感谢您关于 Llasa 的博客。我想微调这个模型。我注意到微调一个 1B 模型需要 24GB 的显存。请问能否估算一下微调 3B 和 8B 模型所需的显存量?此外,这些模型需要多少小时的 WAV 文件作为微调数据?

·

如果您离线处理数据,它就是一个标准的 Llama 模型,因此您可以进行比较。但是请记住,我们添加了新令牌。

Llasa 论文的作者也分享了一些带有在线处理的新训练脚本,适用于非 GPU 贫困者 :)。
https://github.com/zhenye234/LLaSA_training/tree/main/finetune

嗨!感谢您的文章!
我现在正在尝试将模型训练成乌兹别克语,我是 LLM 和 ML 领域的新手。目前,我遇到了运行模型的问题。

我已经用相应的数据集运行了两个脚本,根据文件夹大小,它已经正确训练了。
所以,问题是——我如何现在运行这个模型?
有什么建议、链接可以帮助我理解要搜索什么?

目前,在运行模型时,我得到了这样的结果:
"解码后的带有标记的片段:<|SPEECH_GENERATION_START|><|s_62770|><|s_63794|><|s_60710|><|s_43305|><|s_59942|><|s_15051|><|s_64054|><|s_62770|><|s_65078|><|s_61235|><|s_59702|><|s_55594|><|s_64822|><|s_59702|><|SPEECH_GENERATION_END|>
"

先谢谢了!

·
文章作者

嘿!
你走对了!你看到的输出仍然用特殊标记进行了标记化。要将其转换为自然语言文本,你需要使用你的分词器的解码函数。
你可以在这里找到一个示例:https://huggingface.co/HKUSTAudio/Llasa-1B

你好!你如何在没有输出音频的情况下生成推理?只是截断前N个样本吗?

你好,非常感谢你写了这篇很棒的文章。你训练了多少样本?

·

我使用了250万个样本,总共约7000小时

嗨!

“create_dataset.py”脚本在哪里可以找到?

感谢您的指南!我期待着尝试一下!

·

注册登录 发表评论