使用轻改版PaddleSpeech套件训练自己的AI歌手-声学模型篇

★★★ 本文源自AI Studio社区精品项目,【点击此处】查看更多精品内容 >>>


使用轻改版PaddleSpeech套件训练自己的AI歌手-声学模型篇

现在你可以拥有自己的AI歌手啦,在AiStudio中上传数据集后,按照下面的步骤进行操作,经过漫长的训练等待后(4~14天),就可以拥有一个不错的AI歌手了。项目魔改自PaddleSpeech中的Fastspeech2说话人模型,有兴趣的同好可以去阅读相关技术论文。

使用流程说明:

  1. 上传数据集,可使用自己标注的数据

自己标注的数据应与Opencpop的格式相同

  1. 配置 PaddleSpeech 开发环境

配置好后如需直接用我训练好的模型进行歌声合成,可跳转到第7步

  1. 生成 Duration 时长信息

因为Opencpop使用的标注和PaddleSpeech不兼容,需要转换为PaddleSpeech支持的格式

  1. 训练数据处理
  2. 用处理好的数据训练声学模型
  3. 使用训练好的声学模型测试测试集
  4. 使用训练好的声学模型合成歌声

技术交流:项目使用过程中,如果遇到问题可以扫码加入艾梦的声动小群进行讨论。

PS: 本项目文件目录下的vocoder.ipynb文件用于训练声码器,声码器可以将声学模型生成的梅尔谱转换为波形文件

1. 上传数据集[如果只是测试模型效果,可以跳过这步]

Opencpop官网申请并下载数据集,将数据集上次到AIStudio上,不公开。

挂载在项目上后建议放在 work 目录下,放在 data 目录下次打开会不见

若使用自己的歌声数据集,应该先执行训练声码器项目

音频文件 + 标注文件

opencpop(数据文件夹)
   ├── wavs
       ├── 2001000001.wav
       ├── 2001000002.wav
       ├── 2001000003.wav
       ├── ...
       ├── 2100003756.wav
   └── transcriptions.txt

上传数据说明:

  • 音频数据

音频文件为单声道wav格式,采样率原数据是44100,建议上传采样率大于等于24000的数据,之后都会被降采样到24000

  • transcriptions.txt

音频文件名|歌词|音素|音符|音符持续时长|音素持续时长|连音

示例

2001000001|感受停在我发端的指尖|g an sh ou t ing z ai w o f a d uan d e SP zh i j ian AP|G#4/Ab4 G#4/Ab4 G#4/Ab4 G#4/Ab4 F#4/Gb4 F#4/Gb4 F#4/Gb4 F#4/Gb4 E4 E4 E4 E4 D#4/Eb4 D#4/Eb4 D#4/Eb4 D#4/Eb4 rest E4 E4 E4 E4 rest|0.253030 0.253030 0.428030 0.428030 0.320870 0.320870 0.358110 0.358110 0.218610 0.218610 0.519380 0.519380 0.351070 0.351070 0.152260 0.152260 0.089470 0.405810 0.405810 0.696660 0.696660 0.284630|0.0317 0.22133 0.15421 0.27382 0.06335 0.25752 0.07101 0.2871 0.03623 0.18238 0.18629 0.33309 0.01471 0.33636 0.01415 0.13811 0.08947 0.12862 0.27719 0.07962 0.61704 0.28463|0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
2001000005|面对浩瀚的星海我们微小得像尘埃|m ian d ui h ao h an an d e x ing h ai ai ai AP w o m en w ei x iao d e x iang ch en ai ai ai SP|C#4/Db4 C#4/Db4 D#4/Eb4 D#4/Eb4 C#4/Db4 C#4/Db4 D#4/Eb4 D#4/Eb4 E4 D#4/Eb4 D#4/Eb4 E4 E4 G#4/Ab4 G#4/Ab4 A4 G#4/Ab4 rest C#4/Db4 C#4/Db4 C#4/Db4 C#4/Db4 D#4/Eb4 D#4/Eb4 C#4/Db4 C#4/Db4 D#4/Eb4 D#4/Eb4 E4 E4 E4 E4 G#4/Ab4 A4 G#4/Ab4 rest|0.196990 0.196990 0.102120 0.102120 0.304680 0.304680 0.096780 0.096780 0.100220 0.150010 0.150010 0.361460 0.361460 0.221070 0.221070 0.183240 0.478670 0.384620 0.106510 0.106510 0.143020 0.143020 0.169480 0.169480 0.224180 0.224180 0.089360 0.089360 0.414460 0.414460 0.378050 0.378050 0.162790 0.207380 0.317260 0.297040|0.02765 0.16934 0.01874 0.08338 0.0821 0.22258 0.0693 0.02748 0.10022 0.07137 0.07864 0.12471 0.23675 0.12356 0.09751 0.18324 0.47867 0.38462 0.0405 0.06601 0.08303 0.05999 0.04687 0.12261 0.09778 0.1264 0.02321 0.06615 0.11958 0.29488 0.06723 0.31082 0.16279 0.20738 0.31726 0.29704|0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0

2. 配置 PaddleSpeech 开发环境

安装 轻改版PaddleSpeech

# 配置 PaddleSpeech 开发环境
!git clone https://gitee.com/HighCWu/PaddleSpeech.git --branch svs
%cd PaddleSpeech
!pip install . -i https://mirror.baidu.com/pypi/simple --user
# 下载 NLTK
%cd /home/aistudio
!wget -P data https://paddlespeech.bj.bcebos.com/Parakeet/tools/nltk_data.tar.gz
!tar zxvf data/nltk_data.tar.gz

重启一下内核,使得刚刚安装的依赖都能加载进notebook

# 删除软链接
# aistudio会报错: paddlespeech 的 repo中存在失效软链接
# 执行下面这行命令!!
!find -L /home/aistudio -type l -delete
import subprocess

# 命令行执行函数,可以进入指定路径下执行

def run_cmd(cmd, cwd_path):
    p = subprocess.Popen(cmd, shell=True, cwd=cwd_path)
    res = p.wait()
    print(cmd)
    print("运行结果:", res)
    if res == 0:
        # 运行成功
        print("运行成功")
        return True
    else:
        # 运行失败
        print("运行失败")
        return False
# 试验路径
exp_dir = "/home/aistudio/work/exp"
import os

# 配置试验相关路径信息
cwd_path = "/home/aistudio/PaddleSpeech/examples/opencpop/tts3"
dump_dir = os.path.join(exp_dir, 'dump')
output_dir = os.path.join(exp_dir, 'exp')
main_root = "/home/aistudio/PaddleSpeech"
model = "fastspeech2"
bin_dir = f"{main_root}/paddlespeech/t2s/exps/{model}"
# 使用默认示例,只上传音频数据+标注文本
# 输入数据集路径
datasets_dir = "/home/aistudio/work/datasets"
data_dir = f"{datasets_dir}/opencpop"

# 输出文件路径
wav_output_dir = os.path.join(exp_dir, "output")
os.makedirs(wav_output_dir, exist_ok=True)
# 将默认的 yaml 拷贝一份到 exp_dir 下,方便修改
import shutil
in_label = f"{cwd_path}/conf/default.yaml"
shutil.copy(in_label, exp_dir + "/default.yaml")

训练过程中如果有需要修改的参数,就修改 /home/aistudio/work/exp/default.yaml

config_path = os.path.join(exp_dir, "default.yaml")

☝️ 如果你想直接试验已经训练好的模型,现在你可以运行以下代码先解压预训练模型

import os
import glob
if not os.path.exists('/home/aistudio/data/fastspeech2_opencpop_ckpt'):
    am_ckpt_paths = glob.glob('/home/aistudio/data/data*/fastspeech2_opencpop_ckpt.tar.gz')[0]
    !cd /home/aistudio/data && tar xfz '{am_ckpt_paths}' -C /home/aistudio/data/
!mkdir -p '{dump_dir}'/train
!mkdir -p '{output_dir}'/checkpoints
!cp /home/aistudio/data/fastspeech2_opencpop_ckpt/default.yaml '{config_path}'
!cp /home/aistudio/data/fastspeech2_opencpop_ckpt/phone_id_map.txt '{dump_dir}'/
!cp /home/aistudio/data/fastspeech2_opencpop_ckpt/speech_stats.npy '{dump_dir}'/train/
!cp /home/aistudio/data/fastspeech2_opencpop_ckpt/pitch_stats.npy '{dump_dir}'/train/
!cp /home/aistudio/data/fastspeech2_opencpop_ckpt/snapshot_iter_1000000.pdz '{output_dir}'/checkpoints

点击此处直接跳转到使用已有模型合成歌声部分进行合成实验。

✌️ 如果你是想训练模型,可以先解压数据集,然后执行以下数据解压操作,然后按顺序往下执行数据预处理操作和模型训练操作

# 举例:这里将data目录下的数据集解压到 datasets 路径下,这一步你可以换成自己的数据集
%cd /home/aistudio/work
!mkdir -p datasets
!unzip -qq ../data/data*/opencpop.zip -d ./datasets/
%cd ..

3. 生成 Duration 时长信息

cmd = f"""
python3 {main_root}/utils/gen_duration_for_svs.py \
    --inputdir={datasets_dir} \
    --output=durations.txt \
    --config={config_path}
"""
# 执行该步骤
run_cmd(cmd, cwd_path)

4. 数据预处理

训练数据预处理

cmd1 = f"""
python3 {bin_dir}/preprocess.py \
    --rootdir={data_dir} \
    --dataset=opencpop \
    --dumpdir={dump_dir} \
    --dur-file=durations.txt \
    --config={config_path} \
    --cut-sil=True \
    --num-cpu=20
"""
cmd2 = f"""
python3 {main_root}/utils/compute_statistics.py \
    --metadata={dump_dir}/train/raw/metadata.jsonl \
    --field-name="speech"
"""
cmd3 = f"""
python3 {main_root}/utils/compute_statistics.py \
    --metadata={dump_dir}/train/raw/metadata.jsonl \
    --field-name="pitch"
"""
cmd4 = f"""
python3 {main_root}/utils/compute_statistics.py \
    --metadata={dump_dir}/train/raw/metadata.jsonl \
    --field-name="energy"
"""
cmd5 = f"""
python3 {bin_dir}/normalize.py \
    --metadata={dump_dir}/train/raw/metadata.jsonl \
    --dumpdir={dump_dir}/train/norm \
    --speech-stats={dump_dir}/train/speech_stats.npy \
    --pitch-stats={dump_dir}/train/pitch_stats.npy \
    --energy-stats={dump_dir}/train/energy_stats.npy \
    --phones-dict={dump_dir}/phone_id_map.txt \
    --speaker-dict={dump_dir}/speaker_id_map.txt
"""
cmd6 = f"""
python3 {bin_dir}/normalize.py \
    --metadata={dump_dir}/dev/raw/metadata.jsonl \
    --dumpdir={dump_dir}/dev/norm \
    --speech-stats={dump_dir}/train/speech_stats.npy \
    --pitch-stats={dump_dir}/train/pitch_stats.npy \
    --energy-stats={dump_dir}/train/energy_stats.npy \
    --phones-dict={dump_dir}/phone_id_map.txt \
    --speaker-dict={dump_dir}/speaker_id_map.txt
"""
cmd7 = f"""
python3 {bin_dir}/normalize.py \
    --metadata={dump_dir}/test/raw/metadata.jsonl \
    --dumpdir={dump_dir}/test/norm \
    --speech-stats={dump_dir}/train/speech_stats.npy \
    --pitch-stats={dump_dir}/train/pitch_stats.npy \
    --energy-stats={dump_dir}/train/energy_stats.npy \
    --phones-dict={dump_dir}/phone_id_map.txt \
    --speaker-dict={dump_dir}/speaker_id_map.txt
"""
# 执行该步骤
run_cmd(cmd1, cwd_path)
run_cmd(cmd2, cwd_path)
run_cmd(cmd3, cwd_path)
run_cmd(cmd4, cwd_path)
run_cmd(cmd5, cwd_path)
run_cmd(cmd6, cwd_path)
run_cmd(cmd7, cwd_path)

5. 训练

不同的数据集是不好给出统一的训练参数,因此在这一步,开发者可以根据自己训练的实际情况调整参数,重要参数说明:

  • 训练步数: step (在default.yaml中通过train_max_steps设置最大步数)
  1. step 决定了训练的步数,可以结合 VisualDL 服务,在 AIstudio 中查看训练数据是否已经收敛,当数据集数量增加时,预设的训练轮次(2500000)不一定可以达到收敛状态
  2. 当训练步数过多时,建议新建终端,进入/home/aistudio/PaddleSpeech/examples/opencpop/tts3 路径下, 执行 cmd 命令,AIStudio 在打印特别多的训练信息时,会产生错误
cmd = f"""
python {bin_dir}/train.py \
    --train-metadata={dump_dir}/train/norm/metadata.jsonl \
    --dev-metadata={dump_dir}/dev/norm/metadata.jsonl \
    --config={config_path} \
    --output-dir={output_dir} \
    --ngpu=1 \
    --phones-dict={dump_dir}/phone_id_map.txt
"""
print(cmd)
# 执行该步骤
# 如果训练轮次过多,则复制上面的cmd到终端中运行
run_cmd(cmd, cwd_path)

6. 使用测试集验证数据

# 找到最新生成的模型
def find_max_ckpt(model_path):
    max_ckpt = 0
    max_cpkt_path = ''
    for filename in os.listdir(model_path):
        if filename.endswith('.pdz'):
            files = filename[:-4]
            a1, a2, it = files.split("_")
            if int(it) > max_ckpt:
                max_ckpt = int(it)
                max_cpkt_path = os.path.join(model_path, filename)
    return max_ckpt, max_cpkt_path

if not os.path.exists('/home/aistudio/data/hifigan_opencpop_ckpt'):
    import glob
    voc_ckpt_paths = glob.glob('/home/aistudio/data/data*/hifigan_opencpop_ckpt.zip')[0]
    !cd /home/aistudio/data && unzip -qq '{voc_ckpt_paths}' -d /home/aistudio/data/

voc_ckpt_path = '/home/aistudio/data/hifigan_opencpop_ckpt'
_, voc_ckpt_path_pdz = find_max_ckpt(voc_ckpt_path)
model_path = os.path.join(output_dir, "checkpoints")
ckpt, cpkt_path = find_max_ckpt(model_path)
cmd = f"""
python3 {bin_dir}/../synthesize.py \
    --am=fastspeech2_opencpop \
    --am_config={config_path} \
    --am_ckpt={cpkt_path} \
    --am_stat={dump_dir}/train/speech_stats.npy \
    --voc=hifigan_opencpop \
    --voc_config={voc_ckpt_path}/default.yaml \
    --voc_ckpt={voc_ckpt_path_pdz} \
    --voc_stat={voc_ckpt_path}/feats_stats.npy \
    --test_metadata={dump_dir}/test/norm/metadata.jsonl \
    --output_dir={wav_output_dir} \
    --phones_dict={dump_dir}/phone_id_map.txt \
    --use_durations=True \
    --use_pitch=True
"""
print(cmd)
run_cmd(cmd, cwd_path)

7. 使用训练好的模型合成特定歌声

# 找到最新的模型
def find_max_ckpt(model_path):
    max_ckpt = 0
    max_cpkt_path = ''
    for filename in os.listdir(model_path):
        if filename.endswith('.pdz'):
            files = filename[:-4]
            a1, a2, it = files.split("_")
            if int(it) > max_ckpt:
                max_ckpt = int(it)
                max_cpkt_path = os.path.join(model_path, filename)
    return max_ckpt, max_cpkt_path

if not os.path.exists('/home/aistudio/data/hifigan_opencpop_ckpt'):
    import glob
    voc_ckpt_paths = glob.glob('/home/aistudio/data/data*/hifigan_opencpop_ckpt.zip')[0]
    !cd /home/aistudio/data && unzip -qq '{voc_ckpt_paths}' -d /home/aistudio/data/

voc_ckpt_path = '/home/aistudio/data/hifigan_opencpop_ckpt'
_, voc_ckpt_path_pdz = find_max_ckpt(voc_ckpt_path)
model_path = os.path.join(output_dir, "checkpoints")
ckpt, ckpt_path = find_max_ckpt(model_path)
# 导入相关库
# 如果出现导入出错,请重启内核,从头运行一次

import yaml

from frontend import parse_args, IPyWidgetInfer

# 配置一下参数信息
model_path = os.path.join(output_dir, "checkpoints")
ckpt = find_max_ckpt(model_path)
args = parse_args()
args.am = 'fastspeech2_opencpop'
args.am_config = config_path
args.am_ckpt = ckpt_path
args.am = 'fastspeech2_opencpop'
args.am_config = config_path
args.am_stat = f'{dump_dir}/train/speech_stats.npy'
args.am_pitch_stat = f'{dump_dir}/train/pitch_stats.npy'
args.voc = 'hifigan_opencpop'
args.voc_config = f'{voc_ckpt_path}/default.yaml'
args.voc_ckpt = f'{voc_ckpt_path_pdz}'
args.voc_stat = f'{voc_ckpt_path}/feats_stats.npy'
args.lang = 'sing-zh'
args.phones_dict = f'{dump_dir}/phone_id_map.txt'
args.ngpu = 1

# 加载模型
ipy_config = yaml.safe_load(open('settings.yaml'))
ipy_infer = IPyWidgetInfer(args, **ipy_config)
# 显示测试界面
ipy_infer.run()
VBox(children=(HTML(value='<h1><center><b>轻改版PaddleSpeech歌声合成模型</b></center></h2>'), HTML(value='<p><p>该模型在开源数…

8. 结束语

虽然有PaddleSpeech套件以前就写好的Fastspeech2的模型训练架构,但是从数据集处理到训练到测试数据合成都需要不同程度的魔改,花费了我不少时间。通过上面的学习,相信你也可以使用自己的数据集来训练一个属于自己的歌声合成模型。由于涉及到深度学习模型训练部分,不同的数据集需要做不同的参数尝试,希望你也可以调试出让自己满意的模型。

直接使用Fastspeech2模型训练并没有达到非常好的合成效果,下一步我将尝试在PaddleSpeech上继续魔改,实现DiffSinger模型的歌声合成效果。

最后,在学习过程中,你遇到任何问题都可以加入我的技术交流群与我群群友进行深入的交流探讨。

艾梦的声动小群

  • 1
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值