From 5b03366de0ab054d646b732a1b9280f2762b06cb Mon Sep 17 00:00:00 2001 From: kaleo <1311766212@qq.com> Date: Tue, 26 Mar 2024 11:11:08 +0800 Subject: [PATCH 1/2] translated zh-CN chapter 6 --- chapters/zh-CN/_toctree.yml | 39 +- chapters/zh-CN/chapter6/evaluation.mdx | 18 + chapters/zh-CN/chapter6/fine-tuning.mdx | 557 ++++++++++++++++++ chapters/zh-CN/chapter6/hands_on.mdx | 15 + chapters/zh-CN/chapter6/introduction.mdx | 21 + .../zh-CN/chapter6/pre-trained_models.mdx | 374 ++++++++++++ .../zh-CN/chapter6/supplemental_reading.mdx | 8 + chapters/zh-CN/chapter6/tts_datasets.mdx | 54 ++ 8 files changed, 1063 insertions(+), 23 deletions(-) create mode 100644 chapters/zh-CN/chapter6/evaluation.mdx create mode 100644 chapters/zh-CN/chapter6/fine-tuning.mdx create mode 100644 chapters/zh-CN/chapter6/hands_on.mdx create mode 100644 chapters/zh-CN/chapter6/introduction.mdx create mode 100644 chapters/zh-CN/chapter6/pre-trained_models.mdx create mode 100644 chapters/zh-CN/chapter6/supplemental_reading.mdx create mode 100644 chapters/zh-CN/chapter6/tts_datasets.mdx diff --git a/chapters/zh-CN/_toctree.yml b/chapters/zh-CN/_toctree.yml index fb952a1..9da7016 100644 --- a/chapters/zh-CN/_toctree.yml +++ b/chapters/zh-CN/_toctree.yml @@ -84,29 +84,22 @@ - local: chapter5/supplemental_reading title: 补充阅读 -#- title: 第6单元:由文字合成语音(TTS) -# sections: -# - local: chapter6/introduction -# title: 单元简介 -# - local: chapter6/overview -# title: 如何从文字合成语音 -# - local: chapter6/choosing_dataset -# title: 数据集选择 -# - local: chapter6/preprocessing -# title: 数据加载和预处理 -# - local: chapter6/pre-trained_models -# title: 文字转语音(TTS)预训练模型 -# - local: chapter6/evaluation -# title: 文字转语音(TTS)的评价指标 -# - local: chapter6/fine-tuning -# title: SpeechT5模型的微调 -# - local: chapter6/quiz -# title: 习题 -# quiz: 6 -# - local: chapter6/hands_on -# title: 实战练习 -# - local: chapter6/supplemental_reading -# title: 补充材料 +- title: 第六单元:从文本到语音 + sections: + - local: chapter6/introduction + title: 单元简介 + - local: chapter6/tts_datasets + title: 语音合成数据集 + - local: chapter6/pre-trained_models + title: 语音合成的预训练模型 + - local: chapter6/fine-tuning + title: 微调 SpeechT5 + - local: chapter6/evaluation + title: 评估语音合成模型 + - local: chapter6/hands_on + title: 实战练习 + - local: chapter6/supplemental_reading + title: 补充阅读 # #- title: 第7单元:音频到音频合成(ATA) # sections: diff --git a/chapters/zh-CN/chapter6/evaluation.mdx b/chapters/zh-CN/chapter6/evaluation.mdx new file mode 100644 index 0000000..06306ab --- /dev/null +++ b/chapters/zh-CN/chapter6/evaluation.mdx @@ -0,0 +1,18 @@ +# 评估语音合成模型 + +在训练期间,语音合成模型旨在优化平均平方误差损失(mean-square error loss,简称 MSE)或平均绝对误差(mean absolute error,简称 MAE), +这两者衡量的是预测的频谱图和真正的频谱图之间的差异。MSE 和 MAE 都鼓励模型最小化预测和目标频谱图之间的差异。然而,由于 TTS 是一种一对多映射问题, +即给定文本的输出频谱图有多种可能性,所以评估语音合成模型要比预想的困难得多。 + +与许多其他可以使用定量指标(如准确率、精确度)客观衡量的计算任务不同,评估 TTS 主要依赖于主观的人类分析。 + +评估 TTS 系统最常用方法之一是通过平均意见得分(Mean Opinion Scores,简称 MOS)进行定性评估。MOS 是一种主观评分系统, +允许人类评估者对合成语音的感知质量进行评分,评分范围从 1 到 5。这些得分通常通过听力测试收集,参与者听取并评价合成语音样本。 + +对于 TTS 评估来说,设置客观指标困难的主要原因之一是语音感知的主观性。不同的人类听众对语音的不同方面,包括发音、语调、自然度和清晰度, +有着各自的偏好和敏感度。用单一的数值捕捉这些感知细微差别是一项艰巨的任务。同时,人类评估的主观性使得比较和基准测试不同的 TTS 系统变得困难。 + +此外,这种评估可能会忽视语音合成的某些重要方面,如自然度、表达力和情感影响。这些质量难以客观量化,但在需要合成语音达到类人的品质和引发适当情感反应的应用中至关重要。 + +总之,由于缺乏一个真正客观的指标,评估语音合成模型是一项复杂的任务。最常用的评估方法,即平均意见得分(MOS),依赖于主观的人类分析。 +尽管 MOS 提供了对合成语音质量的宝贵意见,但它也引入了不确定性和主观性。 diff --git a/chapters/zh-CN/chapter6/fine-tuning.mdx b/chapters/zh-CN/chapter6/fine-tuning.mdx new file mode 100644 index 0000000..7cf5a8b --- /dev/null +++ b/chapters/zh-CN/chapter6/fine-tuning.mdx @@ -0,0 +1,557 @@ +# 微调 SpeechT5 + +现在您已经熟悉了语音合成任务和 SpeechT5 模型的内部工作原理,该模型是在英语数据上预训练的,让我们看看如何将其微调到另一种语言。 + +## 基础准备 + +如果您想复现这个示例,请确保您有一个 GPU。在笔记本中,您可以使用以下命令检查: + +```bash +nvidia-smi +``` + + + +在我们的示例中,我们将使用大约 40 小时的训练数据。如果您想使用 Google Colab 免费版的 GPU 复现,需要将训练数据量减少到大约 10-15 小时,并减少训练步骤的数量。 + + + +您还需要一些额外的依赖: + +```bash +pip install transformers datasets soundfile speechbrain accelerate +``` + +最后,不要忘记登录您的 Hugging Face 账户,以便您能够上传并与社区共享您的模型: + +```py +from huggingface_hub import notebook_login + +notebook_login() +``` + +## 数据集 + +在这个示例中,我们将使用 [VoxPopuli](https://huggingface.co/datasets/facebook/voxpopuli) 数据集的荷兰语(`nl`)子集。 +[VoxPopuli](https://huggingface.co/datasets/facebook/voxpopuli) 是一个大规模的多语言语音语料库,包含了 2009-2020 年欧洲议会事件的录音数据。 +它包含 15 种欧洲语言的带标签的音频-转写数据。虽然我们将使用荷兰语子集,但您可以自由选择其他子集。 + +这是一个语音识别(ASR)数据集,所以,如前所述,它不是训练 TTS 模型的最佳选择。然而,对于这个练习来说,它已经足够好了。 + +让我们加载数据: + +```python +from datasets import load_dataset, Audio + +dataset = load_dataset("facebook/voxpopuli", "nl", split="train") +len(dataset) +``` + +**输出:** + +```out +20968 +``` + +20968 条数据应该足以进行微调。输入 SpeechT5 的音频数据应具有 16 kHz 的采样率,所以要确保我们的数据集满足这一要求: + +```python +dataset = dataset.cast_column("audio", Audio(sampling_rate=16000)) +``` + +## 数据预处理 + +处理器包含了分词器和特征提取器,我们需要用它们来预处理训练数据。所以我们先定义要使用的模型检查点,并加载对应的处理器: + +```py +from transformers import SpeechT5Processor + +checkpoint = "microsoft/speecht5_tts" +processor = SpeechT5Processor.from_pretrained(checkpoint) +``` + +### 为 SpeechT5 分词进行文本清理 + +首先,为了处理文本,我们需要处理器的分词器部分,所以让我们来获取它: + +```py +tokenizer = processor.tokenizer +``` + +让我们看一个示例: + +```python +dataset[0] +``` + +**输出:** + +```out +{'audio_id': '20100210-0900-PLENARY-3-nl_20100210-09:06:43_4', + 'language': 9, + 'audio': {'path': '/root/.cache/huggingface/datasets/downloads/extracted/02ec6a19d5b97c03e1379250378454dbf3fa2972943504a91c7da5045aa26a89/train_part_0/20100210-0900-PLENARY-3-nl_20100210-09:06:43_4.wav', + 'array': array([ 4.27246094e-04, 1.31225586e-03, 1.03759766e-03, ..., + -9.15527344e-05, 7.62939453e-04, -2.44140625e-04]), + 'sampling_rate': 16000}, + 'raw_text': 'Dat kan naar mijn gevoel alleen met een brede meerderheid die wij samen zoeken.', + 'normalized_text': 'dat kan naar mijn gevoel alleen met een brede meerderheid die wij samen zoeken.', + 'gender': 'female', + 'speaker_id': '1122', + 'is_gold_transcript': True, + 'accent': 'None'} +``` + +您可能会注意到数据包含 `raw_text` 和 `normalized_text` 特征。在决定使用哪个特征作为文本输入时,需要注意的是 SpeechT5 分词器没有任何数字的词元。 +在 `normalized_text` 中,数字被写成文本。因此,它更合适,我们应该使用 `normalized_text` 作为输入文本。 + +因为 SpeechT5 是在英语上训练的,它可能无法识别荷兰语数据集中的某些字符。如果保持原样,这些字符将被转换为 `` 词元。 +然而,在荷兰语中,某些字符如 `à` 用于强调音节。为了保留文本的含义,我们可以将此字符替换为普通的 `a`。 + +要识别不支持的词元,使用 `SpeechT5Tokenizer` 提取数据集中所有独特字符,该分词器将字符视为词元。为此,我们将编写 `extract_all_chars` 映射函数, +该函数将所有数据样例的转写连接成一个字符串,然后转换为字符集。确保在 `dataset.map()` 中设置 `batched=True` 和 `batch_size=-1`,以便一次性获取所有转写并输入映射函数。 + +```py +def extract_all_chars(batch): + all_text = " ".join(batch["normalized_text"]) + vocab = list(set(all_text)) + return {"vocab": [vocab], "all_text": [all_text]} + + +vocabs = dataset.map( + extract_all_chars, + batched=True, + batch_size=-1, + keep_in_memory=True, + remove_columns=dataset.column_names, +) + +dataset_vocab = set(vocabs["vocab"][0]) +tokenizer_vocab = {k for k, _ in tokenizer.get_vocab().items()} +``` + +现在您有两组字符:一个来自数据集,另一个来自分词器。要识别数据集中任何不支持的字符,您可以取这两组的差集,结果将包含在数据集中而不在分词器中的字符。 + +```py +dataset_vocab - tokenizer_vocab +``` + +**输出:** + +```out +{' ', 'à', 'ç', 'è', 'ë', 'í', 'ï', 'ö', 'ü'} +``` + +为了处理上一步骤中识别的不支持字符,我们可以定义一个将这些字符映射到有效词元的函数。注意,分词器中的空格已经被替换为 `▁`,因此不需要单独处理。 + +```py +replacements = [ + ("à", "a"), + ("ç", "c"), + ("è", "e"), + ("ë", "e"), + ("í", "i"), + ("ï", "i"), + ("ö", "o"), + ("ü", "u"), +] + + +def cleanup_text(inputs): + for src, dst in replacements: + inputs["normalized_text"] = inputs["normalized_text"].replace(src, dst) + return inputs + + +dataset = dataset.map(cleanup_text) +``` + +现在我们处理好了文本中的特殊字符,是时候将注意力转移到音频数据上了。 + +### 说话人 + +VoxPopuli 数据集包含多个说话人的语音,但到底有多少呢?我们可以计算一下数据集中说话人的数量以及每个说话人贡献的数据量。 +数据集总共有 20,968 条数据,这些信息将帮助我们更好地了解数据中的说话人和数据样例的分布。 + +```py +from collections import defaultdict + +speaker_counts = defaultdict(int) + +for speaker_id in dataset["speaker_id"]: + speaker_counts[speaker_id] += 1 +``` + +通过绘制直方图,您可以了解每个说话人的数据量。 + +```py +import matplotlib.pyplot as plt + +plt.figure() +plt.hist(speaker_counts.values(), bins=20) +plt.ylabel("Speakers") +plt.xlabel("Examples") +plt.show() +``` + +
+ Speakers histogram +
+ +直方图显示,数据集中大约三分之一的说话人的数据少于 100 条,而大约十个说话人的数据超过 500 条。为了提高训练效率并平衡数据集,我们可以将数据限制在有 100 到 400 条数据的说话人之间。 + +```py +def select_speaker(speaker_id): + return 100 <= speaker_counts[speaker_id] <= 400 + + +dataset = dataset.filter(select_speaker, input_columns=["speaker_id"]) +``` + +让我们检查还剩多少个说话人: + +```py +len(set(dataset["speaker_id"])) +``` + +**输出:** + +```out +42 +``` + +让我们看看还剩多少条数据: + +```py +len(dataset) +``` + +**输出:** + +```out +9973 +``` + +您留下了不到 10,000 条数据,来自大约 40 个独特的说话人,这应该足够用了。 + +请注意,如果某些数据很长,一些看似数据样例量较少的说话人可能有比预想的更多的音频数据。然而,确定每个说话人的总音频量需要扫描整个数据集, +这是一个耗时的过程,涉及加载和解码每个音频文件。因此,我们在这里选择跳过这一步。 + +### 说话人嵌入 + +为了使 TTS 模型能够区分多个说话人,您需要为每条数据创建一个说话人嵌入。说话人嵌入是模型的一个额外输入,用于描述特定说话人的声音特征。 +要生成这些说话人嵌入,可以使用来自 SpeechBrain 的预训练模型 [spkrec-xvect-voxceleb](https://huggingface.co/speechbrain/spkrec-xvect-voxceleb)。 + +创建一个 `create_speaker_embedding()` 函数,该函数接受音频波形作为输入,并输出包含相应说话人嵌入的 512 维向量。 + +```py +import os +import torch +from speechbrain.pretrained import EncoderClassifier + +spk_model_name = "speechbrain/spkrec-xvect-voxceleb" + +device = "cuda" if torch.cuda.is_available() else "cpu" +speaker_model = EncoderClassifier.from_hparams( + source=spk_model_name, + run_opts={"device": device}, + savedir=os.path.join("/tmp", spk_model_name), +) + + +def create_speaker_embedding(waveform): + with torch.no_grad(): + speaker_embeddings = speaker_model.encode_batch(torch.tensor(waveform)) + speaker_embeddings = torch.nn.functional.normalize(speaker_embeddings, dim=2) + speaker_embeddings = speaker_embeddings.squeeze().cpu().numpy() + return speaker_embeddings +``` + +注意,`speechbrain/spkrec-xvect-voxceleb` 模型是在 VoxCeleb 数据集的英语语音上训练的,而这个示例训练的是荷兰语。 +虽然我们相信这个模型仍然可以为我们的荷兰语数据集生成合理的说话人嵌入,但这个假设可能不总是成立。 + +为了获得最佳结果,我们需要首先在目标语音上训练 X-Vector 模型。这将确保模型能够更好地捕捉荷兰语中存在的独特声音特征。如果您想训练自己的 X-向量模型, +可以参考 [此脚本](https://huggingface.co/mechanicalsea/speecht5-vc/blob/main/manifest/utils/prep_cmu_arctic_spkemb.py)。 + +### 处理数据集 + +最后,让我们将数据处理成模型能够读入的格式。创建一个 `prepare_dataset` 函数,输入单个示例并使用 `SpeechT5Processor` 对象来对输入文本进行分词,并将目标音频加载成对数梅尔谱。它还应该额外输入说话人嵌入。 + +```py +def prepare_dataset(example): + audio = example["audio"] + + example = processor( + text=example["normalized_text"], + audio_target=audio["array"], + sampling_rate=audio["sampling_rate"], + return_attention_mask=False, + ) + + # 去掉批量处理的维度 + example["labels"] = example["labels"][0] + + # 用 SpeechBrain 获取 X-Vector + example["speaker_embeddings"] = create_speaker_embedding(audio["array"]) + + return example +``` + +查看单个示例来验证处理是否正确: + +```py +processed_example = prepare_dataset(dataset[0]) +list(processed_example.keys()) +``` + +**输出:** + +```out +['input_ids', 'labels', 'stop_labels', 'speaker_embeddings'] +``` + +说话人嵌入应该是一个 512 维向量: + +```py +processed_example["speaker_embeddings"].shape +``` + +**输出:** + +```out +(512,) +``` + +标签应该是一个有 80 个 mel 频段的对数梅尔谱。 + +```py +import matplotlib.pyplot as plt + +plt.figure() +plt.imshow(processed_example["labels"].T) +plt.show() +``` + +
+ Log-mel spectrogram with 80 mel bins +
+ +注:如果您看不明白这个频谱图,可能是因为您习惯将低频放在底部,高频放在顶部。然而,在使用 matplotlib 库将频谱图作为图像绘制时,y 轴是反过来的,频谱图看起来是倒置的。 + +现在我们需要将处理函数应用于整个数据集。这将花费 5 到 10 分钟的时间。 + +```py +dataset = dataset.map(prepare_dataset, remove_columns=dataset.column_names) +``` + +您会看到一个警告说数据集中的某些数据长于模型能够处理的最大输入长度(600 词元),得从数据集中删除这些数据。在这里,我们更进一步,为了允许更大的批量大小,删除任何超过 200 词元的内容。 + +```py +def is_not_too_long(input_ids): + input_length = len(input_ids) + return input_length < 200 + + +dataset = dataset.filter(is_not_too_long, input_columns=["input_ids"]) +len(dataset) +``` + +**输出:** + +```out +8259 +``` + +接下来,把数据集分成基本的训练/测试子集: + +```py +dataset = dataset.train_test_split(test_size=0.1) +``` + +### 数据整理器 + +为了将多条数据组合成一个批次,您需要定义一个自定义数据整理器。这个整理器将使用填充词元填充较短的序列,确保所有示例都具有相同的长度。 +对于频谱图标签,填充部分将被特殊值 `-100` 替换。这个特殊值指示模型在计算频谱图的损失函数时忽略那部分频谱图。 + +```py +from dataclasses import dataclass +from typing import Any, Dict, List, Union + + +@dataclass +class TTSDataCollatorWithPadding: + processor: Any + + def __call__( + self, features: List[Dict[str, Union[List[int], torch.Tensor]]] + ) -> Dict[str, torch.Tensor]: + input_ids = [{"input_ids": feature["input_ids"]} for feature in features] + label_features = [{"input_values": feature["labels"]} for feature in features] + speaker_features = [feature["speaker_embeddings"] for feature in features] + + # 把输入数据和生成目标整合进一个批次 + batch = processor.pad( + input_ids=input_ids, labels=label_features, return_tensors="pt" + ) + + # 把填充词元换成 -100 来正确地忽略这一部分的损失函数 + batch["labels"] = batch["labels"].masked_fill( + batch.decoder_attention_mask.unsqueeze(-1).ne(1), -100 + ) + + # 在微调时用不上,删了 + del batch["decoder_attention_mask"] + + # 把目标长度下调到 reduction factor 的整数倍 + if model.config.reduction_factor > 1: + target_lengths = torch.tensor( + [len(feature["input_values"]) for feature in label_features] + ) + target_lengths = target_lengths.new( + [ + length - length % model.config.reduction_factor + for length in target_lengths + ] + ) + max_length = max(target_lengths) + batch["labels"] = batch["labels"][:, :max_length] + + # 加上说话人嵌入 + batch["speaker_embeddings"] = torch.tensor(speaker_features) + + return batch +``` + +在 SpeechT5 中,模型的解码器部分的输入减少了 2 倍(reduction factor)。换句话说,它抛弃了目标序列中每两步中的一步。然后,解码器预测一个两倍长度的序列。 +由于原来的目标序列长度可能是奇数,数据整理器会确保将批次的最大长度调整为 2 的倍数。 + +```py +data_collator = TTSDataCollatorWithPadding(processor=processor) +``` + +## 训练模型 + +从与处理器相同的检查点加载预训练模型: + +```py +from transformers import SpeechT5ForTextToSpeech + +model = SpeechT5ForTextToSpeech.from_pretrained(checkpoint) +``` + +`use_cache=True` 选项与梯度检查点不兼容。我们在训练时禁用这个选项,并在生成时重新启用缓存以加快推理: + +```py +from functools import partial + +# 在训练时禁用缓存 +model.config.use_cache = False + +# 设置语言和任务准备推理,并重新启用缓存 +model.generate = partial(model.generate, use_cache=True) +``` + +定义训练参数。这里我们在训练过程中不计算任何评估指标,我们将在本章稍后讨论评估。这里,我们先只关注损失函数: + +```python +from transformers import Seq2SeqTrainingArguments + +training_args = Seq2SeqTrainingArguments( + output_dir="speecht5_finetuned_voxpopuli_nl", # 改成您选择的仓库名 + per_device_train_batch_size=4, + gradient_accumulation_steps=8, + learning_rate=1e-5, + warmup_steps=500, + max_steps=4000, + gradient_checkpointing=True, + fp16=True, + evaluation_strategy="steps", + per_device_eval_batch_size=2, + save_steps=1000, + eval_steps=1000, + logging_steps=25, + report_to=["tensorboard"], + load_best_model_at_end=True, + greater_is_better=False, + label_names=["labels"], + push_to_hub=True, +) +``` + +实例化 `Trainer` 对象并将模型、数据集和数据整理器传递给它。 + +```py +from transformers import Seq2SeqTrainer + +trainer = Seq2SeqTrainer( + args=training_args, + model=model, + train_dataset=dataset["train"], + eval_dataset=dataset["test"], + data_collator=data_collator, + tokenizer=processor, +) +``` + +有了这个,我们就准备开始训练了!训练将花费几个小时。由于 GPU 不同,当您开始训练时,可能会遇到 CUDA 报“out-of-memory”(显存不足)的错误。这时,您可以尝试将 `per_device_train_batch_size` 两倍两倍地减少,并将 `gradient_accumulation_steps` 增加到两倍以补偿。 + +```py +trainer.train() +``` + +将最终的模型上传到 🤗 Hub: + +```py +trainer.push_to_hub() +``` + +## 推理 + +一旦您微调了一个模型,您就可以使用它进行推理!从 🤗 Hub 加载模型(记得在以下代码片段中使用您的账号名): + +```py +model = SpeechT5ForTextToSpeech.from_pretrained( + "您的账号/speecht5_finetuned_voxpopuli_nl" +) +``` + +选择一个示例,这里我们将从测试数据集中取一个。获取说话人嵌入。 + +```py +example = dataset["test"][304] +speaker_embeddings = torch.tensor(example["speaker_embeddings"]).unsqueeze(0) +``` + +定义一些输入文本并对它进行分词。 + +```py +text = "hallo allemaal, ik praat nederlands. groetjes aan iedereen!" +``` + +预处理输入文本: + +```py +inputs = processor(text=text, return_tensors="pt") +``` + +实例化一个声码器并生成语音: + +```py +from transformers import SpeechT5HifiGan + +vocoder = SpeechT5HifiGan.from_pretrained("microsoft/speecht5_hifigan") +speech = model.generate_speech(inputs["input_ids"], speaker_embeddings, vocoder=vocoder) +``` + +准备好听结果了吗? + +```py +from IPython.display import Audio + +Audio(speech.numpy(), rate=16000) +``` + +用这个模型在新语言上获得的满意结果可能很有挑战性。说话人嵌入的质量可能是一个重要因素。由于 SpeechT5 是使用英语 X-Vector 预训练的,它在使用英语说话人嵌入时表现最佳。如果合成的语音听起来效果不好,尝试使用不同的说话人嵌入。 + +增加训练时长也可能提高结果的质量。但即便不继续训练,语音也显然是荷兰语而不是英语,并且它确实学到了说话人的声音特征(与示例中的原始音频相比较)。另一个可以试验的是模型的配置。例如,尝试使用 `config.reduction_factor = 1` 来看是否能改善结果。 + +在下一节中,我们将讨论如何评估语音合成模型。 diff --git a/chapters/zh-CN/chapter6/hands_on.mdx b/chapters/zh-CN/chapter6/hands_on.mdx new file mode 100644 index 0000000..0c83d11 --- /dev/null +++ b/chapters/zh-CN/chapter6/hands_on.mdx @@ -0,0 +1,15 @@ +# 实战练习 + +在这个单元中,我们探讨了语音合成的音频任务,讨论了现有的 Datasets、预训练模型以及为新语言微调 SpeechT5 的细节。 + +正如您所见,为语音合成任务微调模型在资源较少的情况下可能比较有挑战性。同时,评估语音合成模型也不是一件容易的事。 + +因此,这个实践练习将侧重于练习技能,而不是达到特定的指标。 + +您在这个任务中的目标是在您选择的数据集上微调 SpeechT5。您可以从相同的 `voxpopuli` 数据集中选择另一种语言,或者选择本单元中列出的任何其他数据集。 + +注意训练数据的大小!如果在 Google Colab 免费版的 GPU 上训练,我们推荐将训练数据限制在大约 10-15 小时。 + +微调完成后,请上传到 Hub 来分享您的模型,并加上 `text-to-speech` 模型标签,可以通过 kwargs 或者在 Hub UI 中设置。 + +请记得,这个练习的主要目的是为您提供充分的实践,让您锻炼学到的技能并深入理解语音合成的音频任务。 diff --git a/chapters/zh-CN/chapter6/introduction.mdx b/chapters/zh-CN/chapter6/introduction.mdx new file mode 100644 index 0000000..97a78cd --- /dev/null +++ b/chapters/zh-CN/chapter6/introduction.mdx @@ -0,0 +1,21 @@ +# 第六单元:从文本到语音 + +在上一个单元中,您学习了如何使用 Transformers 将语音转换成文本。现在,让我们换一个方向,看看该如何将输入的文本转换成听起来像人类语音的音频输出。 + +我们在这个单元将学习的任务称为“语音合成”(Text-to-Speech,简称 TTS),要将文本转换为可听的人类语音。这样的模型具有广泛的潜在应用: + +* 辅助 app:可以利用这些模型帮助视觉障碍人士通过声音媒介访问数字内容。 +* 有声读物朗读:将文本的书籍转换成音频形式,使比起读喜欢听的或阅读有困难的人们能更容易地欣赏文学作品。 +* 虚拟助手:TTS 模型是 Siri、Google Assistant 或 Amazon Alexa 等虚拟助手的基本组成部分。它们使用分类模型捕捉到唤醒词,并使用 ASR(语音识别)模型处理了您的请求之后,就可以使用 TTS 模型来回应您的问题。 +* 娱乐、游戏和语言学习:为您的 NPC(非玩家角色)赋予声音,叙述游戏事件,或帮助语言学习者了解单词和短语的正确发音和语调。 + +这些只是一些例子,我相信您还可以想象出更多!然而,能力越大责任越大,需要强调 TTS 模型有可能被用于恶意目的。例如,有了足够的声音样本, +不法分子可能会合成出足以以假乱真的假语音,未经授权使用他人的声音,甚至用于诈骗。如果想要收集数据以微调自己的系统,请仔细考虑隐私和知情同意。 +获取声音数据应获得个人的明确同意,确保他们理解声音在 TTS 系统中使用的目的、范围和潜在风险。请负责任地使用语音合成技术。 + +在这一章中,我们将介绍: + +* [适合训练语音合成模型的数据集](tts_datasets) +* [语音合成的预训练模型](pre-trained_models) +* [在一门新语言上微调 SpeechT5](fine-tuning) +* [评估语音识别模型的性能](evaluation) diff --git a/chapters/zh-CN/chapter6/pre-trained_models.mdx b/chapters/zh-CN/chapter6/pre-trained_models.mdx new file mode 100644 index 0000000..84112ec --- /dev/null +++ b/chapters/zh-CN/chapter6/pre-trained_models.mdx @@ -0,0 +1,374 @@ +# 语音合成的预训练模型 + +与 ASR(语音识别)和音频分类任务相比,语音合成的预训练模型检查点明显较少。在 🤗 Hub 上,您可以找到近 300 个适合的检查点。 +在这些预训练模型中,我们将重点关注两种在 🤗 Transformers 库中开箱即用的架构——SpeechT5 和 Massive Multilingual Speech(MMS)。 +在本节中,我们将探索如何在 Transformers 库中使用这些预训练模型进行 TTS(语音合成)。 + +## SpeechT5 + +[SpeechT5](https://arxiv.org/abs/2110.07205) 是由 Microsoft 的 Junyi Ao 等人发布的模型,它能够处理一系列语音任务。虽然本单元中我们关注的是文本转语音, +但这个模型还可以用于语音转文本的任务(语音识别或说话人识别),以及语音转语音的任务(例如语音增强或变声器)。这是模型设计和预训练的方式所决定的。 + +SpeechT5 的核心是一个常规的 Transformer 编码器-解码器模型。就像任何其他 Transformer 一样,编码器-解码器网络使用隐藏表示来模拟序列到序列的转换。这个 Transformer 骨架对 SpeechT5 支持的所有任务都是相同的。 + +除此之外,SpeechT5 还有六个模态特定(语音/文本)的预处理网络(_pre-nets_)和后处理网络(_post-nets_)。输入的语音或文本(取决于任务)通过相应的预处理网络被预处理, +以获得 Transformer 可以使用的隐藏表示。然后,Transformer 的输出被送进后处理网络,转化为目标模态的输出。 + +以下是该模型的架构(图片来源于原始论文): + +
+ SpeechT5 architecture from the original paper +
+ +SpeechT5 首先使用大规模的未标注语音和文本数据进行预训练,以获得不同模态的统一表示。在预训练阶段,所有的预处理网络和后处理网络同时使用。 + +预训练之后,将整个编解码器骨架针对每个单独任务进行微调。在这个步骤中,只有与特定任务相关的预处理和后处理网络被采用。 +例如,要使用 SpeechT5 进行语音合成,您需要选择文本编码器预处理网络来处理文本输入,以及语音解码器的预处理和后处理网络来处理语音输出。 + +这样就可以获得多个针对不同语音任务微调的模型,它们都受益于最开始在未标注数据上预训练时学到的知识。 + + + +尽管模型开始时使用的是同一个预训练模型的相同权重集,但微调后的最终版本会大不相同。所以,您不能仅仅通过更换预处理和后处理网络, +就将一个微调后的 ASR 模型转换为一个可用的 TTS 模型。SpeechT5 很灵活,但还没有灵活到这个程度 QwQ + + + +让我们具体看看 SpeechT5 在 TTS(文本到语音)任务中使用的预/后处理网络是什么: + +* 文本编码器预处理网络(Text encoder pre-net):一个文本嵌入层,将文本词元映射到编码器可以读入的隐藏表示。这与 NLP 模型(如 BERT)中的做法类似。 +* 语音解码器预处理网络(Speech decoder pre-net):这个网络以对数梅尔谱(log mel spectrogram)为输入,并使用一连串的线性层来将频谱图压缩成隐藏表示。 +* 语音解码器后处理网络(Speech decoder post-net):这个网络预测一个残差来添加到输出的频谱图中,用于优化模型输出的结果。 + +结合起来,这就是 SpeechT5 在语音合成中使用的架构: + +
+ SpeechT5 architecture for TTS +
+ +正如您所看到的,输出是一个对数梅尔谱,而不是最终的波形。如果您记得,我们在 [第 3 单元](../chapter3/introduction#spectrogram-output) 简要讨论过这个话题。 +生成语音的模型的输出常常是对数梅尔谱,还需要通过一个额外的神经网络,即声码器(vocoder),才能转换成波形。 + +让我们看看具体应该怎么做。 + +首先,让我们从 🤗 Hub 加载微调过的 TTS SpeechT5 模型,以及用于分词和特征提取的处理器对象: + +```python +from transformers import SpeechT5Processor, SpeechT5ForTextToSpeech + +processor = SpeechT5Processor.from_pretrained("microsoft/speecht5_tts") +model = SpeechT5ForTextToSpeech.from_pretrained("microsoft/speecht5_tts") +``` + +接下来,给输入的文本分词。 + +```python +inputs = processor(text="Don't count the days, make the days count.", return_tensors="pt") +``` + +SpeechT5 TTS 模型不仅限于生成一种音色的语音。相反,它能够使用所谓的“说话人嵌入”(speaker embeddings)来模仿各种特定说话人的声音特征。 + + + +说话人嵌入(Speaker embeddings)是一个固定大小的向量,不论音频的长度如何都能用一种紧凑的方式表示说话人的身份。这些向量捕获了关于说话人的音色、口音、 +语调以及其他独特特征的关键信息,这些特征区分了不同的说话人。这样的嵌入有说话人验证(speaker verification)、说话人分离(speaker diarization)、 +说话人识别(speaker identification)等多种应用。生成说话人嵌入时最常用的技术包括: + +* I-Vectors(身份向量):I-Vectors 基于高斯混合模型(Gaussian mixture model,GMM)。它属于无监督学习,用一个特定说话人的 GMM 的统计数据得出一个低维度、固定大小的向量来代表说话人。 +* X-Vectors:X-Vectors 利用了深度神经网络(DNN),通过整合时间维度的上下文来捕获帧级的说话人信息。 + +[X-Vectors](https://www.danielpovey.com/files/2018_icassp_xvectors.pdf) 是 SOTA(state-of-the-art)的方法,在测试集上的表现优于 I-Vectors。 +X-Vectors 是深度神经网络产生的:它被训练以区分不同说话人,并将长度不一的语音音频映射到固定维度的嵌入。您还可以加载提前计算好的 X-Vector 说话人嵌入,它封装好了某个特定说话人的说话特征。 + + + +让我们从 Hub 上的数据集中加载一个说话人嵌入。这些嵌入是使用 [CMU ARCTIC 数据集](http://www.festvox.org/cmu_arctic/) 和 [这个脚本](https://huggingface.co/mechanicalsea/speecht5-vc/blob/main/manifest/utils/prep_cmu_arctic_spkemb.py) 获得的,这里使用任何 X-Vector 嵌入都可以。 + +```python +from datasets import load_dataset + +embeddings_dataset = load_dataset("Matthijs/cmu-arctic-xvectors", split="validation") + +import torch + +speaker_embeddings = torch.tensor(embeddings_dataset[7306]["xvector"]).unsqueeze(0) +``` + +说话人嵌入是形状为 (1, 512) 的张量,我们选的这个说话人嵌入描述的是一个女声。 + +此时,我们已经有足够的输入来生成对数梅尔谱作为输出,您可以这样做: + +```python +spectrogram = model.generate_speech(inputs["input_ids"], speaker_embeddings) +``` + +这会输出一个形状为 (140, 80) 的张量,包含对数梅尔谱。第一维是序列长度,可能每次运行代码它的取值都会不一样, +因为语音解码器预处理网络(pre-net)总是对输入序列用 dropout。这给生成的语音添加了一些随机变化。 + +如果我们想生成语音波形,我们还需要指定一个用于把频谱图转换为波形的声码器(vocoder)。理论上,您可以使用任何适用于 80-bin 梅尔谱的声码器。 +🤗 Transformers 提供了一个基于 HiFi-GAN 的声码器,可以很方便地使用。其权重由 SpeechT5 的原作者友情提供。 + + + +[HiFi-GAN](https://arxiv.org/pdf/2010.05646v2.pdf) 是一种用于高保真语音合成的 SOTA 生成对抗网络(GAN)。它能够根据输入的频谱图生成高品质且逼真的音频波形。 + +总的来说,HiFi-GAN 由一个生成器和两个鉴别器组成。生成器是一个全卷积神经网络,它以梅尔谱作为输入并学习产生原始音频波形。 +鉴别器负责区分真实音频和生成音频。这两个鉴别器关注音频的不同方面。 + +HiFi-GAN 在大量高品质音频数据上进行训练。它采用所谓的对抗训练,其中生成器和鉴别器网络相互竞争。最初,生成器产生的音频质量较低, +鉴别器可以轻松地将其与真实音频区分开。随着训练的进行,生成器改进其输出,目标是欺骗鉴别器。反过来,鉴别器也学会更准确地区分真实和生成的音频。 +这种对抗性反馈循环帮助两个网络随时间推移提升性能。最终,HiFi-GAN 学会生成高保真音频,精密地模仿训练数据的特征。 + + + +加载声码器就像加载任何其他 🤗 Transformers 模型一样简单。 + +```python +from transformers import SpeechT5HifiGan + +vocoder = SpeechT5HifiGan.from_pretrained("microsoft/speecht5_hifigan") +``` + +现在您需要做的就是在生成语音时将其作为参数传递,输出将自动转换为语音波形。 + +```python +speech = model.generate_speech(inputs["input_ids"], speaker_embeddings, vocoder=vocoder) +``` + +让我们来听听输出的结果。SpeechT5 使用的采样率始终是 16 kHz。 + +```python +from IPython.display import Audio + +Audio(speech, rate=16000) +``` + +真不错! + +请随意使用 SpeechT5 语音合成 demo 探索其他声音,尝试各种各样的输入。请注意,该预训练检查点仅支持英语: + + + +## Bark + +Bark 是 Suno AI 提出的基于 transformer 的语音合成模型,见 [suno-ai/bark](https://github.com/suno-ai/bark)。 + +与 SpeechT5 不同,Bark 直接生成语音波形,无需在推理过程中使用单独的声码器——它已经集成了这一功能。这种功能是通过使用 [`Encodec`](https://huggingface.co/docs/transformers/main/en/model_doc/encodec) 实现的,它既是编解码器也是压缩工具。 + +借助 `Encodec`,您可以将音频压缩成轻量级格式以减少内存使用,然后再解压缩以恢复原始音频。这个压缩过程由 8 个 codebook 帮助完成, +每个 codebook 都由整数向量组成。可以将这些 codebook 视为音频的整数形式表示或嵌入,并且每个后续的 codebook 都能在前一个的基础上提高音频重建的质量。 +由于 codebook 是整数向量,它们可以被 transformer 模型学习,而 transformer 在这项任务上非常高效。这正是 Bark 被训练去做的任务。 + +更具体地说,Bark 由 4 个主要的模型组成: + +- `BarkSemanticModel`(也称为“文本”模型):一个因果自回归的 transformer 模型,它接收分词后的文本作为输入,并预测表示文本含义的语义文本词元。 +- `BarkCoarseModel`(也称为“粗粒度声学”模型):一个因果自回归的 transformer,它接收 `BarkSemanticModel` 模型的结果作为输入,预测 EnCodec 所需的前两个音频 codebook 。 +- `BarkFineModel`(“细粒度声学”模型),这次是一个非因果自编码 transformer,它基于之前生成的所有 codebook 嵌入,迭代地预测下一个 codebook 。 +- 在 `EncodecModel` 预测了所有 codebook 通道后,Bark 使用它来解码输出音频数组。 + +需要注意的是,前三个模块中的每一个都支持说话人嵌入作为条件参数,以根据预特定的预设调整输出的声音。 + +Bark 是一个高度可控的语音合成模型,意味着您可以调整各种各样的设置,下面我们将见证这一功能。 + +在一切开始之前,我们需要加载模型及其处理器。 + +处理器在这里有两方面的作用: + +1. 它用于对输入文本进行分词,即将其切割成模型可以理解的小片段。 +2. 它存储说话人嵌入,即可以调节生成结果的声音预设。 + +```python +from transformers import BarkModel, BarkProcessor + +model = BarkModel.from_pretrained("suno/bark-small") +processor = BarkProcessor.from_pretrained("suno/bark-small") +``` + +Bark 非常多功能,可以通过处理器加载一个 [说话人嵌入库](https://suno-ai.notion.site/8b8e8749ed514b0cbf3f699013548683?v=bc67cff786b04b50b3ceb756fd05f68c) 中的说话人嵌入来调节它产生的声音。 + +```python +# 设置说话人嵌入 +inputs = processor("This is a test!", voice_preset="v2/en_speaker_3") + +speech_output = model.generate(**inputs).cpu().numpy() +``` + + + +它还可以生成随时可用的多语言语音,例如法语和中文。您可以在 [这里](https://huggingface.co/suno/bark) 找到支持的语言列表。与下面讨论的 MMS 不同,它不需要指定所使用的语言,只需将输入文本调整为相应的语言即可。 + +```python +# 试试法语,同时我们也来用一个法语说话人嵌入 +inputs = processor("C'est un test!", voice_preset="v2/fr_speaker_1") + +speech_output = model.generate(**inputs).cpu().numpy() +``` + + +该模型还可以生成**非语言交流**,例如笑、叹息和哭泣。 您只需使用相应的提示修改输入文本,例如 `[clears throat]`、`[laughter]` 或 `...`。 + +```python +inputs = processor( + "[clears throat] This is a test ... and I just took a long pause.", + voice_preset="v2/fr_speaker_1", +) + +speech_output = model.generate(**inputs).cpu().numpy() +``` + + + +Bark 甚至可以产生音乐。您可以通过在单词周围添加 ♪ 音符 ♪ 来做到这一点。 + +```python +inputs = processor( + "♪ In the mighty jungle, I'm trying to generate barks.", +) + +speech_output = model.generate(**inputs).cpu().numpy() +``` + + + +除了所有这些功能之外,Bark 还支持批处理,这意味着您可以同时处理多个文本条目,但代价是更密集的计算。在某些硬件(例如 GPU)上,批处理可以加快整体生成速度,这意味着一次性生成所有样本比逐个生成样本更快。 + +让我们尝试生成一些示例: + +```python +input_list = [ + "[clears throat] Hello uh ..., my dog is cute [laughter]", + "Let's try generating speech, with Bark, a text-to-speech model", + "♪ In the jungle, the mighty jungle, the lion barks tonight ♪", +] + +# 设置一个说话人嵌入 +inputs = processor(input_list, voice_preset="v2/en_speaker_3") + +speech_output = model.generate(**inputs).cpu().numpy() +``` + +让我们来一个一个听这些输出。 + +第一个: + +```python +from IPython.display import Audio + +sampling_rate = model.generation_config.sample_rate +Audio(speech_output[0], rate=sampling_rate) +``` + + + +第二个: + +```python +Audio(speech_output[1], rate=sampling_rate) +``` + + + +第三个: + +```python +Audio(speech_output[2], rate=sampling_rate) +``` + + + + + +Bark 与其他 🤗 Transformers 模型一样,只需几行代码即可针对速度和内存影响进行优化。要了解具体操作方法,请单击 [此 colab 演示笔记本](https://colab.research.google.com/github/ylacombe/notebooks/blob/main/Benchmark_Bark_HuggingFace.ipynb)。 + + + +## Massive Multilingual Speech (MMS) + +如果您需要一个非英语的预训练模型怎么办?Massive Multilingual Speech(MMS,大规模多语种语音)是另一个涵盖多种语音任务的模型,并且,它支持大量的语言。比方说,它可以合成超过 1,100 种语言的语音。 + +MMS 的语音合成是基于 [VITS Kim et al., 2021](https://arxiv.org/pdf/2106.06103.pdf) 的,它是最先进的 TTS 方法之一。 + +VITS 是一个语音生成网络,可以将文本转换成语音波形。它的工作方式类似于条件变分自编码器(conditional variational auto-encoder),从输入文本估计音频特征。首先,生成用频谱图表示的声学特征。 +然后,使用改编自 HiFi-GAN 的转置卷积层解码出波形。在推理过程中,文本编码被上采样并使用流模块(flow module)和 HiFi-GAN 解码器转换成波形。像 Bark 一样,这里不需要声码器(vocoder),因为已经直接生成波形了。 + + + +MMS 模型最近才被添加到 🤗 Transformers 中,所以您需要从源代码安装该库: + +```bash +pip install git+https://github.com/huggingface/transformers.git +``` + + + +让我们试用一下 MMS,看看如何合成非英语的语音,例如德语。首先,我们将加载特定语言的检查点和分词器: + +```python +from transformers import VitsModel, VitsTokenizer + +model = VitsModel.from_pretrained("facebook/mms-tts-deu") +tokenizer = VitsTokenizer.from_pretrained("facebook/mms-tts-deu") +``` + +您可能会注意到,加载 MMS 模型需要使用 `VitsModel` 和 `VitsTokenizer`。这是因为如前所述,MMS 的 TTS 是基于 VITS 模型的。 + +让我们选择一首德语儿歌的前两句作为示例文本: + +```python +text_example = ( + "Ich bin Schnappi das kleine Krokodil, komm aus Ägypten das liegt direkt am Nil." +) +``` + +要生成波形输出,使用分词器预处理文本,并将其传递给模型: + +```python +import torch + +inputs = tokenizer(text_example, return_tensors="pt") +input_ids = inputs["input_ids"] + + +with torch.no_grad(): + outputs = model(input_ids) + +speech = outputs["waveform"] +``` + +让我们来听听: + +```python +from IPython.display import Audio + +Audio(speech, rate=16000) +``` + +Wunderbar!如果您想尝试其他语言的 MMS,可以 [在 🤗 Hub 上](https://huggingface.co/models?filter=vits) 寻找其他合适的 `vits` 检查点。 + +现在,让我们看看如何自己微调一个 TTS 模型! diff --git a/chapters/zh-CN/chapter6/supplemental_reading.mdx b/chapters/zh-CN/chapter6/supplemental_reading.mdx new file mode 100644 index 0000000..55a3670 --- /dev/null +++ b/chapters/zh-CN/chapter6/supplemental_reading.mdx @@ -0,0 +1,8 @@ +# 补充阅读 + +本单元介绍了语音合成任务,包含了很多内容。想要了解更多吗?在这里,您将找到额外的资源,帮助您深入理解这些主题并提升您的学习体验。 + +* [HiFi-GAN: 用于高效和高保真语音合成的生成对抗网络](https://arxiv.org/pdf/2010.05646.pdf):介绍语音合成中的声码器 HiFi-GAN 的论文。 +* [X-Vectors: 用于说话人识别的鲁棒 DNN 嵌入](https://www.danielpovey.com/files/2018_icassp_xvectors.pdf):介绍说话人嵌入的 X-Vector 方法的论文。 +* [FastSpeech 2: 快速且高质量的端到端语音合成](https://arxiv.org/pdf/2006.04558.pdf):介绍 FastSpeech 2 的论文,这是另一个流行的语音合成模型,它使用了一种非自回归的 TTS 方法。 +* [文本到语音合成的一种基于真实自发语音的向量量化方法](https://arxiv.org/pdf/2302.04215v1.pdf):介绍 MQTTS 的论文,这是一个自回归的 TTS 系统,它用量化的离散表示替换了梅尔谱。 diff --git a/chapters/zh-CN/chapter6/tts_datasets.mdx b/chapters/zh-CN/chapter6/tts_datasets.mdx new file mode 100644 index 0000000..213984c --- /dev/null +++ b/chapters/zh-CN/chapter6/tts_datasets.mdx @@ -0,0 +1,54 @@ +# 语音合成数据集 + +语音合成任务(也称为 _文本转语音_,Text-to-Speech)面临许多挑战。 + +首先,就像之前讨论的语音识别(ASR)一样,文本和语音之间的对齐可能很棘手。然而,与 ASR 不同的是,TTS 是一个**一对多**映射问题, +即同一文本可以以多种不同方式合成。想想您每天听到的语音中声音和说话风格的多样性——每个人说同一句话的方式都不同,但它们都是有效且正确的! +TTS 模型的不同输出,频谱图或音频波形,可能对应同一个真实结果(ground truth)。模型必须学会为每个音素、单词或句子生成正确的持续时间和时序, +这可能会很有挑战性,特别是对于长且复杂的句子。 + +其次,TTS 中存在长距离依赖问题:语言具有时间维度,理解句子的意义通常需要考虑包含了周围词汇的上下文。确保 TTS 模型能捕获并保留长序列中的上下文信息对于生成连贯自然的语音至关重要。 + +最后,训练 TTS 模型通常需要文本和相应的语音录音配对,且为保证模型能够为不同说话人和说话风格生成自然的语音,数据应包含来自多个说话人的多样、有代表性的语音样本。 +收集此类数据既昂贵又耗时,并且对于某些语言来说并不可行。您可能会想,为什么不直接采用为 ASR 设计的数据集来训练 TTS 模型呢?不幸的是, +ASR 数据集并不是最佳选择。它们对于 ASR 有益的特性,如过多的背景噪音,在 TTS 中通常是不好的。能够在嘈杂街道的录音中辨别出语音是很棒的, +但如果您的语音助手回答您时背景有汽车喇叭声和建筑施工声就不那么理想了。尽管如此,有时可以用一些 ASR 数据集来微调,因为寻找高质量、多语言、多说话人的 TTS 数据集可能相当困难。 + +让我们来探索一些 🤗 Hub 上适用于 TTS 的数据集吧。 + +## LJSpeech + +[LJSpeech](https://huggingface.co/datasets/lj_speech) 是一个包含 13,100 个英语音频片段及其对应转写的大型数据集, +内容为一位说话人朗读 7 本纪实类英语书籍的录音。由于其音质高,语言内容多样,LJSpeech 经常被用作评估 TTS 模型的基准。 + +## Multilingual LibriSpeech + +[Multilingual LibriSpeech](https://huggingface.co/datasets/facebook/multilingual_librispeech) 是 LibriSpeech 数据集的多语言扩展版。 +后者只包含英语有声读物,而 Multilingual LibriSpeech 还包括了额外的语言,如德语、荷兰语、西班牙语、法语、意大利语、葡萄牙语和波兰语。 +它提供了每种语言的音频录音以及与之对齐的转写。这个数据集为开发多语言 TTS 系统和探索跨语言语音合成技术提供了宝贵的资源。 + +## VCTK (Voice Cloning Toolkit) + +[VCTK](https://huggingface.co/datasets/vctk) 是专为语音合成研究和开发设计的数据集。它包含了 110 位不同口音的人说英语的录音,每位说话人读约 400 个句子, +这些句子选自报纸、the rainbow passage 和旨在识别说话者口音的引出段落(elicitation paragraph)。VCTK 为训练具有多样化声音和口音的 TTS 模型提供了宝贵资源,使语音合成更加自然和多样化。 + +## Libri-TTS / LibriTTS-R + +[Libri-TTS / LibriTTS-R](https://huggingface.co/datasets/cdminix/libritts-r-aligned) 是一个由约 585 小时的英语朗读语音组成的多说话人英语语料库, +采样率 24kHz,由 Heiga Zen 在 Google Speech 和 Google Brain 团队成员的协助下搭建。LibriTTS 语料库专为 TTS 研究而设计,它源自 LibriSpeech 语料库的原始材料 +(LibriVox 的 mp3 音频文件和 Project Gutenberg 的文本文件)。它与 LibriSpeech 语料库的主要区别如下: + +* 音频文件是 24kHz 采样率。 +* 每条语音数据在句子与句子间断开。 +* 包括原始和规范化的文本。 +* 可以提取上下文信息(例如相邻句子)。 +* 排除了具有显著背景噪音的语音数据。 + +组建一个适用于 TTS 的优秀数据集并非易事,因为这样的数据集需要具备几个关键特性: + +* 高质量和多样化的录音,涵盖广泛的语音模式、口音、语言和情感。录音应清晰、无背景噪音,并展现自然的语音特征。 +* 转写:每个音频录音应有其相应的文本转写。 +* 语言内容的多样性:数据集应包含语言多样化的内容,包括不同类型的句子、短语和单词。它应涵盖各种主题、体裁和领域,以确保模型能够处理不同的语言环境。 + +好消息是,您很可能不需要从头开始训练一个 TTS 模型。在下一节中,我们将探讨在 🤗 Hub 上可用的预训练模型。 + From 04a3e3983b7d6b6af51edfbf268625bd71f9a9ea Mon Sep 17 00:00:00 2001 From: Yihang Chen <108577281+kaleo996@users.noreply.github.com> Date: Tue, 26 Mar 2024 13:03:49 +0800 Subject: [PATCH 2/2] Fixed unclosed in zh-CN/chapter6/pre-trained_models.mdx Sorry, I have accidentally written instead of . --- chapters/zh-CN/chapter6/pre-trained_models.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chapters/zh-CN/chapter6/pre-trained_models.mdx b/chapters/zh-CN/chapter6/pre-trained_models.mdx index 84112ec..32c21d1 100644 --- a/chapters/zh-CN/chapter6/pre-trained_models.mdx +++ b/chapters/zh-CN/chapter6/pre-trained_models.mdx @@ -306,7 +306,7 @@ Your browser does not support the audio element. Bark 与其他 🤗 Transformers 模型一样,只需几行代码即可针对速度和内存影响进行优化。要了解具体操作方法,请单击 [此 colab 演示笔记本](https://colab.research.google.com/github/ylacombe/notebooks/blob/main/Benchmark_Bark_HuggingFace.ipynb)。 - + ## Massive Multilingual Speech (MMS)