VITS源码解读4-辅助文件

VITS源码解读4-辅助文件

本节介绍多个文件:

  • mel_precessing.py

    频谱 spectrogram 转换为 mel_spectrogram 的操作函数

  • losses.py

    训练模型用到的损失函数

  • utils.py

    一个工具包,包含项目运行所需的辅助类或函数

  • commons.py

    包含训练网络时对数据处理函数(暂略)

1. mel_precessing.py

net_g的输入为频谱,但生成音频y_hat和真实音频y需要用mel谱判别。

这里数据输入用到音频转频谱函数

损失判别时,用到音频转梅尔谱(y_hat),频谱转梅尔谱函数(y)。

1.1 四个函数

用于音频信号的动态范围压缩与频谱归一化和反归一化

  • dynamic_range_compression_torch

通过对信号取对数来减少数值范围,
torch.clamp 确保 x 的最小值不低于 clip_val,避免对 0 取对数,
返回经过压缩后的信号。

def dynamic_range_compression_torch(x, C=1, clip_val=1e-5):
    return torch.log(torch.clamp(x, min=clip_val) * C)
  • dynamic_range_decompression_torch

对压缩后的信号的解压缩,恢复信号的值。

def dynamic_range_decompression_torch(x, C=1):
    return torch.exp(x) / C
  • spectral_normalize_torch

该函数用于对输入频谱 magnitudes 进行归一化处理,先压缩再归一化,使频谱的幅值更加稳定。

音频转频谱主要用这个

def spectral_normalize_torch(magnitudes):
    output = dynamic_range_compression_torch(magnitudes)
    return output
  • spectral_de_normalize_torch

反归一化,先解压缩

def spectral_de_normalize_torch(magnitudes):
    output = dynamic_range_decompression_torch(magnitudes)
    return output

1.2 音频转频谱函数

  • spectrogram

将音频转换为频谱格式

def spectrogram_torch(y, n_fft, sampling_rate, hop_size, win_size, center=False):
    if torch.min(y) < -1.:
        print('min value is ', torch.min(y))
    if torch.max(y) > 1.:
        print('max value is ', torch.max(y))

    global hann_window
    dtype_device = str(y.dtype) + '_' + str(y.device)
    wnsize_dtype_device = str(win_size) + '_' + dtype_device
    if wnsize_dtype_device not in hann_window:
        hann_window[wnsize_dtype_device] = torch.hann_window(win_size).to(dtype=y.dtype, device=y.device)

    y = torch.nn.functional.pad(y.unsqueeze(1), (int((n_fft-hop_size)/2), int((n_fft-hop_size)/2)), mode='reflect')
    y = y.squeeze(1)

    spec = torch.stft(y, n_fft, hop_length=hop_size, win_length=win_size, window=hann_window[wnsize_dtype_device],
                      center=center, pad_mode='reflect', normalized=False, onesided=True)

    spec = torch.sqrt(spec.pow(2).sum(-1) + 1e-6)
    return spec
  • spec_to_mel_torch

将频谱转换为mel谱

def spec_to_mel_torch(spec, n_fft, num_mels, sampling_rate, fmin, fmax):
    global mel_basis
    dtype_device = str(spec.dtype) + '_' + str(spec.device)
    fmax_dtype_device = str(fmax) + '_' + dtype_device
    if fmax_dtype_device not in mel_basis:
        mel = librosa_mel_fn(sampling_rate, n_fft, num_mels, fmin, fmax)
        mel_basis[fmax_dtype_device] = torch.from_numpy(mel).to(dtype=spec.dtype, device=spec.device)
    spec = torch.matmul(mel_basis[fmax_dtype_device], spec)
    spec = spectral_normalize_torch(spec)
    return spec

  • mel_spectrogram_torch

上两个函数的集合,音频直接转为mel谱函数,其参数来自json配置文件中的”data“项


n_fft =  "filter_length": 1024,

num_mels =  "n_mel_channels": 80,

sampling_rate =  "sampling_rate": 22050,

hop_size =  "hop_length": 256,

win_size =  "win_length": 1024,

fmin =  "mel_fmin": 0.0,

fmax =  "mel_fmax": null,

 "max_wav_value": 32768.0,

2. utils.py

常用的功能函数,比较杂,这里介绍几个重要的

  • load_checkpoint
    从文件中加载模型和优化器的状态,以便继续训练。

  • save_checkpoint
    将模型和优化器的状态保存到文件中。

  • summarize
    将各种训练数据记录到TensorBoard,用于可视化。

  • plot_spectrogram_to_numpy
    将频谱图绘制为图像并返回其数值表示,用于可视化。

  • plot_alignment_to_numpy
    将对齐矩阵绘制为图像并返回其数值表示,用于可视化。

  • load_filepaths_and_text

  • 输入:

    • filename (str): 包含文件路径和文本的文件。
    • split (str, default “|”): 分隔符。
    • audio_path (str): 替换占位符路径的实际音频路径。
  • 输出:

    • filepaths_and_text (list): 包含文件路径和文本的列表。
  • 功能: 加载包含音频文件路径和文本的文件,并根据实际路径进行替换。

  • HParams 类

    用于简化管理和访问模型的超参数字典,简化字典类型的数据操作。

    在dic[key] = value 的基础上增加等效操作: dic.key =value

3. losses.py

3.1 discriminator_loss(disc_real_outputs, disc_generated_outputs)

判别器损失(Discriminator Loss),仅此项用于用于判别器,其他都用到net_g。该损失使判别器能够有效地区分真实和生成的音频,帮助提升生成器的质量

- 该损失函数通过对真实音频和生成音频的判别输出计算,disc_real_outputs表示对真实音频的输出,disc_generated_outputs表示对生成音频的输出。

- 对于真实音频,希望判别器输出接近1(即 r_loss = torch.mean((1 - dr) ** 2)),而对于生成音频,输出应该接近0(即 g_loss = torch.mean(dg ** 2))。

- 通过对这些输出的均方误差(MSE)计算损失,来优化判别器。

代码:
后两项返回值仅用于统计

def discriminator_loss(disc_real_outputs, disc_generated_outputs):
  loss = 0
  r_losses = []
  g_losses = []
  for dr, dg in zip(disc_real_outputs, disc_generated_outputs):
    	dr = dr.float()
    	dg = dg.float()
    	r_loss = torch.mean((1-dr)**2)
    	g_loss = torch.mean(dg**2)
    	loss += (r_loss + g_loss)
    	r_losses.append(r_loss.item())
    	g_losses.append(g_loss.item())
  return loss, r_losses, g_losses

3.2 feature_loss(fmap_r, fmap_g)

特征匹配损失(Feature Matching Loss)。判别器输出的层级(layer-wise)特征图(feature maps)之间进行匹配。fmap_r代表真实音频的特征图,fmap_g代表生成音频的特征图。两者之间的差异通过绝对差值计算,并对每一层求平均。

用于训练生成器不仅被迫生成能够欺骗判别器的音频,还要生成在多层次特征上与真实音频更加一致的音频。layer-wise的特征保证了细节质量和自然性。

3.3 generator_loss(disc_outputs)

生成器损失(Generator Loss)。以生成器输出作为输入,送入判别器得到的值:disc_outputs。

希望判别器无法区分生成音频和真实音频,即判别器对生成音频的输出的判别值应该接近1

l = torch.mean((1 - dg) ** 2))

该损失函数训练生成器生成更真实、更自然的音频,以欺骗判别器,使其无法区分生成音频和真实音频。

def generator_loss(disc_outputs):
  loss = 0
  gen_losses = []
  for dg in disc_outputs:
    dg = dg.float()
    l = torch.mean((1-dg)**2)
    gen_losses.append(l)
    loss += l

  return loss, gen_losses

3.4 kl_loss(z_p, logs_q, m_p, logs_p, z_mask)

KL散度损失(Kullback-Leibler Divergence Loss)。来自变分推断(Variational Inference),即正则化潜在空间的分布,使得生成的潜在变量服从指定的正态分布。

- z_p, logs_q ,近似后验分布
	(来自音频编码器的波形 y=>z , logs_q,  再到流模型的输出 z => z_p)

- m_p, logs_p代表先验分布
	(来自文本编码器的音素 x => m_p, logs_p)

输入:

z_p:形状为 [b, h, t_t],表示潜在空间中的某个值。
logs_q:形状为 [b, h, t_t],表示分布 q(z) 的对数方差。
m_p:形状为 [b, h, t_t],表示分布 p(z) 的均值。
logs_p:形状为 [b, h, t_t],表示分布 p(z) 的对数方差。
z_mask:形状为 [b, h, t_t],掩码,用于决定哪些时间步长上的值参与损失计算。
- 通过计算这两个分布的KL散度并加权掩码z_mask,得到最终损失。

1.衡量的是两个分布 q(z) 和 p(z) 之间的差异

k l = l o g s p − l o g s q − 0.5 kl = logs_p - logs_q - 0.5 kl=logsplogsq0.5

2.计算潜码 z_p 和均值 m_p 之间的差异,并对差异进行平方和加权处理。加权是通过方差的指数计算来实现的。

k l + = 0.5 ∗ ( ( z p − m p ) ∗ ∗ 2 ) ∗ t o r c h . e x p ( − 2. ∗ l o g s p ) kl += 0.5 * ((z_p - m_p) ** 2) * torch.exp(-2. * logs_p) kl+=0.5((zpmp)2)torch.exp(2.logsp)

3.kl 损失乘以掩码 z_mask,滤掉不需要参与计算的时间步

k l = t o r c h . s u m ( k l ∗ z m a s k ) kl = torch.sum(kl * z_{mask}) kl=torch.sum(klzmask)

4.将损失 kl 除以 z_mask 中参与计算的步数总和,即归一化。

l = k l / t o r c h . s u m ( z m a s k ) l = kl / torch.sum(z_{mask}) l=kl/torch.sum(zmask)

注:实际上kl仅是生成器损失的一项

VITS(Variational Inference for Text-to-Speech)是一种端到端的文本到语音合成方法,它可以将文本转化为自然流畅的语音。VITS-Fast Fine-Tuning是对VITS模型进行快速微调的方法。 在传统的语音合成任务中,需要大量的语音对齐标注数据来训练模型。然而,这个过程非常耗时和昂贵。VITS-Fast Fine-Tuning的目标就是通过少量的标注数据来快速微调已有的VITS模型,以在新的任务上取得更好的性能。 VITS-Fast Fine-Tuning方法的关键在于使用变分推断(variational inference)来构建先验和后验分布。通过这个方法,我们可以使用其他大型语音合成数据集训练好的模型作为先验分布,然后使用少量目标任务的标注数据来估计后验分布。这样一来,我们就能够在新任务上快速微调VITS模型。 具体而言,VITS-Fast Fine-Tuning的过程分为两步。第一步是预训练,它使用大型语音数据集来训练VITS模型,并生成一个先验分布。第二步是微调,它使用目标任务的标注数据来调整VITS模型的参数,以获得更好的性能。由于预训练的先验分布已经包含了一定的知识,微调的过程可以更快速和高效。 总之,VITS-Fast Fine-Tuning是一种用于快速微调VITS模型的方法。它利用变分推断和预训练的先验分布,通过少量目标任务的标注数据来优化模型性能。这个方法可以加快语音合成模型的训练过程,降低训练的时间和成本。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值