【GPT-SOVITS-04】SOVITS 模块-鉴别模型解析-1.SOVITS 鉴别器

1.1、概述

GPT-SOVITS 在鉴别器这块在SOVITS原始版本上做了简化,先回顾下SOVITS的鉴别器。主要包含三类:
在这里插入图片描述
各个鉴别器的输出都包括两类,即各层中间输出和最终结果输出,分别用来计算特征损失和生成损失。如下:
在这里插入图片描述

1.2、MRD举例

在这里插入图片描述

import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.nn.utils import weight_norm, spectral_norm

class DiscriminatorR(torch.nn.Module):
    def __init__(self, hp, resolution):
        super(DiscriminatorR, self).__init__()

        self.resolution = resolution
        self.LRELU_SLOPE = hp.mpd.lReLU_slope

        norm_f = weight_norm if hp.mrd.use_spectral_norm == False else spectral_norm

        self.convs = nn.ModuleList([
            norm_f(nn.Conv2d(1, 32, (3, 9), padding=(1, 4))),
            norm_f(nn.Conv2d(32, 32, (3, 9), stride=(1, 2), padding=(1, 4))),
            norm_f(nn.Conv2d(32, 32, (3, 9), stride=(1, 2), padding=(1, 4))),
            norm_f(nn.Conv2d(32, 32, (3, 9), stride=(1, 2), padding=(1, 4))),
            norm_f(nn.Conv2d(32, 32, (3, 3), padding=(1, 1))),
        ])
        self.conv_post = norm_f(nn.Conv2d(32, 1, (3, 3), padding=(1, 1)))

    def forward(self, x):
        fmap = []

        # 获取频谱,这里是做了窗口傅里叶变换
        # 傅里叶变换时,频谱数量、窗口的移动、窗口大小由参数 resolution 决定
        x = self.spectrogram(x)
        x = x.unsqueeze(1)
        for l in self.convs:

            # 与其他鉴别器一样经过conv-1d 和 leak-relue 形成中间层特征
            x = l(x)
            x = F.leaky_relu(x, self.LRELU_SLOPE)

            # 中间层特征被保存在 fmap 中
            fmap.append(x)
        x = self.conv_post(x)
        fmap.append(x)
        x = torch.flatten(x, 1, -1)

        # 返回各层的中间层特征 fmap  和 最终输出 x
        return fmap, x

    def spectrogram(self, x):
        n_fft, hop_length, win_length = self.resolution
        x = F.pad(x, (int((n_fft - hop_length) / 2), int((n_fft - hop_length) / 2)), mode='reflect')
        x = x.squeeze(1)
        x = torch.stft(x, n_fft=n_fft, hop_length=hop_length, win_length=win_length, center=False, return_complex=False) #[B, F, TT, 2]
        mag = torch.norm(x, p=2, dim =-1) #[B, F, TT]

        return mag


class MultiResolutionDiscriminator(torch.nn.Module):
    def __init__(self, hp):
        super(MultiResolutionDiscriminator, self).__init__()
        self.resolutions = eval(hp.mrd.resolutions)
        self.discriminators = nn.ModuleList(
            [DiscriminatorR(hp, resolution) for resolution in self.resolutions]
        )

    def forward(self, x):
        ret = list()

        # 这里做了一个不同尺度的 DiscriminatorR

        """
        在 base.yml 中 mrd 的参数如下,有四个不同的尺度:
        mrd:
        resolutions: "[(1024, 120, 600), (2048, 240, 1200), (4096, 480, 2400), (512, 50, 240)]" # (filter_length, hop_length, win_length)
        use_spectral_norm: False
        lReLU_slope: 0.2
        """
        for disc in self.discriminators:
            ret.append(disc(x))

        return ret  # [(feat, score), (feat, score), (feat, score)]
上一篇:How to install PyAlink on Ubuntu 22.04-环境准备


下一篇:SpringBoot—@ConditionalOnBean与@ConditionalOnClass-二、@ConditionalOnBean示例