parent
ee70c2eadc
commit
a7b9a9c9b0
@ -0,0 +1,84 @@
|
||||
import numpy as np
|
||||
import paddle
|
||||
from librosa.filters import mel as librosa_mel_fn
|
||||
from scipy.io.wavfile import read
|
||||
|
||||
MAX_WAV_VALUE = 32768.0
|
||||
|
||||
|
||||
def load_wav(full_path):
|
||||
sampling_rate, data = read(full_path)
|
||||
return data, sampling_rate
|
||||
|
||||
|
||||
def dynamic_range_compression(x, C=1, clip_val=1e-05):
|
||||
return np.log(np.clip(x, a_min=clip_val, a_max=None) * C)
|
||||
|
||||
|
||||
def dynamic_range_decompression(x, C=1):
|
||||
return np.exp(x) / C
|
||||
|
||||
|
||||
def dynamic_range_compression_torch(x, C=1, clip_val=1e-05):
|
||||
return paddle.log(paddle.clamp(x, min=clip_val) * C)
|
||||
|
||||
|
||||
def dynamic_range_decompression_torch(x, C=1):
|
||||
return paddle.exp(x=x) / C
|
||||
|
||||
|
||||
def spectral_normalize_torch(magnitudes):
|
||||
output = dynamic_range_compression_torch(magnitudes)
|
||||
return output
|
||||
|
||||
|
||||
def spectral_de_normalize_torch(magnitudes):
|
||||
output = dynamic_range_decompression_torch(magnitudes)
|
||||
return output
|
||||
|
||||
|
||||
mel_basis = {}
|
||||
hann_window = {}
|
||||
|
||||
|
||||
def mel_spectrogram(
|
||||
y, n_fft, num_mels, sampling_rate, hop_size, win_size, fmin, fmax, center=False
|
||||
):
|
||||
if paddle.compat.min(y) < -1.0:
|
||||
print("min value is ", paddle.compat.min(y))
|
||||
if paddle.compat.max(y) > 1.0:
|
||||
print("max value is ", paddle.compat.max(y))
|
||||
global mel_basis, hann_window
|
||||
if f"{str(fmax)}_{str(y.place)}" not in mel_basis:
|
||||
mel = librosa_mel_fn(
|
||||
sr=sampling_rate, n_fft=n_fft, n_mels=num_mels, fmin=fmin, fmax=fmax
|
||||
)
|
||||
mel_basis[str(fmax) + "_" + str(y.place)] = (
|
||||
paddle.from_numpy(mel).float().to(y.place)
|
||||
)
|
||||
hann_window[str(y.place)] = paddle.audio.functional.get_window(
|
||||
win_length=win_size, dtype="float32", window="hann"
|
||||
).to(y.place)
|
||||
y = paddle.compat.pad(
|
||||
y.unsqueeze(1),
|
||||
(int((n_fft - hop_size) / 2), int((n_fft - hop_size) / 2)),
|
||||
mode="reflect",
|
||||
)
|
||||
y = y.squeeze(1)
|
||||
spec = paddle.view_as_real(
|
||||
paddle.signal.stft(
|
||||
x=y,
|
||||
n_fft=n_fft,
|
||||
hop_length=hop_size,
|
||||
win_length=win_size,
|
||||
window=hann_window[str(y.place)],
|
||||
center=center,
|
||||
pad_mode="reflect",
|
||||
normalized=False,
|
||||
onesided=True,
|
||||
)
|
||||
)
|
||||
spec = paddle.sqrt(spec.pow(2).sum(-1) + 1e-09)
|
||||
spec = paddle.matmul(mel_basis[str(fmax) + "_" + str(y.place)], spec)
|
||||
spec = spectral_normalize_torch(spec)
|
||||
return spec
|
||||
@ -0,0 +1,40 @@
|
||||
import paddle
|
||||
|
||||
# from cosyvoice.cli.model import CosyVoice2Model, CosyVoiceModel
|
||||
# from cosyvoice.flow.flow import CausalMaskedDiffWithXvec, MaskedDiffWithXvec
|
||||
# from cosyvoice.hifigan.generator import HiFTGenerator
|
||||
# from cosyvoice.llm.llm import Qwen2LM, TransformerLM
|
||||
from paddlespeech.t2s.modules.transformer.activation import Swish
|
||||
from paddlespeech.t2s.modules.transformer.attention import RelPositionMultiHeadedAttention
|
||||
from paddlespeech.t2s.modules.transformer.embedding import EspnetRelPositionalEncoding
|
||||
from paddlespeech.t2s.modules.transformer.subsampling import LinearNoSubsampling
|
||||
|
||||
|
||||
COSYVOICE_ACTIVATION_CLASSES = {
|
||||
"swish": Swish
|
||||
}
|
||||
COSYVOICE_SUBSAMPLE_CLASSES = {
|
||||
"linear": LinearNoSubsampling,
|
||||
}
|
||||
COSYVOICE_EMB_CLASSES = {
|
||||
"rel_pos_espnet": EspnetRelPositionalEncoding,
|
||||
}
|
||||
COSYVOICE_ATTENTION_CLASSES = {
|
||||
"rel_selfattn": RelPositionMultiHeadedAttention,
|
||||
}
|
||||
|
||||
|
||||
# def get_model_type(configs):
|
||||
# if (
|
||||
# isinstance(configs["llm"], TransformerLM)
|
||||
# and isinstance(configs["flow"], MaskedDiffWithXvec)
|
||||
# and isinstance(configs["hift"], HiFTGenerator)
|
||||
# ):
|
||||
# return CosyVoiceModel
|
||||
# if (
|
||||
# isinstance(configs["llm"], Qwen2LM)
|
||||
# and isinstance(configs["flow"], CausalMaskedDiffWithXvec)
|
||||
# and isinstance(configs["hift"], HiFTGenerator)
|
||||
# ):
|
||||
# return CosyVoice2Model
|
||||
# raise TypeError("No valid model type found!")
|
||||
@ -0,0 +1,443 @@
|
||||
import paddle
|
||||
|
||||
"""HIFI-GAN"""
|
||||
from typing import Dict, List, Optional
|
||||
|
||||
import numpy as np
|
||||
from scipy.signal import get_window
|
||||
from paddlespeech.t2s.modules.transformer.activation import Snake
|
||||
from paddlespeech.t2s.models.CosyVoice.common import get_padding, init_weights
|
||||
|
||||
"""hifigan based generator implementation.
|
||||
|
||||
This code is modified from https://github.com/jik876/hifi-gan
|
||||
,https://github.com/kan-bayashi/ParallelWaveGAN and
|
||||
https://github.com/NVIDIA/BigVGAN
|
||||
|
||||
"""
|
||||
|
||||
|
||||
class ResBlock(paddle.nn.Layer):
|
||||
"""Residual block module in HiFiGAN/BigVGAN."""
|
||||
|
||||
def __init__(self, channels: int=512, kernel_size: int=3, dilations:
|
||||
List[int]=[1, 3, 5]):
|
||||
super(ResBlock, self).__init__()
|
||||
self.convs1 = paddle.nn.LayerList()
|
||||
self.convs2 = paddle.nn.LayerList()
|
||||
for dilation in dilations:
|
||||
self.convs1.append(paddle.nn.utils.weight_norm(layer=paddle.nn.
|
||||
Conv1D(channels, channels, kernel_size, 1, dilation=
|
||||
dilation, padding=get_padding(kernel_size, dilation))))
|
||||
self.convs2.append(paddle.nn.utils.weight_norm(layer=paddle.nn.
|
||||
Conv1D(channels, channels, kernel_size, 1, dilation=1,
|
||||
padding=get_padding(kernel_size, 1))))
|
||||
self.convs1.apply(init_weights)
|
||||
self.convs2.apply(init_weights)
|
||||
self.activations1 = paddle.nn.LayerList(sublayers=[Snake(channels,
|
||||
alpha_logscale=False) for _ in range(len(self.convs1))])
|
||||
self.activations2 = paddle.nn.LayerList(sublayers=[Snake(channels,
|
||||
alpha_logscale=False) for _ in range(len(self.convs2))])
|
||||
|
||||
def forward(self, x: paddle.Tensor) ->paddle.Tensor:
|
||||
for idx in range(len(self.convs1)):
|
||||
xt = self.activations1[idx](x)
|
||||
xt = self.convs1[idx](xt)
|
||||
xt = self.activations2[idx](xt)
|
||||
xt = self.convs2[idx](xt)
|
||||
x = xt + x
|
||||
return x
|
||||
|
||||
def remove_weight_norm(self):
|
||||
for idx in range(len(self.convs1)):
|
||||
paddle.nn.utils.remove_weight_norm(layer=self.convs1[idx])
|
||||
paddle.nn.utils.remove_weight_norm(layer=self.convs2[idx])
|
||||
|
||||
|
||||
class SineGen(paddle.nn.Layer):
|
||||
""" Definition of sine generator
|
||||
SineGen(samp_rate, harmonic_num = 0,
|
||||
sine_amp = 0.1, noise_std = 0.003,
|
||||
voiced_threshold = 0,
|
||||
flag_for_pulse=False)
|
||||
samp_rate: sampling rate in Hz
|
||||
harmonic_num: number of harmonic overtones (default 0)
|
||||
sine_amp: amplitude of sine-wavefrom (default 0.1)
|
||||
noise_std: std of Gaussian noise (default 0.003)
|
||||
voiced_thoreshold: F0 threshold for U/V classification (default 0)
|
||||
flag_for_pulse: this SinGen is used inside PulseGen (default False)
|
||||
Note: when flag_for_pulse is True, the first time step of a voiced
|
||||
segment is always sin(np.pi) or cos(0)
|
||||
"""
|
||||
|
||||
def __init__(self, samp_rate, harmonic_num=0, sine_amp=0.1, noise_std=
|
||||
0.003, voiced_threshold=0):
|
||||
super(SineGen, self).__init__()
|
||||
self.sine_amp = sine_amp
|
||||
self.noise_std = noise_std
|
||||
self.harmonic_num = harmonic_num
|
||||
self.sampling_rate = samp_rate
|
||||
self.voiced_threshold = voiced_threshold
|
||||
|
||||
def _f02uv(self, f0):
|
||||
uv = (f0 > self.voiced_threshold).astype(paddle.float32)
|
||||
return uv
|
||||
|
||||
@paddle.no_grad()
|
||||
def forward(self, f0):
|
||||
"""
|
||||
:param f0: [B, 1, sample_len], Hz
|
||||
:return: [B, 1, sample_len]
|
||||
"""
|
||||
F_mat = paddle.zeros([f0.size(0), self.harmonic_num + 1, f0.size(-1)]).to(f0.place)
|
||||
for i in range(self.harmonic_num + 1):
|
||||
F_mat[:, i:i + 1, :] = f0 * (i + 1) / self.sampling_rate
|
||||
theta_mat = 2 * np.pi * (paddle.cumsum(F_mat, axis=-1) % 1)
|
||||
u_dist = paddle.distribution.Uniform(low=-np.pi, high=np.pi)
|
||||
phase_vec = u_dist.sample(shape=(f0.size(0), self.harmonic_num + 1, 1)
|
||||
).to(F_mat.place)
|
||||
phase_vec[:, 0, :] = 0
|
||||
sine_waves = self.sine_amp * paddle.sin(theta_mat + phase_vec)
|
||||
uv = self._f02uv(f0)
|
||||
noise_amp = uv * self.noise_std + (1 - uv) * self.sine_amp / 3
|
||||
noise = noise_amp * paddle.randn(shape=sine_waves.shape, dtype=
|
||||
sine_waves.dtype)
|
||||
sine_waves = sine_waves * uv + noise
|
||||
return sine_waves, uv, noise
|
||||
|
||||
|
||||
class SourceModuleHnNSF(paddle.nn.Layer):
|
||||
""" SourceModule for hn-nsf
|
||||
SourceModule(sampling_rate, harmonic_num=0, sine_amp=0.1,
|
||||
add_noise_std=0.003, voiced_threshod=0)
|
||||
sampling_rate: sampling_rate in Hz
|
||||
harmonic_num: number of harmonic above F0 (default: 0)
|
||||
sine_amp: amplitude of sine source signal (default: 0.1)
|
||||
add_noise_std: std of additive Gaussian noise (default: 0.003)
|
||||
note that amplitude of noise in unvoiced is decided
|
||||
by sine_amp
|
||||
voiced_threshold: threhold to set U/V given F0 (default: 0)
|
||||
Sine_source, noise_source = SourceModuleHnNSF(F0_sampled)
|
||||
F0_sampled (batchsize, length, 1)
|
||||
Sine_source (batchsize, length, 1)
|
||||
noise_source (batchsize, length 1)
|
||||
uv (batchsize, length, 1)
|
||||
"""
|
||||
|
||||
def __init__(self, sampling_rate, upsample_scale, harmonic_num=0,
|
||||
sine_amp=0.1, add_noise_std=0.003, voiced_threshod=0):
|
||||
super(SourceModuleHnNSF, self).__init__()
|
||||
self.sine_amp = sine_amp
|
||||
self.noise_std = add_noise_std
|
||||
self.l_sin_gen = SineGen(sampling_rate, harmonic_num, sine_amp,
|
||||
add_noise_std, voiced_threshod)
|
||||
self.l_linear = paddle.nn.Linear(in_features=harmonic_num + 1,
|
||||
out_features=1)
|
||||
self.l_tanh = paddle.nn.Tanh()
|
||||
|
||||
def forward(self, x):
|
||||
"""
|
||||
Sine_source, noise_source = SourceModuleHnNSF(F0_sampled)
|
||||
F0_sampled (batchsize, length, 1)
|
||||
Sine_source (batchsize, length, 1)
|
||||
noise_source (batchsize, length 1)
|
||||
"""
|
||||
with paddle.no_grad():
|
||||
sine_wavs, uv, _ = self.l_sin_gen(paddle.transpose(x,perm=[0,2,1]))
|
||||
sine_wavs = paddle.transpose(sine_wavs,perm=[0,2,1])
|
||||
uv = paddle.transpose(uv,perm=[0,2,1])
|
||||
sine_merge = self.l_tanh(self.l_linear(sine_wavs))
|
||||
|
||||
noise = paddle.randn(shape=uv.shape, dtype=uv.dtype
|
||||
) * self.sine_amp / 3
|
||||
return sine_merge, noise, uv
|
||||
|
||||
|
||||
class SineGen2(paddle.nn.Layer):
|
||||
""" Definition of sine generator
|
||||
SineGen(samp_rate, harmonic_num = 0,
|
||||
sine_amp = 0.1, noise_std = 0.003,
|
||||
voiced_threshold = 0,
|
||||
flag_for_pulse=False)
|
||||
samp_rate: sampling rate in Hz
|
||||
harmonic_num: number of harmonic overtones (default 0)
|
||||
sine_amp: amplitude of sine-wavefrom (default 0.1)
|
||||
noise_std: std of Gaussian noise (default 0.003)
|
||||
voiced_thoreshold: F0 threshold for U/V classification (default 0)
|
||||
flag_for_pulse: this SinGen is used inside PulseGen (default False)
|
||||
Note: when flag_for_pulse is True, the first time step of a voiced
|
||||
segment is always sin(np.pi) or cos(0)
|
||||
"""
|
||||
|
||||
def __init__(self, samp_rate, upsample_scale, harmonic_num=0, sine_amp=
|
||||
0.1, noise_std=0.003, voiced_threshold=0, flag_for_pulse=False):
|
||||
super(SineGen2, self).__init__()
|
||||
self.sine_amp = sine_amp
|
||||
self.noise_std = noise_std
|
||||
self.harmonic_num = harmonic_num
|
||||
self.axis = self.harmonic_num + 1
|
||||
self.sampling_rate = samp_rate
|
||||
self.voiced_threshold = voiced_threshold
|
||||
self.flag_for_pulse = flag_for_pulse
|
||||
self.upsample_scale = upsample_scale
|
||||
|
||||
def _f02uv(self, f0):
|
||||
uv = (f0 > self.voiced_threshold).astype(paddle.float32)
|
||||
return uv
|
||||
|
||||
def _f02sine(self, f0_values):
|
||||
""" f0_values: (batchsize, length, axis)
|
||||
where axis indicates fundamental tone and overtones
|
||||
"""
|
||||
rad_values = f0_values / self.sampling_rate % 1
|
||||
rand_ini = paddle.rand(shape=[f0_values.shape[0], f0_values.shape[2]])
|
||||
rand_ini[:, 0] = 0
|
||||
rad_values[:, 0, :] = rad_values[:, 0, :] + rand_ini
|
||||
if not self.flag_for_pulse:
|
||||
x = paddle.transpose(rad_values,perm = [0,2,1])
|
||||
|
||||
rad_values = paddle.transpose(paddle.nn.functional.interpolate(x=x, scale_factor=1 / self.upsample_scale, mode='linear'),perm = [0,2,1])
|
||||
phase = paddle.cumsum(rad_values, axis=1) * 2 * np.pi
|
||||
phase = paddle.transpose(paddle.nn.functional.interpolate(x=paddle.transpose(phase,perm = [0,2,1]) * self.upsample_scale, scale_factor=int(self.upsample_scale),mode='linear'),perm = [0,2,1])
|
||||
sines = paddle.sin(phase)
|
||||
else:
|
||||
uv = self._f02uv(f0_values)
|
||||
uv_1 = paddle.roll(uv, shifts=-1, axis=1)
|
||||
uv_1[:, -1, :] = 1
|
||||
u_loc = (uv < 1) * (uv_1 > 0)
|
||||
tmp_cumsum = paddle.cumsum(rad_values, axis=1)
|
||||
for idx in range(f0_values.shape[0]):
|
||||
temp_sum = tmp_cumsum[idx, u_loc[idx, :, 0], :]
|
||||
temp_sum[1:, :] = temp_sum[1:, :] - temp_sum[0:-1, :]
|
||||
tmp_cumsum[idx, :, :] = 0
|
||||
tmp_cumsum[idx, u_loc[idx, :, 0], :] = temp_sum
|
||||
i_phase = paddle.cumsum(rad_values - tmp_cumsum, axis=1)
|
||||
sines = paddle.cos(i_phase * 2 * np.pi)
|
||||
return sines
|
||||
|
||||
def forward(self, f0):
|
||||
""" sine_tensor, uv = forward(f0)
|
||||
input F0: tensor(batchsize=1, length, axis=1)
|
||||
f0 for unvoiced steps should be 0
|
||||
output sine_tensor: tensor(batchsize=1, length, axis)
|
||||
output uv: tensor(batchsize=1, length, 1)
|
||||
"""
|
||||
paddle.seed(1986)
|
||||
fn = paddle.multiply(f0, paddle.to_tensor([[range(1, self.harmonic_num +
|
||||
2)]],dtype='float32',place=f0.place))
|
||||
|
||||
sine_waves = self._f02sine(fn) * self.sine_amp
|
||||
uv = self._f02uv(f0)
|
||||
noise_amp = uv * self.noise_std + (1 - uv) * self.sine_amp / 3
|
||||
noise = noise_amp * paddle.randn(shape=sine_waves.shape, dtype=
|
||||
sine_waves.dtype)
|
||||
sine_waves = sine_waves * uv + noise
|
||||
|
||||
return sine_waves, uv, noise
|
||||
|
||||
|
||||
class SourceModuleHnNSF2(paddle.nn.Layer):
|
||||
""" SourceModule for hn-nsf
|
||||
SourceModule(sampling_rate, harmonic_num=0, sine_amp=0.1,
|
||||
add_noise_std=0.003, voiced_threshod=0)
|
||||
sampling_rate: sampling_rate in Hz
|
||||
harmonic_num: number of harmonic above F0 (default: 0)
|
||||
sine_amp: amplitude of sine source signal (default: 0.1)
|
||||
add_noise_std: std of additive Gaussian noise (default: 0.003)
|
||||
note that amplitude of noise in unvoiced is decided
|
||||
by sine_amp
|
||||
voiced_threshold: threhold to set U/V given F0 (default: 0)
|
||||
Sine_source, noise_source = SourceModuleHnNSF(F0_sampled)
|
||||
F0_sampled (batchsize, length, 1)
|
||||
Sine_source (batchsize, length, 1)
|
||||
noise_source (batchsize, length 1)
|
||||
uv (batchsize, length, 1)
|
||||
"""
|
||||
|
||||
def __init__(self, sampling_rate, upsample_scale, harmonic_num=0,
|
||||
sine_amp=0.1, add_noise_std=0.003, voiced_threshod=0):
|
||||
super(SourceModuleHnNSF2, self).__init__()
|
||||
self.sine_amp = sine_amp
|
||||
self.noise_std = add_noise_std
|
||||
self.l_sin_gen = SineGen2(sampling_rate, upsample_scale,
|
||||
harmonic_num, sine_amp, add_noise_std, voiced_threshod)
|
||||
self.l_linear = paddle.nn.Linear(in_features=harmonic_num + 1,
|
||||
out_features=1)
|
||||
self.l_tanh = paddle.nn.Tanh()
|
||||
|
||||
def forward(self, x):
|
||||
"""
|
||||
Sine_source, noise_source = SourceModuleHnNSF(F0_sampled)
|
||||
F0_sampled (batchsize, length, 1)
|
||||
Sine_source (batchsize, length, 1)
|
||||
noise_source (batchsize, length 1)
|
||||
"""
|
||||
paddle.seed(1986)
|
||||
with paddle.no_grad():
|
||||
sine_wavs, uv, _ = self.l_sin_gen(x)
|
||||
sine_merge = self.l_tanh(self.l_linear(sine_wavs))
|
||||
noise = paddle.randn(shape=uv.shape, dtype=uv.dtype
|
||||
) * self.sine_amp / 3
|
||||
return sine_merge, noise, uv
|
||||
|
||||
|
||||
class HiFTGenerator(paddle.nn.Layer):
|
||||
"""
|
||||
HiFTNet Generator: Neural Source Filter + ISTFTNet
|
||||
https://arxiv.org/abs/2309.09493
|
||||
"""
|
||||
|
||||
def __init__(self, in_channels: int=80, base_channels: int=512,
|
||||
nb_harmonics: int=8, sampling_rate: int=22050, nsf_alpha: float=0.1,
|
||||
nsf_sigma: float=0.003, nsf_voiced_threshold: float=10,
|
||||
upsample_rates: List[int]=[8, 8], upsample_kernel_sizes: List[int]=
|
||||
[16, 16], istft_params: Dict[str, int]={'n_fft': 16, 'hop_len': 4},
|
||||
resblock_kernel_sizes: List[int]=[3, 7, 11],
|
||||
resblock_dilation_sizes: List[List[int]]=[[1, 3, 5], [1, 3, 5], [1,
|
||||
3, 5]], source_resblock_kernel_sizes: List[int]=[7, 11],
|
||||
source_resblock_dilation_sizes: List[List[int]]=[[1, 3, 5], [1, 3,
|
||||
5]], lrelu_slope: float=0.1, audio_limit: float=0.99, f0_predictor:
|
||||
paddle.nn.Layer=None):
|
||||
super(HiFTGenerator, self).__init__()
|
||||
self.out_channels = 1
|
||||
self.nb_harmonics = nb_harmonics
|
||||
self.sampling_rate = sampling_rate
|
||||
self.istft_params = istft_params
|
||||
self.lrelu_slope = lrelu_slope
|
||||
self.audio_limit = audio_limit
|
||||
self.num_kernels = len(resblock_kernel_sizes)
|
||||
self.num_upsamples = len(upsample_rates)
|
||||
this_SourceModuleHnNSF = (SourceModuleHnNSF if self.sampling_rate ==
|
||||
22050 else SourceModuleHnNSF2)
|
||||
self.m_source = this_SourceModuleHnNSF(sampling_rate=sampling_rate,
|
||||
upsample_scale=np.prod(upsample_rates) * istft_params['hop_len'
|
||||
], harmonic_num=nb_harmonics, sine_amp=nsf_alpha, add_noise_std
|
||||
=nsf_sigma, voiced_threshod=nsf_voiced_threshold)
|
||||
self.f0_upsamp = paddle.nn.Upsample(scale_factor=(1,int(np.prod( upsample_rates) * istft_params['hop_len'])))
|
||||
self.conv_pre = paddle.nn.utils.weight_norm(layer=paddle.nn.Conv1D(in_channels = in_channels, out_channels = base_channels, kernel_size=7, stride=1, padding=3))
|
||||
self.ups = paddle.nn.LayerList()
|
||||
for i, (u, k) in enumerate(zip(upsample_rates, upsample_kernel_sizes)):
|
||||
self.ups.append(paddle.nn.utils.weight_norm(layer=paddle.nn.
|
||||
Conv1DTranspose(in_channels=base_channels // 2 ** i,
|
||||
out_channels=base_channels // 2 ** (i + 1), kernel_size=k,
|
||||
stride=u, padding=(k - u) // 2)))
|
||||
self.source_downs = paddle.nn.LayerList()
|
||||
self.source_resblocks = paddle.nn.LayerList()
|
||||
downsample_rates = [1] + upsample_rates[::-1][:-1]
|
||||
downsample_cum_rates = np.cumprod(downsample_rates)
|
||||
for i, (u, k, d) in enumerate(zip(downsample_cum_rates[::-1],
|
||||
source_resblock_kernel_sizes, source_resblock_dilation_sizes)):
|
||||
if u == 1:
|
||||
self.source_downs.append(paddle.nn.Conv1D(istft_params[
|
||||
'n_fft'] + 2, base_channels // 2 ** (i + 1), 1, 1))
|
||||
else:
|
||||
self.source_downs.append(paddle.nn.Conv1D(
|
||||
in_channels=istft_params['n_fft'] + 2,
|
||||
out_channels=base_channels // (2 ** (i + 1)),
|
||||
kernel_size=(u * 2,),
|
||||
stride=(u,),
|
||||
padding=int(u // 2),
|
||||
))
|
||||
self.source_resblocks.append(ResBlock(base_channels // 2 ** (i +
|
||||
1), k, d))
|
||||
self.resblocks = paddle.nn.LayerList()
|
||||
for i in range(len(self.ups)):
|
||||
ch = base_channels // 2 ** (i + 1)
|
||||
for _, (k, d) in enumerate(zip(resblock_kernel_sizes,
|
||||
resblock_dilation_sizes)):
|
||||
self.resblocks.append(ResBlock(ch, k, d))
|
||||
self.conv_post = paddle.nn.utils.weight_norm(layer=paddle.nn.Conv1D
|
||||
(ch, istft_params['n_fft'] + 2, 7, 1, padding=3))
|
||||
self.ups.apply(init_weights)
|
||||
self.conv_post.apply(init_weights)
|
||||
self.reflection_pad = paddle.nn.Pad1D(padding=(1, 0), mode='reflect')
|
||||
self.stft_window = paddle.to_tensor(get_window('hann',
|
||||
istft_params['n_fft'], fftbins=True).astype(np.float32))
|
||||
self.f0_predictor = f0_predictor
|
||||
|
||||
def remove_weight_norm(self):
|
||||
print('Removing weight norm...')
|
||||
for l in self.ups:
|
||||
paddle.nn.utils.remove_weight_norm(layer=l)
|
||||
for l in self.resblocks:
|
||||
l.remove_weight_norm()
|
||||
paddle.nn.utils.remove_weight_norm(layer=self.conv_pre)
|
||||
paddle.nn.utils.remove_weight_norm(layer=self.conv_post)
|
||||
self.m_source.remove_weight_norm()
|
||||
for l in self.source_downs:
|
||||
paddle.nn.utils.remove_weight_norm(layer=l)
|
||||
for l in self.source_resblocks:
|
||||
l.remove_weight_norm()
|
||||
|
||||
def _stft(self, x):
|
||||
spec = paddle.signal.stft(x=x, n_fft=self.istft_params['n_fft'],
|
||||
hop_length=self.istft_params['hop_len'], win_length=self.
|
||||
istft_params['n_fft'], window=self.stft_window.to(x.place))
|
||||
spec = paddle.as_real(spec)
|
||||
return spec[..., 0], spec[..., 1]
|
||||
|
||||
def _istft(self, magnitude, phase):
|
||||
magnitude = paddle.clip(magnitude, max=100.0)
|
||||
real = magnitude * paddle.cos(phase)
|
||||
img = magnitude * paddle.sin(phase)
|
||||
inverse_transform = paddle.signal.istft(x=paddle.complex(real, img),
|
||||
n_fft=self.istft_params['n_fft'], hop_length=self.istft_params[
|
||||
'hop_len'], win_length=self.istft_params['n_fft'], window=self.
|
||||
stft_window.to(magnitude.place))
|
||||
return inverse_transform
|
||||
|
||||
def decode(self, x: paddle.Tensor, s: paddle.Tensor=paddle.zeros([1, 1, 0])
|
||||
) ->paddle.Tensor:
|
||||
s_stft_real, s_stft_imag = self._stft(s.squeeze(1))
|
||||
s_stft = paddle.cat([s_stft_real, s_stft_imag], dim=1)
|
||||
x = self.conv_pre(x)
|
||||
for i in range(self.num_upsamples):
|
||||
x = paddle.nn.functional.leaky_relu(x=x, negative_slope=self.
|
||||
lrelu_slope)
|
||||
x = self.ups[i](x)
|
||||
if i == self.num_upsamples - 1:
|
||||
x = self.reflection_pad(x)
|
||||
si = self.source_downs[i](s_stft)
|
||||
si = self.source_resblocks[i](si)
|
||||
x = x + si
|
||||
xs = None
|
||||
for j in range(self.num_kernels):
|
||||
if xs is None:
|
||||
xs = self.resblocks[i * self.num_kernels + j](x)
|
||||
else:
|
||||
xs += self.resblocks[i * self.num_kernels + j](x)
|
||||
x = xs / self.num_kernels
|
||||
x = paddle.nn.functional.leaky_relu(x=x)
|
||||
x = self.conv_post(x)
|
||||
magnitude = paddle.exp(x=x[:, :self.istft_params['n_fft'] // 2 + 1, :])
|
||||
phase = paddle.sin(x[:, self.istft_params['n_fft'] // 2 + 1:, :])
|
||||
x = self._istft(magnitude, phase)
|
||||
x = paddle.clip(x, -self.audio_limit, self.audio_limit)
|
||||
return x
|
||||
|
||||
def forward(self, batch: dict) ->Dict[str,
|
||||
Optional[paddle.Tensor]]:
|
||||
speech_feat = paddle.transpose(batch['speech_feat'],perm = [0,2,1]).to(device)
|
||||
f0 = self.f0_predictor(speech_feat)
|
||||
s = paddle.transpose(self.f0_upsamp(f0[:, None]),perm = [0,2,1])
|
||||
s, _, _ = self.m_source(s)
|
||||
s = paddle.transpose(s,perm = [0,2,1])
|
||||
|
||||
generated_speech = self.decode(x=speech_feat, s=s)
|
||||
return generated_speech, f0
|
||||
|
||||
@paddle.no_grad()
|
||||
def inference(self, speech_feat: paddle.Tensor, cache_source: paddle.
|
||||
Tensor=paddle.zeros([1, 1, 0])) ->paddle.Tensor:
|
||||
paddle.seed(1986)
|
||||
f0 = self.f0_predictor(speech_feat)
|
||||
f0_4d = f0[:, None].unsqueeze(2)
|
||||
s_4d = self.f0_upsamp(f0_4d)
|
||||
s_3d = s_4d.squeeze(2)
|
||||
s = paddle.transpose(s_3d, perm=[0, 2, 1])
|
||||
s, _, _ = self.m_source(s)
|
||||
s = paddle.transpose(s,perm = [0,2,1])
|
||||
if cache_source.shape[2] != 0:
|
||||
s[:, :, :cache_source.shape[2]] = cache_source
|
||||
generated_speech = self.decode(x=speech_feat, s=s)
|
||||
return generated_speech, s
|
||||
@ -0,0 +1,25 @@
|
||||
import paddle
|
||||
class ConvRNNF0Predictor(paddle.nn.Layer):
|
||||
|
||||
def __init__(self, num_class: int=1, in_channels: int=80, cond_channels:
|
||||
int=512):
|
||||
super().__init__()
|
||||
self.num_class = num_class
|
||||
self.condnet = paddle.nn.Sequential(paddle.nn.utils.weight_norm(
|
||||
layer=paddle.nn.Conv1D(in_channels, cond_channels, kernel_size=
|
||||
3, padding=1)), paddle.nn.ELU(), paddle.nn.utils.weight_norm(
|
||||
layer=paddle.nn.Conv1D(cond_channels, cond_channels,
|
||||
kernel_size=3, padding=1)), paddle.nn.ELU(), paddle.nn.utils.
|
||||
weight_norm(layer=paddle.nn.Conv1D(cond_channels, cond_channels,
|
||||
kernel_size=3, padding=1)), paddle.nn.ELU(), paddle.nn.utils.
|
||||
weight_norm(layer=paddle.nn.Conv1D(cond_channels, cond_channels,
|
||||
kernel_size=3, padding=1)), paddle.nn.ELU(), paddle.nn.utils.
|
||||
weight_norm(layer=paddle.nn.Conv1D(cond_channels, cond_channels,
|
||||
kernel_size=3, padding=1)), paddle.nn.ELU())
|
||||
self.classifier = paddle.nn.Linear(in_features=cond_channels,
|
||||
out_features=self.num_class)
|
||||
|
||||
def forward(self, x: paddle.Tensor) ->paddle.Tensor:
|
||||
x = self.condnet(x)
|
||||
x = paddle.transpose(x, perm=[0, 2, 1])
|
||||
return paddle.abs(x=self.classifier(x).squeeze(-1))
|
||||
@ -0,0 +1 @@
|
||||
from .flow import CausalMaskedDiffWithXvec
|
||||
@ -0,0 +1,625 @@
|
||||
import inspect
|
||||
import math
|
||||
from typing import Callable, List, Optional, Union
|
||||
import paddle
|
||||
|
||||
class Attention(paddle.nn.Layer):
|
||||
"""
|
||||
A cross attention layer.
|
||||
|
||||
Parameters:
|
||||
query_dim (`int`):
|
||||
The number of channels in the query.
|
||||
cross_attention_dim (`int`, *optional*):
|
||||
The number of channels in the encoder_hidden_states. If not given, defaults to `query_dim`.
|
||||
heads (`int`, *optional*, defaults to 8):
|
||||
The number of heads to use for multi-head attention.
|
||||
dim_head (`int`, *optional*, defaults to 64):
|
||||
The number of channels in each head.
|
||||
dropout (`float`, *optional*, defaults to 0.0):
|
||||
The dropout probability to use.
|
||||
bias (`bool`, *optional*, defaults to False):
|
||||
Set to `True` for the query, key, and value linear layers to contain a bias parameter.
|
||||
upcast_attention (`bool`, *optional*, defaults to False):
|
||||
Set to `True` to upcast the attention computation to `float32`.
|
||||
upcast_softmax (`bool`, *optional*, defaults to False):
|
||||
Set to `True` to upcast the softmax computation to `float32`.
|
||||
cross_attention_norm (`str`, *optional*, defaults to `None`):
|
||||
The type of normalization to use for the cross attention. Can be `None`, `layer_norm`, or `group_norm`.
|
||||
cross_attention_norm_num_groups (`int`, *optional*, defaults to 32):
|
||||
The number of groups to use for the group norm in the cross attention.
|
||||
added_kv_proj_dim (`int`, *optional*, defaults to `None`):
|
||||
The number of channels to use for the added key and value projections. If `None`, no projection is used.
|
||||
norm_num_groups (`int`, *optional*, defaults to `None`):
|
||||
The number of groups to use for the group norm in the attention.
|
||||
spatial_norm_dim (`int`, *optional*, defaults to `None`):
|
||||
The number of channels to use for the spatial normalization.
|
||||
out_bias (`bool`, *optional*, defaults to `True`):
|
||||
Set to `True` to use a bias in the output linear layer.
|
||||
scale_qk (`bool`, *optional*, defaults to `True`):
|
||||
Set to `True` to scale the query and key by `1 / sqrt(dim_head)`.
|
||||
only_cross_attention (`bool`, *optional*, defaults to `False`):
|
||||
Set to `True` to only use cross attention and not added_kv_proj_dim. Can only be set to `True` if
|
||||
`added_kv_proj_dim` is not `None`.
|
||||
eps (`float`, *optional*, defaults to 1e-5):
|
||||
An additional value added to the denominator in group normalization that is used for numerical stability.
|
||||
rescale_output_factor (`float`, *optional*, defaults to 1.0):
|
||||
A factor to rescale the output by dividing it with this value.
|
||||
residual_connection (`bool`, *optional*, defaults to `False`):
|
||||
Set to `True` to add the residual connection to the output.
|
||||
_from_deprecated_attn_block (`bool`, *optional*, defaults to `False`):
|
||||
Set to `True` if the attention block is loaded from a deprecated state dict.
|
||||
processor (`AttnProcessor`, *optional*, defaults to `None`):
|
||||
The attention processor to use. If `None`, defaults to `AttnProcessor2_0` if `torch 2.x` is used and
|
||||
`AttnProcessor` otherwise.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
query_dim: int,
|
||||
cross_attention_dim: Optional[int] = None,
|
||||
heads: int = 8,
|
||||
dim_head: int = 64,
|
||||
dropout: float = 0.0,
|
||||
bias: bool = False,
|
||||
upcast_attention: bool = False,
|
||||
upcast_softmax: bool = False,
|
||||
cross_attention_norm: Optional[str] = None,
|
||||
cross_attention_norm_num_groups: int = 32,
|
||||
qk_norm: Optional[str] = None,
|
||||
added_kv_proj_dim: Optional[int] = None,
|
||||
norm_num_groups: Optional[int] = None,
|
||||
spatial_norm_dim: Optional[int] = None,
|
||||
out_bias: bool = True,
|
||||
scale_qk: bool = True,
|
||||
only_cross_attention: bool = False,
|
||||
eps: float = 1e-05,
|
||||
rescale_output_factor: float = 1.0,
|
||||
residual_connection: bool = False,
|
||||
_from_deprecated_attn_block: bool = False,
|
||||
processor: Optional["AttnProcessor"] = None,
|
||||
out_dim: int = None,
|
||||
context_pre_only=None,
|
||||
):
|
||||
super().__init__()
|
||||
self.inner_dim = out_dim if out_dim is not None else dim_head * heads
|
||||
self.query_dim = query_dim
|
||||
self.use_bias = bias
|
||||
self.is_cross_attention = cross_attention_dim is not None
|
||||
self.cross_attention_dim = (
|
||||
cross_attention_dim if cross_attention_dim is not None else query_dim
|
||||
)
|
||||
self.upcast_attention = upcast_attention
|
||||
self.upcast_softmax = upcast_softmax
|
||||
self.rescale_output_factor = rescale_output_factor
|
||||
self.residual_connection = residual_connection
|
||||
self.dropout = dropout
|
||||
self.fused_projections = False
|
||||
self.out_dim = out_dim if out_dim is not None else query_dim
|
||||
self.context_pre_only = context_pre_only
|
||||
self._from_deprecated_attn_block = _from_deprecated_attn_block
|
||||
self.scale_qk = scale_qk
|
||||
self.scale = dim_head**-0.5 if self.scale_qk else 1.0
|
||||
self.heads = out_dim // dim_head if out_dim is not None else heads
|
||||
self.sliceable_head_dim = heads
|
||||
self.added_kv_proj_dim = added_kv_proj_dim
|
||||
self.only_cross_attention = only_cross_attention
|
||||
if self.added_kv_proj_dim is None and self.only_cross_attention:
|
||||
raise ValueError(
|
||||
"`only_cross_attention` can only be set to True if `added_kv_proj_dim` is not None. Make sure to set either `only_cross_attention=False` or define `added_kv_proj_dim`."
|
||||
)
|
||||
if norm_num_groups is not None:
|
||||
self.group_norm = paddle.nn.GroupNorm(
|
||||
num_channels=query_dim,
|
||||
num_groups=norm_num_groups,
|
||||
epsilon=eps,
|
||||
weight_attr=True,
|
||||
bias_attr=True,
|
||||
)
|
||||
else:
|
||||
self.group_norm = None
|
||||
if spatial_norm_dim is not None:
|
||||
self.spatial_norm = SpatialNorm(
|
||||
f_channels=query_dim, zq_channels=spatial_norm_dim
|
||||
)
|
||||
else:
|
||||
self.spatial_norm = None
|
||||
if qk_norm is None:
|
||||
self.norm_q = None
|
||||
self.norm_k = None
|
||||
elif qk_norm == "layer_norm":
|
||||
self.norm_q = paddle.nn.LayerNorm(normalized_shape=dim_head, epsilon=eps)
|
||||
self.norm_k = paddle.nn.LayerNorm(normalized_shape=dim_head, epsilon=eps)
|
||||
else:
|
||||
raise ValueError(
|
||||
f"unknown qk_norm: {qk_norm}. Should be None or 'layer_norm'"
|
||||
)
|
||||
if cross_attention_norm is None:
|
||||
self.norm_cross = None
|
||||
elif cross_attention_norm == "layer_norm":
|
||||
self.norm_cross = paddle.nn.LayerNorm(
|
||||
normalized_shape=self.cross_attention_dim
|
||||
)
|
||||
elif cross_attention_norm == "group_norm":
|
||||
if self.added_kv_proj_dim is not None:
|
||||
norm_cross_num_channels = added_kv_proj_dim
|
||||
else:
|
||||
norm_cross_num_channels = self.cross_attention_dim
|
||||
self.norm_cross = paddle.nn.GroupNorm(
|
||||
num_channels=norm_cross_num_channels,
|
||||
num_groups=cross_attention_norm_num_groups,
|
||||
epsilon=1e-05,
|
||||
weight_attr=True,
|
||||
bias_attr=True,
|
||||
)
|
||||
else:
|
||||
raise ValueError(
|
||||
f"unknown cross_attention_norm: {cross_attention_norm}. Should be None, 'layer_norm' or 'group_norm'"
|
||||
)
|
||||
self.to_q = paddle.nn.Linear(
|
||||
in_features=query_dim, out_features=self.inner_dim, bias_attr=bias
|
||||
)
|
||||
if not self.only_cross_attention:
|
||||
self.to_k = paddle.nn.Linear(
|
||||
in_features=self.cross_attention_dim,
|
||||
out_features=self.inner_dim,
|
||||
bias_attr=bias,
|
||||
)
|
||||
self.to_v = paddle.nn.Linear(
|
||||
in_features=self.cross_attention_dim,
|
||||
out_features=self.inner_dim,
|
||||
bias_attr=bias,
|
||||
)
|
||||
else:
|
||||
self.to_k = None
|
||||
self.to_v = None
|
||||
if self.added_kv_proj_dim is not None:
|
||||
self.add_k_proj = paddle.nn.Linear(
|
||||
in_features=added_kv_proj_dim, out_features=self.inner_dim
|
||||
)
|
||||
self.add_v_proj = paddle.nn.Linear(
|
||||
in_features=added_kv_proj_dim, out_features=self.inner_dim
|
||||
)
|
||||
if self.context_pre_only is not None:
|
||||
self.add_q_proj = paddle.nn.Linear(
|
||||
in_features=added_kv_proj_dim, out_features=self.inner_dim
|
||||
)
|
||||
self.to_out = paddle.nn.LayerList(sublayers=[])
|
||||
self.to_out.append(
|
||||
paddle.nn.Linear(
|
||||
in_features=self.inner_dim,
|
||||
out_features=self.out_dim,
|
||||
bias_attr=out_bias,
|
||||
)
|
||||
)
|
||||
self.to_out.append(paddle.nn.Dropout(p=dropout))
|
||||
if self.context_pre_only is not None and not self.context_pre_only:
|
||||
self.to_add_out = paddle.nn.Linear(
|
||||
in_features=self.inner_dim,
|
||||
out_features=self.out_dim,
|
||||
bias_attr=out_bias,
|
||||
)
|
||||
processor = AttnProcessor()
|
||||
processor = AttnProcessor2_0()
|
||||
self.set_processor(processor)
|
||||
|
||||
def set_processor(self, processor: "AttnProcessor") -> None:
|
||||
"""
|
||||
Set the attention processor to use.
|
||||
|
||||
Args:
|
||||
processor (`AttnProcessor`):
|
||||
The attention processor to use.
|
||||
"""
|
||||
if (
|
||||
hasattr(self, "processor")
|
||||
and isinstance(self.processor, paddle.nn.Layer)
|
||||
and not isinstance(processor, paddle.nn.Layer)
|
||||
):
|
||||
self._modules.pop("processor")
|
||||
self.processor = processor
|
||||
|
||||
def forward(
|
||||
self,
|
||||
hidden_states: paddle.Tensor,
|
||||
encoder_hidden_states: Optional[paddle.Tensor] = None,
|
||||
attention_mask: Optional[paddle.Tensor] = None,
|
||||
**cross_attention_kwargs,
|
||||
) -> paddle.Tensor:
|
||||
"""
|
||||
The forward method of the `Attention` class.
|
||||
|
||||
Args:
|
||||
hidden_states (`torch.Tensor`):
|
||||
The hidden states of the query.
|
||||
encoder_hidden_states (`torch.Tensor`, *optional*):
|
||||
The hidden states of the encoder.
|
||||
attention_mask (`torch.Tensor`, *optional*):
|
||||
The attention mask to use. If `None`, no mask is applied.
|
||||
**cross_attention_kwargs:
|
||||
Additional keyword arguments to pass along to the cross attention.
|
||||
|
||||
Returns:
|
||||
`torch.Tensor`: The output of the attention layer.
|
||||
"""
|
||||
attn_parameters = set(
|
||||
inspect.signature(self.processor.__call__).parameters.keys()
|
||||
)
|
||||
quiet_attn_parameters = {"ip_adapter_masks"}
|
||||
unused_kwargs = [
|
||||
k
|
||||
for k, _ in cross_attention_kwargs.items()
|
||||
if k not in attn_parameters and k not in quiet_attn_parameters
|
||||
]
|
||||
if len(unused_kwargs) > 0:
|
||||
logger.warning(
|
||||
f"cross_attention_kwargs {unused_kwargs} are not expected by {self.processor.__class__.__name__} and will be ignored."
|
||||
)
|
||||
cross_attention_kwargs = {
|
||||
k: w for k, w in cross_attention_kwargs.items() if k in attn_parameters
|
||||
}
|
||||
return self.processor(
|
||||
self,
|
||||
hidden_states,
|
||||
encoder_hidden_states=encoder_hidden_states,
|
||||
attention_mask=attention_mask,
|
||||
**cross_attention_kwargs,
|
||||
)
|
||||
|
||||
def batch_to_head_dim(self, tensor: paddle.Tensor) -> paddle.Tensor:
|
||||
"""
|
||||
Reshape the tensor from `[batch_size, seq_len, dim]` to `[batch_size // heads, seq_len, dim * heads]`. `heads`
|
||||
is the number of heads initialized while constructing the `Attention` class.
|
||||
|
||||
Args:
|
||||
tensor (`torch.Tensor`): The tensor to reshape.
|
||||
|
||||
Returns:
|
||||
`torch.Tensor`: The reshaped tensor.
|
||||
"""
|
||||
head_size = self.heads
|
||||
batch_size, seq_len, dim = tensor.shape
|
||||
tensor = tensor.reshape(batch_size // head_size, head_size, seq_len, dim)
|
||||
tensor = tensor.permute(0, 2, 1, 3).reshape(
|
||||
batch_size // head_size, seq_len, dim * head_size
|
||||
)
|
||||
return tensor
|
||||
|
||||
def head_to_batch_dim(
|
||||
self, tensor: paddle.Tensor, out_dim: int = 3
|
||||
) -> paddle.Tensor:
|
||||
"""
|
||||
Reshape the tensor from `[batch_size, seq_len, dim]` to `[batch_size, seq_len, heads, dim // heads]` `heads` is
|
||||
the number of heads initialized while constructing the `Attention` class.
|
||||
|
||||
Args:
|
||||
tensor (`torch.Tensor`): The tensor to reshape.
|
||||
out_dim (`int`, *optional*, defaults to `3`): The output dimension of the tensor. If `3`, the tensor is
|
||||
reshaped to `[batch_size * heads, seq_len, dim // heads]`.
|
||||
|
||||
Returns:
|
||||
`torch.Tensor`: The reshaped tensor.
|
||||
"""
|
||||
head_size = self.heads
|
||||
if tensor.ndim == 3:
|
||||
batch_size, seq_len, dim = tensor.shape
|
||||
extra_dim = 1
|
||||
else:
|
||||
batch_size, extra_dim, seq_len, dim = tensor.shape
|
||||
tensor = tensor.reshape(
|
||||
batch_size, seq_len * extra_dim, head_size, dim // head_size
|
||||
)
|
||||
tensor = tensor.permute(0, 2, 1, 3)
|
||||
if out_dim == 3:
|
||||
tensor = tensor.reshape(
|
||||
batch_size * head_size, seq_len * extra_dim, dim // head_size
|
||||
)
|
||||
return tensor
|
||||
|
||||
def get_attention_scores(
|
||||
self,
|
||||
query: paddle.Tensor,
|
||||
key: paddle.Tensor,
|
||||
attention_mask: paddle.Tensor = None,
|
||||
) -> paddle.Tensor:
|
||||
"""
|
||||
Compute the attention scores.
|
||||
|
||||
Args:
|
||||
query (`torch.Tensor`): The query tensor.
|
||||
key (`torch.Tensor`): The key tensor.
|
||||
attention_mask (`torch.Tensor`, *optional*): The attention mask to use. If `None`, no mask is applied.
|
||||
|
||||
Returns:
|
||||
`torch.Tensor`: The attention probabilities/scores.
|
||||
"""
|
||||
dtype = query.dtype
|
||||
if self.upcast_attention:
|
||||
query = query.float()
|
||||
key = key.float()
|
||||
if attention_mask is None:
|
||||
baddbmm_input = paddle.empty(
|
||||
query.shape[0],
|
||||
query.shape[1],
|
||||
key.shape[1],
|
||||
dtype=query.dtype,
|
||||
device=query.place,
|
||||
)
|
||||
beta = 0
|
||||
else:
|
||||
baddbmm_input = attention_mask
|
||||
beta = 1
|
||||
attention_scores = paddle.baddbmm(
|
||||
input=baddbmm_input,
|
||||
x=query,
|
||||
y=key.transpose(-1, -2),
|
||||
beta=beta,
|
||||
alpha=self.scale,
|
||||
)
|
||||
del baddbmm_input
|
||||
if self.upcast_softmax:
|
||||
attention_scores = attention_scores.float()
|
||||
attention_probs = attention_scores.softmax(dim=-1)
|
||||
del attention_scores
|
||||
attention_probs = attention_probs.to(dtype)
|
||||
return attention_probs
|
||||
|
||||
def prepare_attention_mask(
|
||||
self,
|
||||
attention_mask: paddle.Tensor,
|
||||
target_length: int,
|
||||
batch_size: int,
|
||||
out_dim: int = 3,
|
||||
) -> paddle.Tensor:
|
||||
"""
|
||||
Prepare the attention mask for the attention computation.
|
||||
|
||||
Args:
|
||||
attention_mask (`torch.Tensor`):
|
||||
The attention mask to prepare.
|
||||
target_length (`int`):
|
||||
The target length of the attention mask. This is the length of the attention mask after padding.
|
||||
batch_size (`int`):
|
||||
The batch size, which is used to repeat the attention mask.
|
||||
out_dim (`int`, *optional*, defaults to `3`):
|
||||
The output dimension of the attention mask. Can be either `3` or `4`.
|
||||
|
||||
Returns:
|
||||
`torch.Tensor`: The prepared attention mask.
|
||||
"""
|
||||
head_size = self.heads
|
||||
if attention_mask is None:
|
||||
return attention_mask
|
||||
current_length: int = attention_mask.shape[-1]
|
||||
if current_length != target_length:
|
||||
if attention_mask.device.type == "mps":
|
||||
padding_shape = (
|
||||
attention_mask.shape[0],
|
||||
attention_mask.shape[1],
|
||||
target_length,
|
||||
)
|
||||
padding = paddle.zeros(
|
||||
padding_shape,
|
||||
dtype=attention_mask.dtype,
|
||||
device=attention_mask.place,
|
||||
)
|
||||
attention_mask = paddle.cat([attention_mask, padding], dim=2)
|
||||
else:
|
||||
attention_mask = paddle.compat.pad(
|
||||
attention_mask, (0, target_length), value=0.0
|
||||
)
|
||||
if out_dim == 3:
|
||||
if attention_mask.shape[0] < batch_size * head_size:
|
||||
attention_mask = attention_mask.repeat_interleave(head_size, axis=0)
|
||||
elif out_dim == 4:
|
||||
attention_mask = attention_mask.unsqueeze(1)
|
||||
attention_mask = attention_mask.repeat_interleave(head_size, dim=1)
|
||||
return attention_mask
|
||||
|
||||
def norm_encoder_hidden_states(
|
||||
self, encoder_hidden_states: paddle.Tensor
|
||||
) -> paddle.Tensor:
|
||||
"""
|
||||
Normalize the encoder hidden states. Requires `self.norm_cross` to be specified when constructing the
|
||||
`Attention` class.
|
||||
|
||||
Args:
|
||||
encoder_hidden_states (`torch.Tensor`): Hidden states of the encoder.
|
||||
|
||||
Returns:
|
||||
`torch.Tensor`: The normalized encoder hidden states.
|
||||
"""
|
||||
assert (
|
||||
self.norm_cross is not None
|
||||
), "self.norm_cross must be defined to call self.norm_encoder_hidden_states"
|
||||
if isinstance(self.norm_cross, paddle.nn.LayerNorm):
|
||||
encoder_hidden_states = self.norm_cross(encoder_hidden_states)
|
||||
elif isinstance(self.norm_cross, paddle.nn.GroupNorm):
|
||||
encoder_hidden_states = encoder_hidden_states.transpose(1, 2)
|
||||
encoder_hidden_states = self.norm_cross(encoder_hidden_states)
|
||||
encoder_hidden_states = encoder_hidden_states.transpose(1, 2)
|
||||
else:
|
||||
assert False
|
||||
return encoder_hidden_states
|
||||
|
||||
@paddle.no_grad()
|
||||
def fuse_projections(self, fuse=True):
|
||||
device = self.to_q.weight.data.place
|
||||
dtype = self.to_q.weight.data.dtype
|
||||
if not self.is_cross_attention:
|
||||
concatenated_weights = paddle.cat(
|
||||
[self.to_q.weight.data, self.to_k.weight.data, self.to_v.weight.data]
|
||||
)
|
||||
in_features = concatenated_weights.shape[1]
|
||||
out_features = concatenated_weights.shape[0]
|
||||
self.to_qkv = paddle.nn.Linear(
|
||||
in_features=in_features,
|
||||
out_features=out_features,
|
||||
bias_attr=self.use_bias,
|
||||
)
|
||||
self.to_qkv.weight.copy_(concatenated_weights)
|
||||
if self.use_bias:
|
||||
concatenated_bias = paddle.cat(
|
||||
[self.to_q.bias.data, self.to_k.bias.data, self.to_v.bias.data]
|
||||
)
|
||||
self.to_qkv.bias.copy_(concatenated_bias)
|
||||
else:
|
||||
concatenated_weights = paddle.cat(
|
||||
[self.to_k.weight.data, self.to_v.weight.data]
|
||||
)
|
||||
in_features = concatenated_weights.shape[1]
|
||||
out_features = concatenated_weights.shape[0]
|
||||
self.to_kv = paddle.nn.Linear(
|
||||
in_features=in_features,
|
||||
out_features=out_features,
|
||||
bias_attr=self.use_bias,
|
||||
)
|
||||
self.to_kv.weight.copy_(concatenated_weights)
|
||||
if self.use_bias:
|
||||
concatenated_bias = paddle.cat(
|
||||
[self.to_k.bias.data, self.to_v.bias.data]
|
||||
)
|
||||
self.to_kv.bias.copy_(concatenated_bias)
|
||||
self.fused_projections = fuse
|
||||
|
||||
|
||||
class AttnProcessor:
|
||||
"""
|
||||
Default processor for performing attention-related computations.
|
||||
"""
|
||||
|
||||
def __call__(
|
||||
self,
|
||||
attn: Attention,
|
||||
hidden_states: paddle.Tensor,
|
||||
encoder_hidden_states: Optional[paddle.Tensor] = None,
|
||||
attention_mask: Optional[paddle.Tensor] = None,
|
||||
temb: Optional[paddle.Tensor] = None,
|
||||
*args,
|
||||
**kwargs,
|
||||
) -> paddle.Tensor:
|
||||
residual = hidden_states
|
||||
if attn.spatial_norm is not None:
|
||||
hidden_states = attn.spatial_norm(hidden_states, temb)
|
||||
input_ndim = hidden_states.ndim
|
||||
if input_ndim == 4:
|
||||
batch_size, channel, height, width = hidden_states.shape
|
||||
hidden_states = hidden_states.view(
|
||||
batch_size, channel, height * width
|
||||
).transpose(1, 2)
|
||||
batch_size, sequence_length, _ = (
|
||||
hidden_states.shape
|
||||
if encoder_hidden_states is None
|
||||
else encoder_hidden_states.shape
|
||||
)
|
||||
attention_mask = attn.prepare_attention_mask(
|
||||
attention_mask, sequence_length, batch_size
|
||||
)
|
||||
if attn.group_norm is not None:
|
||||
hidden_states = attn.group_norm(hidden_states.transpose(1, 2)).transpose(
|
||||
1, 2
|
||||
)
|
||||
query = attn.to_q(hidden_states)
|
||||
if encoder_hidden_states is None:
|
||||
encoder_hidden_states = hidden_states
|
||||
elif attn.norm_cross:
|
||||
encoder_hidden_states = attn.norm_encoder_hidden_states(
|
||||
encoder_hidden_states
|
||||
)
|
||||
key = attn.to_k(encoder_hidden_states)
|
||||
value = attn.to_v(encoder_hidden_states)
|
||||
query = attn.head_to_batch_dim(query)
|
||||
key = attn.head_to_batch_dim(key)
|
||||
value = attn.head_to_batch_dim(value)
|
||||
attention_probs = attn.get_attention_scores(query, key, attention_mask)
|
||||
hidden_states = paddle.bmm(attention_probs, value)
|
||||
hidden_states = attn.batch_to_head_dim(hidden_states)
|
||||
hidden_states = attn.to_out[0](hidden_states)
|
||||
hidden_states = attn.to_out[1](hidden_states)
|
||||
if input_ndim == 4:
|
||||
hidden_states = hidden_states.transpose(-1, -2).reshape(
|
||||
batch_size, channel, height, width
|
||||
)
|
||||
if attn.residual_connection:
|
||||
hidden_states = hidden_states + residual
|
||||
hidden_states = hidden_states / attn.rescale_output_factor
|
||||
return hidden_states
|
||||
|
||||
class AttnProcessor2_0:
|
||||
"""
|
||||
Processor for implementing scaled dot-product attention (enabled by default if you're using PyTorch 2.0).
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
def __call__(
|
||||
self,
|
||||
attn: Attention,
|
||||
hidden_states: paddle.Tensor,
|
||||
encoder_hidden_states: Optional[paddle.Tensor] = None,
|
||||
attention_mask: Optional[paddle.Tensor] = None,
|
||||
temb: Optional[paddle.Tensor] = None,
|
||||
*args,
|
||||
**kwargs,
|
||||
) -> paddle.Tensor:
|
||||
residual = hidden_states
|
||||
if attn.spatial_norm is not None:
|
||||
hidden_states = attn.spatial_norm(hidden_states, temb)
|
||||
input_ndim = hidden_states.ndim
|
||||
if input_ndim == 4:
|
||||
batch_size, channel, height, width = hidden_states.shape
|
||||
hidden_states = hidden_states.view(
|
||||
batch_size, channel, height * width
|
||||
).transpose(1, 2)
|
||||
batch_size, sequence_length, _ = (
|
||||
hidden_states.shape
|
||||
if encoder_hidden_states is None
|
||||
else encoder_hidden_states.shape
|
||||
)
|
||||
if attention_mask is not None:
|
||||
attention_mask = attn.prepare_attention_mask(
|
||||
attention_mask, sequence_length, batch_size
|
||||
)
|
||||
attention_mask = attention_mask.view(
|
||||
[batch_size, attn.heads, -1, attention_mask.shape[-1]]
|
||||
)
|
||||
if attn.group_norm is not None:
|
||||
hidden_states = attn.group_norm(hidden_states.transpose(1, 2)).transpose(
|
||||
1, 2
|
||||
)
|
||||
query = attn.to_q(hidden_states)
|
||||
if encoder_hidden_states is None:
|
||||
encoder_hidden_states = hidden_states
|
||||
elif attn.norm_cross:
|
||||
encoder_hidden_states = attn.norm_encoder_hidden_states(
|
||||
encoder_hidden_states
|
||||
)
|
||||
key = attn.to_k(encoder_hidden_states)
|
||||
value = attn.to_v(encoder_hidden_states)
|
||||
inner_dim = key.shape[-1]
|
||||
head_dim = inner_dim // attn.heads
|
||||
query = paddle.transpose(query.view([batch_size, -1, attn.heads, head_dim]),perm = [0,2,1])
|
||||
key = paddle.transpose(key.view([batch_size, -1, attn.heads, head_dim]),perm = [0,2,1])
|
||||
value =paddle.transpose(value.view([batch_size, -1, attn.heads, head_dim]),perm = [0,2,1])
|
||||
hidden_states = paddle.nn.functional.scaled_dot_product_attention(
|
||||
query.transpose([0, 2, 1, 3]),
|
||||
key.transpose([0, 2, 1, 3]),
|
||||
value.transpose([0, 2, 1, 3]),
|
||||
attn_mask=attention_mask,
|
||||
dropout_p=0.0,
|
||||
is_causal=False,
|
||||
).transpose([0, 2, 1, 3])
|
||||
hidden_states = paddle.transpose(hidden_states,perm = [0,2,1]).reshape(
|
||||
[batch_size, -1, attn.heads * head_dim]
|
||||
)
|
||||
hidden_states = hidden_states.to(query.dtype)
|
||||
hidden_states = attn.to_out[0](hidden_states)
|
||||
hidden_states = attn.to_out[1](hidden_states)
|
||||
if input_ndim == 4:
|
||||
hidden_states =paddle.transpose(hidden_states,perm = [0,1,3,2]).reshape(
|
||||
[batch_size, channel, height, width]
|
||||
)
|
||||
if attn.residual_connection:
|
||||
hidden_states = hidden_states + residual
|
||||
hidden_states = hidden_states / attn.rescale_output_factor
|
||||
return hidden_states
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,99 @@
|
||||
import paddle
|
||||
|
||||
"""ConvolutionModule definition."""
|
||||
from typing import Tuple
|
||||
|
||||
|
||||
class ConvolutionModule(paddle.nn.Layer):
|
||||
"""ConvolutionModule in Conformer model."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
channels: int,
|
||||
kernel_size: int = 15,
|
||||
activation: paddle.nn.Layer = paddle.nn.ReLU(),
|
||||
norm: str = "batch_norm",
|
||||
causal: bool = False,
|
||||
bias: bool = True,
|
||||
):
|
||||
"""Construct an ConvolutionModule object.
|
||||
Args:
|
||||
channels (int): The number of channels of conv layers.
|
||||
kernel_size (int): Kernel size of conv layers.
|
||||
causal (int): Whether use causal convolution or not
|
||||
"""
|
||||
super().__init__()
|
||||
self.pointwise_conv1 = paddle.nn.Conv1d(
|
||||
channels, 2 * channels, kernel_size=1, stride=1, padding=0, bias=bias
|
||||
)
|
||||
if causal:
|
||||
padding = 0
|
||||
self.lorder = kernel_size - 1
|
||||
else:
|
||||
assert (kernel_size - 1) % 2 == 0
|
||||
padding = (kernel_size - 1) // 2
|
||||
self.lorder = 0
|
||||
self.depthwise_conv = paddle.nn.Conv1d(
|
||||
channels,
|
||||
channels,
|
||||
kernel_size,
|
||||
stride=1,
|
||||
padding=padding,
|
||||
groups=channels,
|
||||
bias=bias,
|
||||
)
|
||||
assert norm in ["batch_norm", "layer_norm"]
|
||||
if norm == "batch_norm":
|
||||
self.use_layer_norm = False
|
||||
self.norm = paddle.nn.BatchNorm1D(num_features=channels)
|
||||
else:
|
||||
self.use_layer_norm = True
|
||||
self.norm = paddle.nn.LayerNorm(normalized_shape=channels)
|
||||
self.pointwise_conv2 = paddle.nn.Conv1d(
|
||||
channels, channels, kernel_size=1, stride=1, padding=0, bias=bias
|
||||
)
|
||||
self.activation = activation
|
||||
|
||||
def forward(
|
||||
self,
|
||||
x: paddle.Tensor,
|
||||
mask_pad: paddle.Tensor = paddle.ones((0, 0, 0), dtype=paddle.bool),
|
||||
cache: paddle.Tensor = paddle.zeros((0, 0, 0)),
|
||||
) -> Tuple[paddle.Tensor, paddle.Tensor]:
|
||||
"""Compute convolution module.
|
||||
Args:
|
||||
x (torch.Tensor): Input tensor (#batch, time, channels).
|
||||
mask_pad (torch.Tensor): used for batch padding (#batch, 1, time),
|
||||
(0, 0, 0) means fake mask.
|
||||
cache (torch.Tensor): left context cache, it is only
|
||||
used in causal convolution (#batch, channels, cache_t),
|
||||
(0, 0, 0) meas fake cache.
|
||||
Returns:
|
||||
torch.Tensor: Output tensor (#batch, time, channels).
|
||||
"""
|
||||
x = x.transpose(1, 2)
|
||||
if mask_pad.size(2) > 0:
|
||||
x.masked_fill_(~mask_pad, 0.0)
|
||||
if self.lorder > 0:
|
||||
if cache.size(2) == 0:
|
||||
x = paddle.compat.pad(x, (self.lorder, 0), "constant", 0.0)
|
||||
else:
|
||||
assert cache.size(0) == x.size(0)
|
||||
assert cache.size(1) == x.size(1)
|
||||
x = paddle.cat((cache, x), dim=2)
|
||||
assert x.size(2) > self.lorder
|
||||
new_cache = x[:, :, -self.lorder :]
|
||||
else:
|
||||
new_cache = paddle.zeros((0, 0, 0), dtype=x.dtype, device=x.place)
|
||||
x = self.pointwise_conv1(x)
|
||||
x = paddle.nn.functional.glu(x=x, axis=1)
|
||||
x = self.depthwise_conv(x)
|
||||
if self.use_layer_norm:
|
||||
x = x.transpose(1, 2)
|
||||
x = self.activation(self.norm(x))
|
||||
if self.use_layer_norm:
|
||||
x = x.transpose(1, 2)
|
||||
x = self.pointwise_conv2(x)
|
||||
if mask_pad.size(2) > 0:
|
||||
x.masked_fill_(~mask_pad, 0.0)
|
||||
return x.transpose(1, 2), new_cache
|
||||
@ -0,0 +1,132 @@
|
||||
import paddle
|
||||
|
||||
from ..utils import deprecate
|
||||
from ..utils.import_utils import is_torch_npu_available
|
||||
|
||||
if is_torch_npu_available():
|
||||
import torch_npu
|
||||
ACTIVATION_FUNCTIONS = {
|
||||
"swish": paddle.nn.SiLU(),
|
||||
"silu": paddle.nn.SiLU(),
|
||||
"mish": paddle.nn.Mish(),
|
||||
"gelu": paddle.nn.GELU(),
|
||||
"relu": paddle.nn.ReLU(),
|
||||
}
|
||||
|
||||
|
||||
def get_activation(act_fn: str) -> paddle.nn.Layer:
|
||||
"""Helper function to get activation function from string.
|
||||
|
||||
Args:
|
||||
act_fn (str): Name of activation function.
|
||||
|
||||
Returns:
|
||||
nn.Module: Activation function.
|
||||
"""
|
||||
act_fn = act_fn.lower()
|
||||
if act_fn in ACTIVATION_FUNCTIONS:
|
||||
return ACTIVATION_FUNCTIONS[act_fn]
|
||||
else:
|
||||
raise ValueError(f"Unsupported activation function: {act_fn}")
|
||||
|
||||
|
||||
class FP32SiLU(paddle.nn.Layer):
|
||||
"""
|
||||
SiLU activation function with input upcasted to torch.float32.
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
def forward(self, inputs: paddle.Tensor) -> paddle.Tensor:
|
||||
return paddle.nn.functional.silu(inputs.float(), inplace=False).to(inputs.dtype)
|
||||
|
||||
|
||||
class GELU(paddle.nn.Layer):
|
||||
"""
|
||||
GELU activation function with tanh approximation support with `approximate="tanh"`.
|
||||
|
||||
Parameters:
|
||||
dim_in (`int`): The number of channels in the input.
|
||||
dim_out (`int`): The number of channels in the output.
|
||||
approximate (`str`, *optional*, defaults to `"none"`): If `"tanh"`, use tanh approximation.
|
||||
bias (`bool`, defaults to True): Whether to use a bias in the linear layer.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self, dim_in: int, dim_out: int, approximate: str = "none", bias: bool = True
|
||||
):
|
||||
super().__init__()
|
||||
self.proj = paddle.nn.Linear(
|
||||
in_features=dim_in, out_features=dim_out, bias_attr=bias
|
||||
)
|
||||
self.approximate = approximate
|
||||
|
||||
def gelu(self, gate: paddle.Tensor) -> paddle.Tensor:
|
||||
if gate.device.type != "mps":
|
||||
return paddle.nn.functional.gelu(gate, approximate=self.approximate)
|
||||
return paddle.nn.functional.gelu(
|
||||
gate.to(dtype=paddle.float32), approximate=self.approximate
|
||||
).to(dtype=gate.dtype)
|
||||
|
||||
def forward(self, hidden_states):
|
||||
hidden_states = self.proj(hidden_states)
|
||||
hidden_states = self.gelu(hidden_states)
|
||||
return hidden_states
|
||||
|
||||
|
||||
class GEGLU(paddle.nn.Layer):
|
||||
"""
|
||||
A [variant](https://arxiv.org/abs/2002.05202) of the gated linear unit activation function.
|
||||
|
||||
Parameters:
|
||||
dim_in (`int`): The number of channels in the input.
|
||||
dim_out (`int`): The number of channels in the output.
|
||||
bias (`bool`, defaults to True): Whether to use a bias in the linear layer.
|
||||
"""
|
||||
|
||||
def __init__(self, dim_in: int, dim_out: int, bias: bool = True):
|
||||
super().__init__()
|
||||
self.proj = paddle.nn.Linear(
|
||||
in_features=dim_in, out_features=dim_out * 2, bias_attr=bias
|
||||
)
|
||||
|
||||
def gelu(self, gate: paddle.Tensor) -> paddle.Tensor:
|
||||
if gate.device.type != "mps":
|
||||
return paddle.nn.functional.gelu(gate)
|
||||
return paddle.nn.functional.gelu(gate.to(dtype=paddle.float32)).to(
|
||||
dtype=gate.dtype
|
||||
)
|
||||
|
||||
def forward(self, hidden_states, *args, **kwargs):
|
||||
if len(args) > 0 or kwargs.get("scale", None) is not None:
|
||||
deprecation_message = "The `scale` argument is deprecated and will be ignored. Please remove it, as passing it will raise an error in the future. `scale` should directly be passed while calling the underlying pipeline component i.e., via `cross_attention_kwargs`."
|
||||
deprecate("scale", "1.0.0", deprecation_message)
|
||||
hidden_states = self.proj(hidden_states)
|
||||
if is_torch_npu_available():
|
||||
return torch_npu.npu_geglu(hidden_states, dim=-1, approximate=1)[0]
|
||||
else:
|
||||
hidden_states, gate = hidden_states.chunk(2, dim=-1)
|
||||
return hidden_states * self.gelu(gate)
|
||||
|
||||
|
||||
class ApproximateGELU(paddle.nn.Layer):
|
||||
"""
|
||||
The approximate form of the Gaussian Error Linear Unit (GELU). For more details, see section 2 of this
|
||||
[paper](https://arxiv.org/abs/1606.08415).
|
||||
|
||||
Parameters:
|
||||
dim_in (`int`): The number of channels in the input.
|
||||
dim_out (`int`): The number of channels in the output.
|
||||
bias (`bool`, defaults to True): Whether to use a bias in the linear layer.
|
||||
"""
|
||||
|
||||
def __init__(self, dim_in: int, dim_out: int, bias: bool = True):
|
||||
super().__init__()
|
||||
self.proj = paddle.nn.Linear(
|
||||
in_features=dim_in, out_features=dim_out, bias_attr=bias
|
||||
)
|
||||
|
||||
def forward(self, x: paddle.Tensor) -> paddle.Tensor:
|
||||
x = self.proj(x)
|
||||
return x * paddle.nn.functional.sigmoid(1.702 * x)
|
||||
@ -0,0 +1,124 @@
|
||||
from abc import ABC
|
||||
|
||||
import paddle
|
||||
from matcha.models.components.decoder import Decoder
|
||||
from matcha.utils.pylogger import get_pylogger
|
||||
|
||||
log = get_pylogger(__name__)
|
||||
|
||||
|
||||
class BASECFM(paddle.nn.Layer, ABC):
|
||||
def __init__(self, n_feats, cfm_params, n_spks=1, spk_emb_dim=128):
|
||||
super().__init__()
|
||||
self.n_feats = n_feats
|
||||
self.n_spks = n_spks
|
||||
self.spk_emb_dim = spk_emb_dim
|
||||
self.solver = cfm_params.solver
|
||||
if hasattr(cfm_params, "sigma_min"):
|
||||
self.sigma_min = cfm_params.sigma_min
|
||||
else:
|
||||
self.sigma_min = 0.0001
|
||||
self.estimator = None
|
||||
|
||||
@paddle.no_grad()
|
||||
def forward(self, mu, mask, n_timesteps, temperature=1.0, spks=None, cond=None):
|
||||
"""Forward diffusion
|
||||
|
||||
Args:
|
||||
mu (torch.Tensor): output of encoder
|
||||
shape: (batch_size, n_feats, mel_timesteps)
|
||||
mask (torch.Tensor): output_mask
|
||||
shape: (batch_size, 1, mel_timesteps)
|
||||
n_timesteps (int): number of diffusion steps
|
||||
temperature (float, optional): temperature for scaling noise. Defaults to 1.0.
|
||||
spks (torch.Tensor, optional): speaker ids. Defaults to None.
|
||||
shape: (batch_size, spk_emb_dim)
|
||||
cond: Not used but kept for future purposes
|
||||
|
||||
Returns:
|
||||
sample: generated mel-spectrogram
|
||||
shape: (batch_size, n_feats, mel_timesteps)
|
||||
"""
|
||||
z = paddle.randn(shape=mu.shape, dtype=mu.dtype) * temperature
|
||||
t_span = paddle.linspace(start=0, stop=1, num=n_timesteps + 1)
|
||||
return self.solve_euler(
|
||||
z, t_span=t_span, mu=mu, mask=mask, spks=spks, cond=cond
|
||||
)
|
||||
|
||||
def solve_euler(self, x, t_span, mu, mask, spks, cond):
|
||||
"""
|
||||
Fixed euler solver for ODEs.
|
||||
Args:
|
||||
x (torch.Tensor): random noise
|
||||
t_span (torch.Tensor): n_timesteps interpolated
|
||||
shape: (n_timesteps + 1,)
|
||||
mu (torch.Tensor): output of encoder
|
||||
shape: (batch_size, n_feats, mel_timesteps)
|
||||
mask (torch.Tensor): output_mask
|
||||
shape: (batch_size, 1, mel_timesteps)
|
||||
spks (torch.Tensor, optional): speaker ids. Defaults to None.
|
||||
shape: (batch_size, spk_emb_dim)
|
||||
cond: Not used but kept for future purposes
|
||||
"""
|
||||
t, _, dt = t_span[0], t_span[-1], t_span[1] - t_span[0]
|
||||
sol = []
|
||||
for step in range(1, len(t_span)):
|
||||
dphi_dt = self.estimator(x, mask, mu, t, spks, cond)
|
||||
x = x + dt * dphi_dt
|
||||
t = t + dt
|
||||
sol.append(x)
|
||||
if step < len(t_span) - 1:
|
||||
dt = t_span[step + 1] - t
|
||||
return sol[-1]
|
||||
|
||||
def compute_loss(self, x1, mask, mu, spks=None, cond=None):
|
||||
"""Computes diffusion loss
|
||||
|
||||
Args:
|
||||
x1 (torch.Tensor): Target
|
||||
shape: (batch_size, n_feats, mel_timesteps)
|
||||
mask (torch.Tensor): target mask
|
||||
shape: (batch_size, 1, mel_timesteps)
|
||||
mu (torch.Tensor): output of encoder
|
||||
shape: (batch_size, n_feats, mel_timesteps)
|
||||
spks (torch.Tensor, optional): speaker embedding. Defaults to None.
|
||||
shape: (batch_size, spk_emb_dim)
|
||||
|
||||
Returns:
|
||||
loss: conditional flow matching loss
|
||||
y: conditional flow
|
||||
shape: (batch_size, n_feats, mel_timesteps)
|
||||
"""
|
||||
b, _, t = mu.shape
|
||||
t = paddle.rand(shape=[b, 1, 1], dtype=mu.dtype)
|
||||
z = paddle.randn(shape=x1.shape, dtype=x1.dtype)
|
||||
y = (1 - (1 - self.sigma_min) * t) * z + t * x1
|
||||
u = x1 - (1 - self.sigma_min) * z
|
||||
loss = paddle.nn.functional.mse_loss(
|
||||
input=self.estimator(y, mask, mu, t.squeeze(), spks),
|
||||
label=u,
|
||||
reduction="sum",
|
||||
) / (paddle.sum(mask) * u.shape[1])
|
||||
return loss, y
|
||||
|
||||
|
||||
class CFM(BASECFM):
|
||||
def __init__(
|
||||
self,
|
||||
in_channels,
|
||||
out_channel,
|
||||
cfm_params,
|
||||
decoder_params,
|
||||
n_spks=1,
|
||||
spk_emb_dim=64,
|
||||
):
|
||||
super().__init__(
|
||||
n_feats=in_channels,
|
||||
cfm_params=cfm_params,
|
||||
n_spks=n_spks,
|
||||
spk_emb_dim=spk_emb_dim,
|
||||
)
|
||||
in_channels = in_channels + (spk_emb_dim if n_spks > 1 else 0)
|
||||
self.estimator = Decoder(
|
||||
in_channels=in_channels, out_channels=out_channel, **decoder_params
|
||||
)
|
||||
@ -0,0 +1,123 @@
|
||||
from typing import Optional, Tuple, Union
|
||||
|
||||
import paddle
|
||||
|
||||
|
||||
class LoRALinearLayer(paddle.nn.Layer):
|
||||
"""
|
||||
A linear layer that is used with LoRA.
|
||||
|
||||
Parameters:
|
||||
in_features (`int`):
|
||||
Number of input features.
|
||||
out_features (`int`):
|
||||
Number of output features.
|
||||
rank (`int`, `optional`, defaults to 4):
|
||||
The rank of the LoRA layer.
|
||||
network_alpha (`float`, `optional`, defaults to `None`):
|
||||
The value of the network alpha used for stable learning and preventing underflow. This value has the same
|
||||
meaning as the `--network_alpha` option in the kohya-ss trainer script. See
|
||||
https://github.com/darkstorm2150/sd-scripts/blob/main/docs/train_network_README-en.md#execute-learning
|
||||
device (`torch.device`, `optional`, defaults to `None`):
|
||||
The device to use for the layer's weights.
|
||||
dtype (`torch.dtype`, `optional`, defaults to `None`):
|
||||
The dtype to use for the layer's weights.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
in_features: int,
|
||||
out_features: int,
|
||||
rank: int = 4,
|
||||
network_alpha: Optional[float] = None,
|
||||
device: Optional[Union[paddle.CPUPlace, paddle.CUDAPlace, str]] = None,
|
||||
dtype: Optional[paddle.dtype] = None,
|
||||
):
|
||||
super().__init__()
|
||||
self.down = paddle.nn.Linear(
|
||||
in_features=in_features, out_features=rank, bias_attr=False
|
||||
)
|
||||
self.up = paddle.nn.Linear(
|
||||
in_features=rank, out_features=out_features, bias_attr=False
|
||||
)
|
||||
self.network_alpha = network_alpha
|
||||
self.rank = rank
|
||||
self.out_features = out_features
|
||||
self.in_features = in_features
|
||||
paddle.nn.init.normal_(self.down.weight, std=1 / rank)
|
||||
paddle.nn.init.zeros_(self.up.weight)
|
||||
|
||||
def forward(self, hidden_states: paddle.Tensor) -> paddle.Tensor:
|
||||
orig_dtype = hidden_states.dtype
|
||||
dtype = self.down.weight.dtype
|
||||
down_hidden_states = self.down(hidden_states.to(dtype))
|
||||
up_hidden_states = self.up(down_hidden_states)
|
||||
if self.network_alpha is not None:
|
||||
up_hidden_states *= self.network_alpha / self.rank
|
||||
return up_hidden_states.to(orig_dtype)
|
||||
|
||||
|
||||
|
||||
class LoRACompatibleLinear(paddle.nn.Linear):
|
||||
"""
|
||||
A Linear layer that can be used with LoRA.
|
||||
"""
|
||||
|
||||
def __init__(self, *args, lora_layer: Optional[LoRALinearLayer] = None, **kwargs):
|
||||
super().__init__(*args, **kwargs)
|
||||
self.lora_layer = lora_layer
|
||||
|
||||
def set_lora_layer(self, lora_layer: Optional[LoRALinearLayer]):
|
||||
self.lora_layer = lora_layer
|
||||
|
||||
def _fuse_lora(self, lora_scale: float = 1.0, safe_fusing: bool = False):
|
||||
if self.lora_layer is None:
|
||||
return
|
||||
dtype, device = self.weight.data.dtype, self.weight.data.place
|
||||
w_orig = self.weight.data.float()
|
||||
w_up = self.lora_layer.up.weight.data.float()
|
||||
w_down = self.lora_layer.down.weight.data.float()
|
||||
if self.lora_layer.network_alpha is not None:
|
||||
w_up = w_up * self.lora_layer.network_alpha / self.lora_layer.rank
|
||||
fused_weight = (
|
||||
w_orig + lora_scale * paddle.bmm(w_up[None, :], w_down[None, :])[0]
|
||||
)
|
||||
if safe_fusing and paddle.isnan(fused_weight).any().item():
|
||||
raise ValueError(
|
||||
f"This LoRA weight seems to be broken. Encountered NaN values when trying to fuse LoRA weights for {self}.LoRA weights will not be fused."
|
||||
)
|
||||
self.weight.data = fused_weight.to(device=device, dtype=dtype)
|
||||
self.lora_layer = None
|
||||
self.w_up = w_up.cpu()
|
||||
self.w_down = w_down.cpu()
|
||||
self._lora_scale = lora_scale
|
||||
|
||||
def _unfuse_lora(self):
|
||||
if not (
|
||||
getattr(self, "w_up", None) is not None
|
||||
and getattr(self, "w_down", None) is not None
|
||||
):
|
||||
return
|
||||
fused_weight = self.weight.data
|
||||
dtype, device = fused_weight.dtype, fused_weight.place
|
||||
w_up = self.w_up.to(device=device).float()
|
||||
w_down = self.w_down.to(device).float()
|
||||
unfused_weight = (
|
||||
fused_weight.float()
|
||||
- self._lora_scale * paddle.bmm(w_up[None, :], w_down[None, :])[0]
|
||||
)
|
||||
self.weight.data = unfused_weight.to(device=device, dtype=dtype)
|
||||
self.w_up = None
|
||||
self.w_down = None
|
||||
|
||||
def forward(
|
||||
self, hidden_states: paddle.Tensor, scale: float = 1.0
|
||||
) -> paddle.Tensor:
|
||||
if self.lora_layer is None:
|
||||
out = super().forward(hidden_states)
|
||||
return out
|
||||
else:
|
||||
out = super().forward(hidden_states) + scale * self.lora_layer(
|
||||
hidden_states
|
||||
)
|
||||
return out
|
||||
@ -0,0 +1,287 @@
|
||||
import paddle
|
||||
|
||||
def device2str(type=None, index=None, *, device=None):
|
||||
type = device if device else type
|
||||
if isinstance(type, int):
|
||||
type = f'gpu:{type}'
|
||||
elif isinstance(type, str):
|
||||
if 'cuda' in type:
|
||||
type = type.replace('cuda', 'gpu')
|
||||
if 'cpu' in type:
|
||||
type = 'cpu'
|
||||
elif index is not None:
|
||||
type = f'{type}:{index}'
|
||||
elif isinstance(type, paddle.CPUPlace) or (type is None):
|
||||
type = 'cpu'
|
||||
elif isinstance(type, paddle.CUDAPlace):
|
||||
type = f'gpu:{type.get_device_id()}'
|
||||
|
||||
return type
|
||||
|
||||
def _Tensor_max(self, *args, **kwargs):
|
||||
if "other" in kwargs:
|
||||
kwargs["y"] = kwargs.pop("other")
|
||||
ret = paddle.maximum(self, *args, **kwargs)
|
||||
elif len(args) == 1 and isinstance(args[0], paddle.Tensor):
|
||||
ret = paddle.maximum(self, *args, **kwargs)
|
||||
else:
|
||||
if "dim" in kwargs:
|
||||
kwargs["axis"] = kwargs.pop("dim")
|
||||
|
||||
if "axis" in kwargs or len(args) >= 1:
|
||||
ret = paddle.max(self, *args, **kwargs), paddle.argmax(self, *args, **kwargs)
|
||||
else:
|
||||
ret = paddle.max(self, *args, **kwargs)
|
||||
|
||||
return ret
|
||||
|
||||
setattr(paddle.Tensor, "_max", _Tensor_max)
|
||||
|
||||
|
||||
|
||||
"""
|
||||
def subsequent_mask(
|
||||
size: int,
|
||||
device: torch.device = torch.device("cpu"),
|
||||
) -> torch.Tensor:
|
||||
""\"Create mask for subsequent steps (size, size).
|
||||
|
||||
This mask is used only in decoder which works in an auto-regressive mode.
|
||||
This means the current step could only do attention with its left steps.
|
||||
|
||||
In encoder, fully attention is used when streaming is not necessary and
|
||||
the sequence is not long. In this case, no attention mask is needed.
|
||||
|
||||
When streaming is need, chunk-based attention is used in encoder. See
|
||||
subsequent_chunk_mask for the chunk-based attention mask.
|
||||
|
||||
Args:
|
||||
size (int): size of mask
|
||||
str device (str): "cpu" or "cuda" or torch.Tensor.device
|
||||
dtype (torch.device): result dtype
|
||||
|
||||
Returns:
|
||||
torch.Tensor: mask
|
||||
|
||||
Examples:
|
||||
>>> subsequent_mask(3)
|
||||
[[1, 0, 0],
|
||||
[1, 1, 0],
|
||||
[1, 1, 1]]
|
||||
""\"
|
||||
ret = torch.ones(size, size, device=device, dtype=torch.bool)
|
||||
return torch.tril(ret)
|
||||
"""
|
||||
|
||||
|
||||
def subsequent_mask(
|
||||
>>>>>> size: int, device: torch.device = device2str("cpu")
|
||||
) -> paddle.Tensor:
|
||||
"""Create mask for subsequent steps (size, size).
|
||||
|
||||
This mask is used only in decoder which works in an auto-regressive mode.
|
||||
This means the current step could only do attention with its left steps.
|
||||
|
||||
In encoder, fully attention is used when streaming isnot necessary and
|
||||
the sequence is not long. In this case, no attention mask is needed.
|
||||
|
||||
When streaming is need, chunk-based attention is used in encoder. See
|
||||
subsequent_chunk_mask for the chunk-based attention mask.
|
||||
|
||||
Args:
|
||||
size (int): size of mask
|
||||
str device (str): "cpu" or "cuda" or torch.Tensor.device
|
||||
dtype (torch.device): result dtype
|
||||
|
||||
Returns:
|
||||
torch.Tensor: mask
|
||||
|
||||
Examples:
|
||||
>>> subsequent_mask(3)
|
||||
[[1, 0, 0],
|
||||
[1, 1, 0],
|
||||
[1, 1, 1]]
|
||||
"""
|
||||
arange = paddle.arange(size, device=device)
|
||||
mask = arange.expand(size, size)
|
||||
arange = arange.unsqueeze(-1)
|
||||
mask = mask <= arange
|
||||
return mask
|
||||
|
||||
|
||||
def subsequent_chunk_mask_deprecated(
|
||||
size: int,
|
||||
chunk_size: int,
|
||||
num_left_chunks: int = -1,
|
||||
>>>>>> device: torch.device = device2str("cpu"),
|
||||
) -> paddle.Tensor:
|
||||
"""Create mask for subsequent steps (size, size) with chunk size,
|
||||
this is for streaming encoder
|
||||
|
||||
Args:
|
||||
size (int): size of mask
|
||||
chunk_size (int): size of chunk
|
||||
num_left_chunks (int): number of left chunks
|
||||
<0: use full chunk
|
||||
>=0: use num_left_chunks
|
||||
device (torch.device): "cpu" or "cuda" or torch.Tensor.device
|
||||
|
||||
Returns:
|
||||
torch.Tensor: mask
|
||||
|
||||
Examples:
|
||||
>>> subsequent_chunk_mask(4, 2)
|
||||
[[1, 1, 0, 0],
|
||||
[1, 1, 0, 0],
|
||||
[1, 1, 1, 1],
|
||||
[1, 1, 1, 1]]
|
||||
"""
|
||||
ret = paddle.zeros(size, size, device=device, dtype=paddle.bool)
|
||||
for i in range(size):
|
||||
if num_left_chunks < 0:
|
||||
start = 0
|
||||
else:
|
||||
start = max((i // chunk_size - num_left_chunks) * chunk_size, 0)
|
||||
ending = min((i // chunk_size + 1) * chunk_size, size)
|
||||
ret[i, start:ending] = True
|
||||
return ret
|
||||
|
||||
|
||||
def subsequent_chunk_mask(
|
||||
size: int,
|
||||
chunk_size: int,
|
||||
num_left_chunks: int = -1,
|
||||
>>>>>> device: torch.device = device2str("cpu"),
|
||||
) -> paddle.Tensor:
|
||||
"""Create mask for subsequent steps (size, size) with chunk size,
|
||||
this is for streaming encoder
|
||||
|
||||
Args:
|
||||
size (int): size of mask
|
||||
chunk_size (int): size of chunk
|
||||
num_left_chunks (int): number of left chunks
|
||||
<0: use full chunk
|
||||
>=0: use num_left_chunks
|
||||
device (torch.device): "cpu" or "cuda" or torch.Tensor.device
|
||||
|
||||
Returns:
|
||||
torch.Tensor: mask
|
||||
|
||||
Examples:
|
||||
>>> subsequent_chunk_mask(4, 2)
|
||||
[[1, 1, 0, 0],
|
||||
[1, 1, 0, 0],
|
||||
[1, 1, 1, 1],
|
||||
[1, 1, 1, 1]]
|
||||
"""
|
||||
pos_idx = paddle.arange(size, device=device)
|
||||
block_value = (
|
||||
paddle.div(pos_idx, chunk_size, rounding_mode="trunc") + 1
|
||||
) * chunk_size
|
||||
ret = pos_idx.unsqueeze(0) < block_value.unsqueeze(1)
|
||||
return ret
|
||||
|
||||
|
||||
def add_optional_chunk_mask(
|
||||
xs: paddle.Tensor,
|
||||
masks: paddle.Tensor,
|
||||
use_dynamic_chunk: bool,
|
||||
use_dynamic_left_chunk: bool,
|
||||
decoding_chunk_size: int,
|
||||
static_chunk_size: int,
|
||||
num_decoding_left_chunks: int,
|
||||
enable_full_context: bool = True,
|
||||
):
|
||||
"""Apply optional mask for encoder.
|
||||
|
||||
Args:
|
||||
xs (torch.Tensor): padded input, (B, L, D), L for max length
|
||||
mask (torch.Tensor): mask for xs, (B, 1, L)
|
||||
use_dynamic_chunk (bool): whether to use dynamic chunk or not
|
||||
use_dynamic_left_chunk (bool): whether to use dynamic left chunk for
|
||||
training.
|
||||
decoding_chunk_size (int): decoding chunk size for dynamic chunk, it's
|
||||
0: default for training, use random dynamic chunk.
|
||||
<0: for decoding, use full chunk.
|
||||
>0: for decoding, use fixed chunk size as set.
|
||||
static_chunk_size (int): chunk size for static chunk training/decoding
|
||||
if it's greater than 0, if use_dynamic_chunk is true,
|
||||
this parameter will be ignored
|
||||
num_decoding_left_chunks: number of left chunks, this is for decoding,
|
||||
the chunk size is decoding_chunk_size.
|
||||
>=0: use num_decoding_left_chunks
|
||||
<0: use all left chunks
|
||||
enable_full_context (bool):
|
||||
True: chunk size is either [1, 25] or full context(max_len)
|
||||
False: chunk size ~ U[1, 25]
|
||||
|
||||
Returns:
|
||||
torch.Tensor: chunk mask of the input xs.
|
||||
"""
|
||||
if use_dynamic_chunk:
|
||||
max_len = xs.size(1)
|
||||
if decoding_chunk_size < 0:
|
||||
chunk_size = max_len
|
||||
num_left_chunks = -1
|
||||
elif decoding_chunk_size > 0:
|
||||
chunk_size = decoding_chunk_size
|
||||
num_left_chunks = num_decoding_left_chunks
|
||||
else:
|
||||
chunk_size = paddle.randint(low=1, high=max_len, shape=(1,)).item()
|
||||
num_left_chunks = -1
|
||||
if chunk_size > max_len // 2 and enable_full_context:
|
||||
chunk_size = max_len
|
||||
else:
|
||||
chunk_size = chunk_size % 25 + 1
|
||||
if use_dynamic_left_chunk:
|
||||
max_left_chunks = (max_len - 1) // chunk_size
|
||||
num_left_chunks = paddle.randint(
|
||||
low=0, high=max_left_chunks, shape=(1,)
|
||||
).item()
|
||||
chunk_masks = subsequent_chunk_mask(
|
||||
xs.size(1), chunk_size, num_left_chunks, xs.place
|
||||
)
|
||||
chunk_masks = chunk_masks.unsqueeze(0)
|
||||
chunk_masks = masks & chunk_masks
|
||||
elif static_chunk_size > 0:
|
||||
num_left_chunks = num_decoding_left_chunks
|
||||
chunk_masks = subsequent_chunk_mask(
|
||||
xs.size(1), static_chunk_size, num_left_chunks, xs.place
|
||||
)
|
||||
chunk_masks = chunk_masks.unsqueeze(0)
|
||||
chunk_masks = masks & chunk_masks
|
||||
else:
|
||||
chunk_masks = masks
|
||||
assert chunk_masks.dtype == paddle.bool
|
||||
if (chunk_masks.sum(dim=-1) == 0).sum().item() != 0:
|
||||
print(
|
||||
"get chunk_masks all false at some timestep, force set to true, make sure they are masked in futuer computation!"
|
||||
)
|
||||
chunk_masks[chunk_masks.sum(dim=-1) == 0] = True
|
||||
return chunk_masks
|
||||
|
||||
|
||||
def make_pad_mask(lengths: paddle.Tensor, max_len: int = 0) -> paddle.Tensor:
|
||||
"""Make mask tensor containing indices of padded part.
|
||||
|
||||
See description of make_non_pad_mask.
|
||||
|
||||
Args:
|
||||
lengths (torch.Tensor): Batch of lengths (B,).
|
||||
Returns:
|
||||
torch.Tensor: Mask tensor containing indices of padded part.
|
||||
|
||||
Examples:
|
||||
>>> lengths = [5, 3, 2]
|
||||
>>> make_pad_mask(lengths)
|
||||
masks = [[0, 0, 0, 0 ,0],
|
||||
[0, 0, 0, 1, 1],
|
||||
[0, 0, 1, 1, 1]]
|
||||
"""
|
||||
batch_size = lengths.size(0)
|
||||
max_len = max_len if max_len > 0 else lengths._max().item()
|
||||
seq_range = paddle.arange(0, max_len, dtype=paddle.int64, device=lengths.place)
|
||||
seq_range_expand = seq_range.unsqueeze(0).expand(batch_size, max_len)
|
||||
seq_length_expand = lengths.unsqueeze(-1)
|
||||
mask = seq_range_expand >= seq_length_expand
|
||||
return mask
|
||||
@ -0,0 +1,445 @@
|
||||
import math
|
||||
from typing import Optional
|
||||
|
||||
import einops
|
||||
import paddle
|
||||
from conformer import ConformerBlock
|
||||
from matcha.models.components.transformer import BasicTransformerBlock
|
||||
ACTIVATION_FUNCTIONS = {
|
||||
"swish": paddle.nn.SiLU(),
|
||||
"silu": paddle.nn.SiLU(),
|
||||
"mish": paddle.nn.Mish(),
|
||||
"gelu": paddle.nn.GELU(),
|
||||
"relu": paddle.nn.ReLU(),
|
||||
}
|
||||
def get_activation(act_fn: str) -> paddle.nn.Layer:
|
||||
"""Helper function to get activation function from string.
|
||||
|
||||
Args:
|
||||
act_fn (str): Name of activation function.
|
||||
|
||||
Returns:
|
||||
nn.Module: Activation function.
|
||||
"""
|
||||
act_fn = act_fn.lower()
|
||||
if act_fn in ACTIVATION_FUNCTIONS:
|
||||
return ACTIVATION_FUNCTIONS[act_fn]
|
||||
else:
|
||||
raise ValueError(f"Unsupported activation function: {act_fn}")
|
||||
|
||||
class SinusoidalPosEmb(paddle.nn.Layer):
|
||||
def __init__(self, dim):
|
||||
super().__init__()
|
||||
self.dim = dim
|
||||
assert self.dim % 2 == 0, "SinusoidalPosEmb requires dim to be even"
|
||||
|
||||
def forward(self, x, scale=1000):
|
||||
if x.ndim < 1:
|
||||
x = x.unsqueeze(0)
|
||||
device = x.place
|
||||
half_dim = self.dim // 2
|
||||
emb = math.log(10000) / (half_dim - 1)
|
||||
emb = paddle.exp(x=paddle.arange(half_dim, device=device).float() * -emb)
|
||||
emb = scale * x.unsqueeze(1) * emb.unsqueeze(0)
|
||||
emb = paddle.cat((emb.sin(), emb.cos()), dim=-1)
|
||||
return emb
|
||||
|
||||
|
||||
class Block1D(paddle.nn.Layer):
|
||||
def __init__(self, dim, dim_out, groups=8):
|
||||
super().__init__()
|
||||
self.block = paddle.nn.Sequential(
|
||||
paddle.nn.Conv1d(dim, dim_out, 3, padding=1),
|
||||
paddle.nn.GroupNorm(num_groups=groups, num_channels=dim_out),
|
||||
paddle.nn.Mish(),
|
||||
)
|
||||
|
||||
def forward(self, x, mask):
|
||||
output = self.block(x * mask)
|
||||
return output * mask
|
||||
|
||||
|
||||
class ResnetBlock1D(paddle.nn.Layer):
|
||||
def __init__(self, dim, dim_out, time_emb_dim, groups=8):
|
||||
super().__init__()
|
||||
self.mlp = paddle.nn.Sequential(
|
||||
paddle.nn.Mish(),
|
||||
paddle.nn.Linear(in_features=time_emb_dim, out_features=dim_out),
|
||||
)
|
||||
self.block1 = Block1D(dim, dim_out, groups=groups)
|
||||
self.block2 = Block1D(dim_out, dim_out, groups=groups)
|
||||
self.res_conv = paddle.nn.Conv1d(dim, dim_out, 1)
|
||||
|
||||
def forward(self, x, mask, time_emb):
|
||||
h = self.block1(x, mask)
|
||||
h += self.mlp(time_emb).unsqueeze(-1)
|
||||
h = self.block2(h, mask)
|
||||
output = h + self.res_conv(x * mask)
|
||||
return output
|
||||
|
||||
|
||||
class Downsample1D(paddle.nn.Layer):
|
||||
def __init__(self, dim):
|
||||
super().__init__()
|
||||
self.conv = paddle.nn.Conv1d(dim, dim, 3, 2, 1)
|
||||
|
||||
def forward(self, x):
|
||||
return self.conv(x)
|
||||
|
||||
|
||||
class TimestepEmbedding(paddle.nn.Layer):
|
||||
def __init__(
|
||||
self,
|
||||
in_channels: int,
|
||||
time_embed_dim: int,
|
||||
act_fn: str = "silu",
|
||||
out_dim: int = None,
|
||||
post_act_fn: Optional[str] = None,
|
||||
cond_proj_dim=None,
|
||||
):
|
||||
super().__init__()
|
||||
self.linear_1 = paddle.nn.Linear(
|
||||
in_features=in_channels, out_features=time_embed_dim
|
||||
)
|
||||
if cond_proj_dim is not None:
|
||||
self.cond_proj = paddle.nn.Linear(
|
||||
in_features=cond_proj_dim, out_features=in_channels, bias_attr=False
|
||||
)
|
||||
else:
|
||||
self.cond_proj = None
|
||||
self.act = get_activation(act_fn)
|
||||
if out_dim is not None:
|
||||
time_embed_dim_out = out_dim
|
||||
else:
|
||||
time_embed_dim_out = time_embed_dim
|
||||
self.linear_2 = paddle.nn.Linear(
|
||||
in_features=time_embed_dim, out_features=time_embed_dim_out
|
||||
)
|
||||
if post_act_fn is None:
|
||||
self.post_act = None
|
||||
else:
|
||||
self.post_act = get_activation(post_act_fn)
|
||||
|
||||
def forward(self, sample, condition=None):
|
||||
if condition is not None:
|
||||
sample = sample + self.cond_proj(condition)
|
||||
sample = self.linear_1(sample)
|
||||
if self.act is not None:
|
||||
sample = self.act(sample)
|
||||
sample = self.linear_2(sample)
|
||||
if self.post_act is not None:
|
||||
sample = self.post_act(sample)
|
||||
return sample
|
||||
|
||||
|
||||
class Upsample1D(paddle.nn.Layer):
|
||||
"""A 1D upsampling layer with an optional convolution.
|
||||
|
||||
Parameters:
|
||||
channels (`int`):
|
||||
number of channels in the inputs and outputs.
|
||||
use_conv (`bool`, default `False`):
|
||||
option to use a convolution.
|
||||
use_conv_transpose (`bool`, default `False`):
|
||||
option to use a convolution transpose.
|
||||
out_channels (`int`, optional):
|
||||
number of output channels. Defaults to `channels`.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
channels,
|
||||
use_conv=False,
|
||||
use_conv_transpose=True,
|
||||
out_channels=None,
|
||||
name="conv",
|
||||
):
|
||||
super().__init__()
|
||||
self.channels = channels
|
||||
self.out_channels = out_channels or channels
|
||||
self.use_conv = use_conv
|
||||
self.use_conv_transpose = use_conv_transpose
|
||||
self.name = name
|
||||
self.conv = None
|
||||
if use_conv_transpose:
|
||||
self.conv = paddle.nn.Conv1DTranspose(
|
||||
in_channels=channels,
|
||||
out_channels=self.out_channels,
|
||||
kernel_size=4,
|
||||
stride=2,
|
||||
padding=1,
|
||||
)
|
||||
elif use_conv:
|
||||
self.conv = paddle.nn.Conv1d(self.channels, self.out_channels, 3, padding=1)
|
||||
|
||||
def forward(self, inputs):
|
||||
assert inputs.shape[1] == self.channels
|
||||
if self.use_conv_transpose:
|
||||
return self.conv(inputs)
|
||||
outputs = paddle.nn.functional.interpolate(
|
||||
x=inputs, scale_factor=2.0, mode="nearest"
|
||||
)
|
||||
if self.use_conv:
|
||||
outputs = self.conv(outputs)
|
||||
return outputs
|
||||
|
||||
|
||||
class ConformerWrapper(ConformerBlock):
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
dim,
|
||||
dim_head=64,
|
||||
heads=8,
|
||||
ff_mult=4,
|
||||
conv_expansion_factor=2,
|
||||
conv_kernel_size=31,
|
||||
attn_dropout=0,
|
||||
ff_dropout=0,
|
||||
conv_dropout=0,
|
||||
conv_causal=False,
|
||||
):
|
||||
super().__init__(
|
||||
dim=dim,
|
||||
dim_head=dim_head,
|
||||
heads=heads,
|
||||
ff_mult=ff_mult,
|
||||
conv_expansion_factor=conv_expansion_factor,
|
||||
conv_kernel_size=conv_kernel_size,
|
||||
attn_dropout=attn_dropout,
|
||||
ff_dropout=ff_dropout,
|
||||
conv_dropout=conv_dropout,
|
||||
conv_causal=conv_causal,
|
||||
)
|
||||
|
||||
def forward(
|
||||
self,
|
||||
hidden_states,
|
||||
attention_mask,
|
||||
encoder_hidden_states=None,
|
||||
encoder_attention_mask=None,
|
||||
timestep=None,
|
||||
):
|
||||
return super().forward(x=hidden_states, mask=attention_mask.bool())
|
||||
|
||||
|
||||
class Decoder(paddle.nn.Layer):
|
||||
def __init__(
|
||||
self,
|
||||
in_channels,
|
||||
out_channels,
|
||||
channels=(256, 256),
|
||||
dropout=0.05,
|
||||
attention_head_dim=64,
|
||||
n_blocks=1,
|
||||
num_mid_blocks=2,
|
||||
num_heads=4,
|
||||
act_fn="snake",
|
||||
down_block_type="transformer",
|
||||
mid_block_type="transformer",
|
||||
up_block_type="transformer",
|
||||
):
|
||||
super().__init__()
|
||||
channels = tuple(channels)
|
||||
self.in_channels = in_channels
|
||||
self.out_channels = out_channels
|
||||
self.time_embeddings = SinusoidalPosEmb(in_channels)
|
||||
time_embed_dim = channels[0] * 4
|
||||
self.time_mlp = TimestepEmbedding(
|
||||
in_channels=in_channels, time_embed_dim=time_embed_dim, act_fn="silu"
|
||||
)
|
||||
self.down_blocks = paddle.nn.LayerList(sublayers=[])
|
||||
self.mid_blocks = paddle.nn.LayerList(sublayers=[])
|
||||
self.up_blocks = paddle.nn.LayerList(sublayers=[])
|
||||
output_channel = in_channels
|
||||
for i in range(len(channels)):
|
||||
input_channel = output_channel
|
||||
output_channel = channels[i]
|
||||
is_last = i == len(channels) - 1
|
||||
resnet = ResnetBlock1D(
|
||||
dim=input_channel, dim_out=output_channel, time_emb_dim=time_embed_dim
|
||||
)
|
||||
transformer_blocks = paddle.nn.LayerList(
|
||||
sublayers=[
|
||||
self.get_block(
|
||||
down_block_type,
|
||||
output_channel,
|
||||
attention_head_dim,
|
||||
num_heads,
|
||||
dropout,
|
||||
act_fn,
|
||||
)
|
||||
for _ in range(n_blocks)
|
||||
]
|
||||
)
|
||||
downsample = (
|
||||
Downsample1D(output_channel)
|
||||
if not is_last
|
||||
else paddle.nn.Conv1d(output_channel, output_channel, 3, padding=1)
|
||||
)
|
||||
self.down_blocks.append(
|
||||
paddle.nn.LayerList(sublayers=[resnet, transformer_blocks, downsample])
|
||||
)
|
||||
for i in range(num_mid_blocks):
|
||||
input_channel = channels[-1]
|
||||
out_channels = channels[-1]
|
||||
resnet = ResnetBlock1D(
|
||||
dim=input_channel, dim_out=output_channel, time_emb_dim=time_embed_dim
|
||||
)
|
||||
transformer_blocks = paddle.nn.LayerList(
|
||||
sublayers=[
|
||||
self.get_block(
|
||||
mid_block_type,
|
||||
output_channel,
|
||||
attention_head_dim,
|
||||
num_heads,
|
||||
dropout,
|
||||
act_fn,
|
||||
)
|
||||
for _ in range(n_blocks)
|
||||
]
|
||||
)
|
||||
self.mid_blocks.append(
|
||||
paddle.nn.LayerList(sublayers=[resnet, transformer_blocks])
|
||||
)
|
||||
channels = channels[::-1] + (channels[0],)
|
||||
for i in range(len(channels) - 1):
|
||||
input_channel = channels[i]
|
||||
output_channel = channels[i + 1]
|
||||
is_last = i == len(channels) - 2
|
||||
resnet = ResnetBlock1D(
|
||||
dim=2 * input_channel,
|
||||
dim_out=output_channel,
|
||||
time_emb_dim=time_embed_dim,
|
||||
)
|
||||
transformer_blocks = paddle.nn.LayerList(
|
||||
sublayers=[
|
||||
self.get_block(
|
||||
up_block_type,
|
||||
output_channel,
|
||||
attention_head_dim,
|
||||
num_heads,
|
||||
dropout,
|
||||
act_fn,
|
||||
)
|
||||
for _ in range(n_blocks)
|
||||
]
|
||||
)
|
||||
upsample = (
|
||||
Upsample1D(output_channel, use_conv_transpose=True)
|
||||
if not is_last
|
||||
else paddle.nn.Conv1d(output_channel, output_channel, 3, padding=1)
|
||||
)
|
||||
self.up_blocks.append(
|
||||
paddle.nn.LayerList(sublayers=[resnet, transformer_blocks, upsample])
|
||||
)
|
||||
self.final_block = Block1D(channels[-1], channels[-1])
|
||||
self.final_proj = paddle.nn.Conv1d(channels[-1], self.out_channels, 1)
|
||||
self.initialize_weights()
|
||||
|
||||
@staticmethod
|
||||
def get_block(block_type, dim, attention_head_dim, num_heads, dropout, act_fn):
|
||||
if block_type == "conformer":
|
||||
block = ConformerWrapper(
|
||||
dim=dim,
|
||||
dim_head=attention_head_dim,
|
||||
heads=num_heads,
|
||||
ff_mult=1,
|
||||
conv_expansion_factor=2,
|
||||
ff_dropout=dropout,
|
||||
attn_dropout=dropout,
|
||||
conv_dropout=dropout,
|
||||
conv_kernel_size=31,
|
||||
)
|
||||
elif block_type == "transformer":
|
||||
block = BasicTransformerBlock(
|
||||
dim=dim,
|
||||
num_attention_heads=num_heads,
|
||||
attention_head_dim=attention_head_dim,
|
||||
dropout=dropout,
|
||||
activation_fn=act_fn,
|
||||
)
|
||||
else:
|
||||
raise ValueError(f"Unknown block type {block_type}")
|
||||
return block
|
||||
|
||||
def initialize_weights(self):
|
||||
for m in self.sublayers():
|
||||
if isinstance(m, paddle.nn.Conv1d):
|
||||
paddle.nn.init.kaiming_normal_(m.weight, nonlinearity="relu")
|
||||
if m.bias is not None:
|
||||
paddle.nn.init.constant_(m.bias, 0)
|
||||
elif isinstance(m, paddle.nn.GroupNorm):
|
||||
paddle.nn.init.constant_(m.weight, 1)
|
||||
paddle.nn.init.constant_(m.bias, 0)
|
||||
elif isinstance(m, paddle.nn.Linear):
|
||||
paddle.nn.init.kaiming_normal_(m.weight, nonlinearity="relu")
|
||||
if m.bias is not None:
|
||||
paddle.nn.init.constant_(m.bias, 0)
|
||||
|
||||
def forward(self, x, mask, mu, t, spks=None, cond=None):
|
||||
"""Forward pass of the UNet1DConditional model.
|
||||
|
||||
Args:
|
||||
x (torch.Tensor): shape (batch_size, in_channels, time)
|
||||
mask (_type_): shape (batch_size, 1, time)
|
||||
t (_type_): shape (batch_size)
|
||||
spks (_type_, optional): shape: (batch_size, condition_channels). Defaults to None.
|
||||
cond (_type_, optional): placeholder for future use. Defaults to None.
|
||||
|
||||
Raises:
|
||||
ValueError: _description_
|
||||
ValueError: _description_
|
||||
|
||||
Returns:
|
||||
_type_: _description_
|
||||
"""
|
||||
t = self.time_embeddings(t)
|
||||
t = self.time_mlp(t)
|
||||
x = einops.pack([x, mu], "b * t")[0]
|
||||
if spks is not None:
|
||||
spks = einops.repeat(spks, "b c -> b c t", t=x.shape[-1])
|
||||
x = einops.pack([x, spks], "b * t")[0]
|
||||
hiddens = []
|
||||
masks = [mask]
|
||||
for resnet, transformer_blocks, downsample in self.down_blocks:
|
||||
mask_down = masks[-1]
|
||||
x = resnet(x, mask_down, t)
|
||||
x = einops.rearrange(x, "b c t -> b t c")
|
||||
mask_down = einops.rearrange(mask_down, "b 1 t -> b t")
|
||||
for transformer_block in transformer_blocks:
|
||||
x = transformer_block(
|
||||
hidden_states=x, attention_mask=mask_down, timestep=t
|
||||
)
|
||||
x = einops.rearrange(x, "b t c -> b c t")
|
||||
mask_down = einops.rearrange(mask_down, "b t -> b 1 t")
|
||||
hiddens.append(x)
|
||||
x = downsample(x * mask_down)
|
||||
masks.append(mask_down[:, :, ::2])
|
||||
masks = masks[:-1]
|
||||
mask_mid = masks[-1]
|
||||
for resnet, transformer_blocks in self.mid_blocks:
|
||||
x = resnet(x, mask_mid, t)
|
||||
x = einops.rearrange(x, "b c t -> b t c")
|
||||
mask_mid = einops.rearrange(mask_mid, "b 1 t -> b t")
|
||||
for transformer_block in transformer_blocks:
|
||||
x = transformer_block(
|
||||
hidden_states=x, attention_mask=mask_mid, timestep=t
|
||||
)
|
||||
x = einops.rearrange(x, "b t c -> b c t")
|
||||
mask_mid = einops.rearrange(mask_mid, "b t -> b 1 t")
|
||||
for resnet, transformer_blocks, upsample in self.up_blocks:
|
||||
mask_up = masks.pop()
|
||||
x = resnet(einops.pack([x, hiddens.pop()], "b * t")[0], mask_up, t)
|
||||
x = einops.rearrange(x, "b c t -> b t c")
|
||||
mask_up = einops.rearrange(mask_up, "b 1 t -> b t")
|
||||
for transformer_block in transformer_blocks:
|
||||
x = transformer_block(
|
||||
hidden_states=x, attention_mask=mask_up, timestep=t
|
||||
)
|
||||
x = einops.rearrange(x, "b t c -> b c t")
|
||||
mask_up = einops.rearrange(mask_up, "b t -> b 1 t")
|
||||
x = upsample(x * mask_up)
|
||||
x = self.final_block(x, mask_up)
|
||||
output = self.final_proj(x * mask_up)
|
||||
return output * mask
|
||||
@ -0,0 +1,276 @@
|
||||
import numbers
|
||||
from typing import Dict, Optional, Tuple
|
||||
|
||||
import paddle
|
||||
from paddle import nn
|
||||
from .activations import get_activation
|
||||
from .embeddings import (CombinedTimestepLabelEmbeddings,
|
||||
PixArtAlphaCombinedTimestepSizeEmbeddings)
|
||||
def get_activation(act_fn):
|
||||
if act_fn == "silu":
|
||||
return nn.Silu()
|
||||
elif act_fn == "mish":
|
||||
return nn.Mish()
|
||||
elif act_fn == "relu":
|
||||
return nn.ReLU()
|
||||
elif act_fn == "gelu":
|
||||
return nn.GELU()
|
||||
else:
|
||||
raise ValueError(f"Unsupported activation function: {act_fn}")
|
||||
|
||||
class AdaLayerNorm(paddle.nn.Layer):
|
||||
"""
|
||||
Norm layer modified to incorporate timestep embeddings.
|
||||
|
||||
Parameters:
|
||||
embedding_dim (`int`): The size of each embedding vector.
|
||||
num_embeddings (`int`): The size of the embeddings dictionary.
|
||||
"""
|
||||
|
||||
def __init__(self, embedding_dim: int, num_embeddings: int):
|
||||
super().__init__()
|
||||
self.emb = paddle.nn.Embedding(num_embeddings, embedding_dim)
|
||||
self.silu = paddle.nn.SiLU()
|
||||
self.linear = paddle.nn.Linear(
|
||||
in_features=embedding_dim, out_features=embedding_dim * 2
|
||||
)
|
||||
self.norm = paddle.nn.LayerNorm(
|
||||
normalized_shape=embedding_dim, weight_attr=False, bias_attr=False
|
||||
)
|
||||
|
||||
def forward(self, x: paddle.Tensor, timestep: paddle.Tensor) -> paddle.Tensor:
|
||||
emb = self.linear(self.silu(self.emb(timestep)))
|
||||
scale, shift = paddle.chunk(emb, 2)
|
||||
x = self.norm(x) * (1 + scale) + shift
|
||||
return x
|
||||
|
||||
|
||||
class AdaLayerNormZero(paddle.nn.Layer):
|
||||
"""
|
||||
Norm layer adaptive layer norm zero (adaLN-Zero).
|
||||
|
||||
Parameters:
|
||||
embedding_dim (`int`): The size of each embedding vector.
|
||||
num_embeddings (`int`): The size of the embeddings dictionary.
|
||||
"""
|
||||
|
||||
def __init__(self, embedding_dim: int, num_embeddings: Optional[int] = None):
|
||||
super().__init__()
|
||||
if num_embeddings is not None:
|
||||
self.emb = CombinedTimestepLabelEmbeddings(num_embeddings, embedding_dim)
|
||||
else:
|
||||
self.emb = None
|
||||
self.silu = paddle.nn.SiLU()
|
||||
self.linear = paddle.nn.Linear(
|
||||
in_features=embedding_dim, out_features=6 * embedding_dim, bias_attr=True
|
||||
)
|
||||
self.norm = paddle.nn.LayerNorm(
|
||||
normalized_shape=embedding_dim,
|
||||
weight_attr=False,
|
||||
bias_attr=False,
|
||||
epsilon=1e-06,
|
||||
)
|
||||
|
||||
def forward(
|
||||
self,
|
||||
x: paddle.Tensor,
|
||||
timestep: Optional[paddle.Tensor] = None,
|
||||
class_labels: Optional[paddle.LongTensor] = None,
|
||||
hidden_dtype: Optional[paddle.dtype] = None,
|
||||
emb: Optional[paddle.Tensor] = None,
|
||||
) -> Tuple[
|
||||
paddle.Tensor, paddle.Tensor, paddle.Tensor, paddle.Tensor, paddle.Tensor
|
||||
]:
|
||||
if self.emb is not None:
|
||||
emb = self.emb(timestep, class_labels, hidden_dtype=hidden_dtype)
|
||||
emb = self.linear(self.silu(emb))
|
||||
shift_msa, scale_msa, gate_msa, shift_mlp, scale_mlp, gate_mlp = emb.chunk(
|
||||
6, dim=1
|
||||
)
|
||||
x = self.norm(x) * (1 + scale_msa[:, None]) + shift_msa[:, None]
|
||||
return x, gate_msa, shift_mlp, scale_mlp, gate_mlp
|
||||
|
||||
|
||||
class AdaLayerNormSingle(paddle.nn.Layer):
|
||||
"""
|
||||
Norm layer adaptive layer norm single (adaLN-single).
|
||||
|
||||
As proposed in PixArt-Alpha (see: https://arxiv.org/abs/2310.00426; Section 2.3).
|
||||
|
||||
Parameters:
|
||||
embedding_dim (`int`): The size of each embedding vector.
|
||||
use_additional_conditions (`bool`): To use additional conditions for normalization or not.
|
||||
"""
|
||||
|
||||
def __init__(self, embedding_dim: int, use_additional_conditions: bool = False):
|
||||
super().__init__()
|
||||
self.emb = PixArtAlphaCombinedTimestepSizeEmbeddings(
|
||||
embedding_dim,
|
||||
size_emb_dim=embedding_dim // 3,
|
||||
use_additional_conditions=use_additional_conditions,
|
||||
)
|
||||
self.silu = paddle.nn.SiLU()
|
||||
self.linear = paddle.nn.Linear(
|
||||
in_features=embedding_dim, out_features=6 * embedding_dim, bias_attr=True
|
||||
)
|
||||
|
||||
def forward(
|
||||
self,
|
||||
timestep: paddle.Tensor,
|
||||
added_cond_kwargs: Optional[Dict[str, paddle.Tensor]] = None,
|
||||
batch_size: Optional[int] = None,
|
||||
hidden_dtype: Optional[paddle.dtype] = None,
|
||||
) -> Tuple[
|
||||
paddle.Tensor, paddle.Tensor, paddle.Tensor, paddle.Tensor, paddle.Tensor
|
||||
]:
|
||||
embedded_timestep = self.emb(
|
||||
timestep,
|
||||
**added_cond_kwargs,
|
||||
batch_size=batch_size,
|
||||
hidden_dtype=hidden_dtype,
|
||||
)
|
||||
return self.linear(self.silu(embedded_timestep)), embedded_timestep
|
||||
|
||||
|
||||
class AdaGroupNorm(paddle.nn.Layer):
|
||||
"""
|
||||
GroupNorm layer modified to incorporate timestep embeddings.
|
||||
|
||||
Parameters:
|
||||
embedding_dim (`int`): The size of each embedding vector.
|
||||
num_embeddings (`int`): The size of the embeddings dictionary.
|
||||
num_groups (`int`): The number of groups to separate the channels into.
|
||||
act_fn (`str`, *optional*, defaults to `None`): The activation function to use.
|
||||
eps (`float`, *optional*, defaults to `1e-5`): The epsilon value to use for numerical stability.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
embedding_dim: int,
|
||||
out_dim: int,
|
||||
num_groups: int,
|
||||
act_fn: Optional[str] = None,
|
||||
eps: float = 1e-05,
|
||||
):
|
||||
super().__init__()
|
||||
self.num_groups = num_groups
|
||||
self.eps = eps
|
||||
if act_fn is None:
|
||||
self.act = None
|
||||
else:
|
||||
self.act = get_activation(act_fn)
|
||||
self.linear = paddle.nn.Linear(
|
||||
in_features=embedding_dim, out_features=out_dim * 2
|
||||
)
|
||||
|
||||
def forward(self, x: paddle.Tensor, emb: paddle.Tensor) -> paddle.Tensor:
|
||||
if self.act:
|
||||
emb = self.act(emb)
|
||||
emb = self.linear(emb)
|
||||
emb = emb[:, :, None, None]
|
||||
scale, shift = emb.chunk(2, dim=1)
|
||||
x = paddle.nn.functional.group_norm(
|
||||
x=x, num_groups=self.num_groups, epsilon=self.eps
|
||||
)
|
||||
x = x * (1 + scale) + shift
|
||||
return x
|
||||
|
||||
|
||||
class AdaLayerNormContinuous(paddle.nn.Layer):
|
||||
def __init__(
|
||||
self,
|
||||
embedding_dim: int,
|
||||
conditioning_embedding_dim: int,
|
||||
elementwise_affine=True,
|
||||
eps=1e-05,
|
||||
bias=True,
|
||||
norm_type="layer_norm",
|
||||
):
|
||||
super().__init__()
|
||||
self.silu = paddle.nn.SiLU()
|
||||
self.linear = paddle.nn.Linear(
|
||||
in_features=conditioning_embedding_dim,
|
||||
out_features=embedding_dim * 2,
|
||||
bias_attr=bias,
|
||||
)
|
||||
if norm_type == "layer_norm":
|
||||
self.norm = LayerNorm(embedding_dim, eps, elementwise_affine, bias)
|
||||
elif norm_type == "rms_norm":
|
||||
self.norm = RMSNorm(embedding_dim, eps, elementwise_affine)
|
||||
else:
|
||||
raise ValueError(f"unknown norm_type {norm_type}")
|
||||
|
||||
def forward(
|
||||
self, x: paddle.Tensor, conditioning_embedding: paddle.Tensor
|
||||
) -> paddle.Tensor:
|
||||
emb = self.linear(self.silu(conditioning_embedding).to(x.dtype))
|
||||
scale, shift = paddle.chunk(emb, 2, dim=1)
|
||||
x = self.norm(x) * (1 + scale)[:, None, :] + shift[:, None, :]
|
||||
return x
|
||||
|
||||
LayerNorm = paddle.nn.LayerNorm
|
||||
|
||||
|
||||
class LayerNorm(paddle.nn.Layer):
|
||||
def __init__(
|
||||
self,
|
||||
dim,
|
||||
eps: float = 1e-05,
|
||||
elementwise_affine: bool = True,
|
||||
bias: bool = True,
|
||||
):
|
||||
super().__init__()
|
||||
self.eps = eps
|
||||
if isinstance(dim, numbers.Integral):
|
||||
dim = (dim,)
|
||||
self.dim = paddle.Size(dim)
|
||||
if elementwise_affine:
|
||||
self.weight = paddle.nn.parameter.Parameter(paddle.ones(dim))
|
||||
self.bias = (
|
||||
paddle.nn.parameter.Parameter(paddle.zeros(dim)) if bias else None
|
||||
)
|
||||
else:
|
||||
self.weight = None
|
||||
self.bias = None
|
||||
|
||||
def forward(self, input):
|
||||
return paddle.nn.functional.layer_norm(
|
||||
input, self.dim, self.weight, self.bias, self.eps
|
||||
)
|
||||
|
||||
|
||||
class RMSNorm(paddle.nn.Layer):
|
||||
def __init__(self, dim, eps: float, elementwise_affine: bool = True):
|
||||
super().__init__()
|
||||
self.eps = eps
|
||||
if isinstance(dim, numbers.Integral):
|
||||
dim = (dim,)
|
||||
self.dim = paddle.Size(dim)
|
||||
if elementwise_affine:
|
||||
self.weight = paddle.nn.parameter.Parameter(paddle.ones(dim))
|
||||
else:
|
||||
self.weight = None
|
||||
|
||||
def forward(self, hidden_states):
|
||||
input_dtype = hidden_states.dtype
|
||||
variance = hidden_states.to(paddle.float32).pow(2).mean(-1, keepdim=True)
|
||||
hidden_states = hidden_states * paddle.rsqrt(variance + self.eps)
|
||||
if self.weight is not None:
|
||||
if self.weight.dtype in [paddle.float16, paddle.bfloat16]:
|
||||
hidden_states = hidden_states.to(self.weight.dtype)
|
||||
hidden_states = hidden_states * self.weight
|
||||
else:
|
||||
hidden_states = hidden_states.to(input_dtype)
|
||||
return hidden_states
|
||||
|
||||
|
||||
class GlobalResponseNorm(paddle.nn.Layer):
|
||||
def __init__(self, dim):
|
||||
super().__init__()
|
||||
self.gamma = paddle.nn.parameter.Parameter(paddle.zeros(1, 1, 1, dim))
|
||||
self.beta = paddle.nn.parameter.Parameter(paddle.zeros(1, 1, 1, dim))
|
||||
|
||||
def forward(self, x):
|
||||
gx = paddle.norm(x, p=2, dim=(1, 2), keepdim=True)
|
||||
nx = gx / (gx.mean(dim=-1, keepdim=True) + 1e-06)
|
||||
return self.gamma * (x * nx) + self.beta + x
|
||||
@ -0,0 +1,99 @@
|
||||
import paddle
|
||||
|
||||
"""ConvolutionModule definition."""
|
||||
from typing import Tuple
|
||||
|
||||
|
||||
class ConvolutionModule(paddle.nn.Layer):
|
||||
"""ConvolutionModule in Conformer model."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
channels: int,
|
||||
kernel_size: int = 15,
|
||||
activation: paddle.nn.Layer = paddle.nn.ReLU(),
|
||||
norm: str = "batch_norm",
|
||||
causal: bool = False,
|
||||
bias: bool = True,
|
||||
):
|
||||
"""Construct an ConvolutionModule object.
|
||||
Args:
|
||||
channels (int): The number of channels of conv layers.
|
||||
kernel_size (int): Kernel size of conv layers.
|
||||
causal (int): Whether use causal convolution or not
|
||||
"""
|
||||
super().__init__()
|
||||
self.pointwise_conv1 = paddle.nn.Conv1d(
|
||||
channels, 2 * channels, kernel_size=1, stride=1, padding=0, bias=bias
|
||||
)
|
||||
if causal:
|
||||
padding = 0
|
||||
self.lorder = kernel_size - 1
|
||||
else:
|
||||
assert (kernel_size - 1) % 2 == 0
|
||||
padding = (kernel_size - 1) // 2
|
||||
self.lorder = 0
|
||||
self.depthwise_conv = paddle.nn.Conv1d(
|
||||
channels,
|
||||
channels,
|
||||
kernel_size,
|
||||
stride=1,
|
||||
padding=padding,
|
||||
groups=channels,
|
||||
bias=bias,
|
||||
)
|
||||
assert norm in ["batch_norm", "layer_norm"]
|
||||
if norm == "batch_norm":
|
||||
self.use_layer_norm = False
|
||||
self.norm = paddle.nn.BatchNorm1D(num_features=channels)
|
||||
else:
|
||||
self.use_layer_norm = True
|
||||
self.norm = paddle.nn.LayerNorm(normalized_shape=channels)
|
||||
self.pointwise_conv2 = paddle.nn.Conv1d(
|
||||
channels, channels, kernel_size=1, stride=1, padding=0, bias=bias
|
||||
)
|
||||
self.activation = activation
|
||||
|
||||
def forward(
|
||||
self,
|
||||
x: paddle.Tensor,
|
||||
mask_pad: paddle.Tensor = paddle.ones((0, 0, 0), dtype=paddle.bool),
|
||||
cache: paddle.Tensor = paddle.zeros((0, 0, 0)),
|
||||
) -> Tuple[paddle.Tensor, paddle.Tensor]:
|
||||
"""Compute convolution module.
|
||||
Args:
|
||||
x (torch.Tensor): Input tensor (#batch, time, channels).
|
||||
mask_pad (torch.Tensor): used for batch padding (#batch, 1, time),
|
||||
(0, 0, 0) means fake mask.
|
||||
cache (torch.Tensor): left context cache, it is only
|
||||
used in causal convolution (#batch, channels, cache_t),
|
||||
(0, 0, 0) meas fake cache.
|
||||
Returns:
|
||||
torch.Tensor: Output tensor (#batch, time, channels).
|
||||
"""
|
||||
x = x.transpose(1, 2)
|
||||
if mask_pad.size(2) > 0:
|
||||
x.masked_fill_(~mask_pad, 0.0)
|
||||
if self.lorder > 0:
|
||||
if cache.size(2) == 0:
|
||||
x = paddle.compat.pad(x, (self.lorder, 0), "constant", 0.0)
|
||||
else:
|
||||
assert cache.size(0) == x.size(0)
|
||||
assert cache.size(1) == x.size(1)
|
||||
x = paddle.cat((cache, x), dim=2)
|
||||
assert x.size(2) > self.lorder
|
||||
new_cache = x[:, :, -self.lorder :]
|
||||
else:
|
||||
new_cache = paddle.zeros((0, 0, 0), dtype=x.dtype, device=x.place)
|
||||
x = self.pointwise_conv1(x)
|
||||
x = paddle.nn.functional.glu(x=x, axis=1)
|
||||
x = self.depthwise_conv(x)
|
||||
if self.use_layer_norm:
|
||||
x = x.transpose(1, 2)
|
||||
x = self.activation(self.norm(x))
|
||||
if self.use_layer_norm:
|
||||
x = x.transpose(1, 2)
|
||||
x = self.pointwise_conv2(x)
|
||||
if mask_pad.size(2) > 0:
|
||||
x.masked_fill_(~mask_pad, 0.0)
|
||||
return x.transpose(1, 2), new_cache
|
||||
@ -0,0 +1,275 @@
|
||||
import paddle
|
||||
|
||||
"""Positonal Encoding Module."""
|
||||
import math
|
||||
from typing import Tuple, Union
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
||||
class PositionalEncoding(paddle.nn.Layer):
|
||||
"""Positional encoding.
|
||||
|
||||
:param int d_model: embedding dim
|
||||
:param float dropout_rate: dropout rate
|
||||
:param int max_len: maximum input length
|
||||
|
||||
PE(pos, 2i) = sin(pos/(10000^(2i/dmodel)))
|
||||
PE(pos, 2i+1) = cos(pos/(10000^(2i/dmodel)))
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
d_model: int,
|
||||
dropout_rate: float,
|
||||
max_len: int = 5000,
|
||||
reverse: bool = False,
|
||||
):
|
||||
"""Construct an PositionalEncoding object."""
|
||||
super().__init__()
|
||||
self.d_model = d_model
|
||||
self.xscale = math.sqrt(self.d_model)
|
||||
self.dropout = paddle.nn.Dropout(p=dropout_rate)
|
||||
self.max_len = max_len
|
||||
self.pe = paddle.zeros(self.max_len, self.d_model)
|
||||
position = paddle.arange(0, self.max_len, dtype=paddle.float32).unsqueeze(1)
|
||||
div_term = paddle.exp(
|
||||
x=paddle.arange(0, self.d_model, 2, dtype=paddle.float32)
|
||||
* -(math.log(10000.0) / self.d_model)
|
||||
)
|
||||
self.pe[:, 0::2] = paddle.sin(position * div_term)
|
||||
self.pe[:, 1::2] = paddle.cos(position * div_term)
|
||||
self.pe = self.pe.unsqueeze(0)
|
||||
|
||||
def forward(
|
||||
self, x: paddle.Tensor, offset: Union[int, paddle.Tensor] = 0
|
||||
) -> Tuple[paddle.Tensor, paddle.Tensor]:
|
||||
"""Add positional encoding.
|
||||
|
||||
Args:
|
||||
x (torch.Tensor): Input. Its shape is (batch, time, ...)
|
||||
offset (int, torch.tensor): position offset
|
||||
|
||||
Returns:
|
||||
torch.Tensor: Encoded tensor. Its shape is (batch, time, ...)
|
||||
torch.Tensor: for compatibility to RelPositionalEncoding
|
||||
"""
|
||||
self.pe = self.pe.to(x.place)
|
||||
pos_emb = self.position_encoding(offset, x.size(1), False)
|
||||
x = x * self.xscale + pos_emb
|
||||
return self.dropout(x), self.dropout(pos_emb)
|
||||
|
||||
def position_encoding(
|
||||
self, offset: Union[int, paddle.Tensor], size: int, apply_dropout: bool = True
|
||||
) -> paddle.Tensor:
|
||||
"""For getting encoding in a streaming fashion
|
||||
|
||||
Attention!!!!!
|
||||
we apply dropout only once at the whole utterance level in a none
|
||||
streaming way, but will call this function several times with
|
||||
increasing input size in a streaming scenario, so the dropout will
|
||||
be applied several times.
|
||||
|
||||
Args:
|
||||
offset (int or torch.tensor): start offset
|
||||
size (int): required size of position encoding
|
||||
|
||||
Returns:
|
||||
torch.Tensor: Corresponding encoding
|
||||
"""
|
||||
if isinstance(offset, int):
|
||||
assert offset + size <= self.max_len
|
||||
pos_emb = self.pe[:, offset : offset + size]
|
||||
elif isinstance(offset, paddle.Tensor) and offset.dim() == 0:
|
||||
assert offset + size <= self.max_len
|
||||
pos_emb = self.pe[:, offset : offset + size]
|
||||
else:
|
||||
assert paddle.compat.max(offset) + size <= self.max_len
|
||||
index = offset.unsqueeze(1) + paddle.arange(0, size).to(offset.place)
|
||||
flag = index > 0
|
||||
index = index * flag
|
||||
pos_emb = paddle.nn.functional.embedding(index, self.pe[0])
|
||||
if apply_dropout:
|
||||
pos_emb = self.dropout(pos_emb)
|
||||
return pos_emb
|
||||
|
||||
|
||||
class RelPositionalEncoding(PositionalEncoding):
|
||||
"""Relative positional encoding module.
|
||||
See : Appendix B in https://arxiv.org/abs/1901.02860
|
||||
Args:
|
||||
d_model (int): Embedding dimension.
|
||||
dropout_rate (float): Dropout rate.
|
||||
max_len (int): Maximum input length.
|
||||
"""
|
||||
|
||||
def __init__(self, d_model: int, dropout_rate: float, max_len: int = 5000):
|
||||
"""Initialize class."""
|
||||
super().__init__(d_model, dropout_rate, max_len, reverse=True)
|
||||
|
||||
def forward(
|
||||
self, x: paddle.Tensor, offset: Union[int, paddle.Tensor] = 0
|
||||
) -> Tuple[paddle.Tensor, paddle.Tensor]:
|
||||
"""Compute positional encoding.
|
||||
Args:
|
||||
x (torch.Tensor): Input tensor (batch, time, `*`).
|
||||
Returns:
|
||||
torch.Tensor: Encoded tensor (batch, time, `*`).
|
||||
torch.Tensor: Positional embedding tensor (1, time, `*`).
|
||||
"""
|
||||
self.pe = self.pe.to(x.place)
|
||||
x = x * self.xscale
|
||||
pos_emb = self.position_encoding(offset, x.size(1), False)
|
||||
return self.dropout(x), self.dropout(pos_emb)
|
||||
|
||||
|
||||
class WhisperPositionalEncoding(PositionalEncoding):
|
||||
"""Sinusoids position encoding used in openai-whisper.encoder"""
|
||||
|
||||
def __init__(self, d_model: int, dropout_rate: float, max_len: int = 1500):
|
||||
super().__init__(d_model, dropout_rate, max_len)
|
||||
self.xscale = 1.0
|
||||
log_timescale_increment = np.log(10000) / (d_model // 2 - 1)
|
||||
inv_timescales = paddle.exp(
|
||||
x=-log_timescale_increment * paddle.arange(d_model // 2)
|
||||
)
|
||||
scaled_time = (
|
||||
paddle.arange(max_len)[:, np.newaxis] * inv_timescales[np.newaxis, :]
|
||||
)
|
||||
pe = paddle.cat([paddle.sin(scaled_time), paddle.cos(scaled_time)], dim=1)
|
||||
delattr(self, "pe")
|
||||
self.register_buffer(name="pe", tensor=pe.unsqueeze(0))
|
||||
|
||||
|
||||
class LearnablePositionalEncoding(PositionalEncoding):
|
||||
"""Learnable position encoding used in openai-whisper.decoder"""
|
||||
|
||||
def __init__(self, d_model: int, dropout_rate: float, max_len: int = 448):
|
||||
super().__init__(d_model, dropout_rate, max_len)
|
||||
self.pe = paddle.nn.parameter.Parameter(paddle.empty(1, max_len, d_model))
|
||||
self.xscale = 1.0
|
||||
|
||||
|
||||
class NoPositionalEncoding(paddle.nn.Layer):
|
||||
"""No position encoding"""
|
||||
|
||||
def __init__(self, d_model: int, dropout_rate: float):
|
||||
super().__init__()
|
||||
self.d_model = d_model
|
||||
self.dropout = paddle.nn.Dropout(p=dropout_rate)
|
||||
|
||||
def forward(
|
||||
self, x: paddle.Tensor, offset: Union[int, paddle.Tensor] = 0
|
||||
) -> Tuple[paddle.Tensor, paddle.Tensor]:
|
||||
"""Just return zero vector for interface compatibility"""
|
||||
pos_emb = paddle.zeros(1, x.size(1), self.d_model).to(x.place)
|
||||
return self.dropout(x), pos_emb
|
||||
|
||||
def position_encoding(
|
||||
self, offset: Union[int, paddle.Tensor], size: int
|
||||
) -> paddle.Tensor:
|
||||
return paddle.zeros(1, size, self.d_model)
|
||||
|
||||
|
||||
class EspnetRelPositionalEncoding(paddle.nn.Layer):
|
||||
"""Relative positional encoding module (new implementation).
|
||||
|
||||
Details can be found in https://github.com/espnet/espnet/pull/2816.
|
||||
|
||||
See : Appendix B in https://arxiv.org/abs/1901.02860
|
||||
|
||||
Args:
|
||||
d_model (int): Embedding dimension.
|
||||
dropout_rate (float): Dropout rate.
|
||||
max_len (int): Maximum input length.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self, d_model: int, dropout_rate: float, max_len: int = 5000):
|
||||
"""Construct an PositionalEncoding object."""
|
||||
super(EspnetRelPositionalEncoding, self).__init__()
|
||||
self.d_model = d_model
|
||||
self.xscale = math.sqrt(self.d_model)
|
||||
self.dropout = paddle.nn.Dropout(p=dropout_rate)
|
||||
self.pe = None
|
||||
self.extend_pe(paddle.tensor(0.0).expand(1, max_len))
|
||||
|
||||
def extend_pe(self, x: paddle.Tensor):
|
||||
"""Reset the positional encodings."""
|
||||
if self.pe is not None:
|
||||
if self.pe.size(1) >= x.size(1) * 2 - 1:
|
||||
if self.pe.dtype != x.dtype or self.pe.place != x.place:
|
||||
self.pe = self.pe.to(dtype=x.dtype, device=x.place)
|
||||
return
|
||||
pe_positive = paddle.zeros(x.size(1), self.d_model)
|
||||
pe_negative = paddle.zeros(x.size(1), self.d_model)
|
||||
position = paddle.arange(0, x.size(1), dtype=paddle.float32).unsqueeze(1)
|
||||
div_term = paddle.exp(
|
||||
x=paddle.arange(0, self.d_model, 2, dtype=paddle.float32)
|
||||
* -(math.log(10000.0) / self.d_model)
|
||||
)
|
||||
pe_positive[:, 0::2] = paddle.sin(position * div_term)
|
||||
pe_positive[:, 1::2] = paddle.cos(position * div_term)
|
||||
pe_negative[:, 0::2] = paddle.sin(-1 * position * div_term)
|
||||
pe_negative[:, 1::2] = paddle.cos(-1 * position * div_term)
|
||||
pe_positive = paddle.flip(x=pe_positive, axis=[0]).unsqueeze(0)
|
||||
pe_negative = pe_negative[1:].unsqueeze(0)
|
||||
pe = paddle.cat([pe_positive, pe_negative], dim=1)
|
||||
self.pe = pe.to(device=x.place, dtype=x.dtype)
|
||||
|
||||
def forward(
|
||||
self, x: paddle.Tensor, offset: Union[int, paddle.Tensor] = 0
|
||||
) -> Tuple[paddle.Tensor, paddle.Tensor]:
|
||||
"""Add positional encoding.
|
||||
|
||||
Args:
|
||||
x (torch.Tensor): Input tensor (batch, time, `*`).
|
||||
|
||||
Returns:
|
||||
torch.Tensor: Encoded tensor (batch, time, `*`).
|
||||
|
||||
"""
|
||||
self.extend_pe(x)
|
||||
x = x * self.xscale
|
||||
pos_emb = self.position_encoding(size=x.size(1), offset=offset)
|
||||
return self.dropout(x), self.dropout(pos_emb)
|
||||
|
||||
def position_encoding(
|
||||
self, offset: Union[int, paddle.Tensor], size: int
|
||||
) -> paddle.Tensor:
|
||||
"""For getting encoding in a streaming fashion
|
||||
|
||||
Attention!!!!!
|
||||
we apply dropout only once at the whole utterance level in a none
|
||||
streaming way, but will call this function several times with
|
||||
increasing input size in a streaming scenario, so the dropout will
|
||||
be applied several times.
|
||||
|
||||
Args:
|
||||
offset (int or torch.tensor): start offset
|
||||
size (int): required size of position encoding
|
||||
|
||||
Returns:
|
||||
torch.Tensor: Corresponding encoding
|
||||
"""
|
||||
if isinstance(offset, int):
|
||||
pos_emb = self.pe[
|
||||
:,
|
||||
self.pe.size(1) // 2
|
||||
- size
|
||||
- offset
|
||||
+ 1 : self.pe.size(1) // 2
|
||||
+ size
|
||||
+ offset,
|
||||
]
|
||||
elif isinstance(offset, paddle.Tensor):
|
||||
pos_emb = self.pe[
|
||||
:,
|
||||
self.pe.size(1) // 2
|
||||
- size
|
||||
- offset
|
||||
+ 1 : self.pe.size(1) // 2
|
||||
+ size
|
||||
+ offset,
|
||||
]
|
||||
return pos_emb
|
||||
@ -0,0 +1,343 @@
|
||||
import paddle
|
||||
|
||||
"""Encoder definition."""
|
||||
from typing import Tuple
|
||||
import paddle.nn.functional as F
|
||||
from paddlespeech.t2s.modules.transformer.convolution import ConvolutionModule
|
||||
from paddlespeech.t2s.modules.transformer.encoder_layer import ConformerEncoderLayer
|
||||
from paddlespeech.t2s.modules.transformer.positionwise_feed_forward import PositionwiseFeedForward
|
||||
from paddlespeech.t2s.models.CosyVoice.class_utils import (COSYVOICE_ACTIVATION_CLASSES,
|
||||
COSYVOICE_ATTENTION_CLASSES,
|
||||
COSYVOICE_EMB_CLASSES,
|
||||
COSYVOICE_SUBSAMPLE_CLASSES)
|
||||
from paddlespeech.t2s.modules.transformer.mask import add_optional_chunk_mask, make_pad_mask
|
||||
|
||||
|
||||
class Upsample1D(paddle.nn.Layer):
|
||||
"""A 1D upsampling layer with an optional convolution.
|
||||
|
||||
Parameters:
|
||||
channels (`int`):
|
||||
number of channels in the inputs and outputs.
|
||||
use_conv (`bool`, default `False`):
|
||||
option to use a convolution.
|
||||
use_conv_transpose (`bool`, default `False`):
|
||||
option to use a convolution transpose.
|
||||
out_channels (`int`, optional):
|
||||
number of output channels. Defaults to `channels`.
|
||||
"""
|
||||
|
||||
def __init__(self, channels: int, out_channels: int, stride: int = 2):
|
||||
super().__init__()
|
||||
self.channels = channels
|
||||
self.out_channels = out_channels
|
||||
self.stride = stride
|
||||
self.conv = paddle.nn.Conv1D(
|
||||
self.channels, self.out_channels, stride * 2 + 1, stride=1, padding=0
|
||||
)
|
||||
|
||||
def forward(
|
||||
self, inputs: paddle.Tensor, input_lengths: paddle.Tensor
|
||||
) -> Tuple[paddle.Tensor, paddle.Tensor]:
|
||||
inputs = inputs.unsqueeze(2)
|
||||
outputs = paddle.nn.functional.interpolate(
|
||||
x=inputs, scale_factor=[1, float(self.stride)],mode="nearest"
|
||||
)
|
||||
outputs = outputs.squeeze(2)
|
||||
outputs = F.pad(outputs, [self.stride * 2, 0], value=0.0)
|
||||
outputs = self.conv(outputs)
|
||||
return outputs, input_lengths * self.stride
|
||||
|
||||
|
||||
class PreLookaheadLayer(paddle.nn.Layer):
|
||||
def __init__(self, channels: int, pre_lookahead_len: int = 1):
|
||||
super().__init__()
|
||||
self.channels = channels
|
||||
self.pre_lookahead_len = pre_lookahead_len
|
||||
self.conv1 = paddle.nn.Conv1D(
|
||||
channels, channels, kernel_size=pre_lookahead_len + 1, stride=1, padding=0
|
||||
)
|
||||
self.conv2 = paddle.nn.Conv1D(
|
||||
channels, channels, kernel_size=3, stride=1, padding=0
|
||||
)
|
||||
|
||||
def forward(
|
||||
self, inputs: paddle.Tensor, context: paddle.Tensor = paddle.zeros([0, 0, 0])
|
||||
) -> paddle.Tensor:
|
||||
"""
|
||||
inputs: (batch_size, seq_len, channels)
|
||||
"""
|
||||
outputs = paddle.transpose(inputs, perm=[0, 2, 1]).contiguous()
|
||||
context = paddle.transpose(context, perm=[0, 2, 1]).contiguous()
|
||||
if context.shape[2] == 0:
|
||||
outputs = F.pad(
|
||||
outputs, [0, self.pre_lookahead_len], mode="constant", value=0.0
|
||||
)
|
||||
else:
|
||||
assert (
|
||||
self.training is False
|
||||
), "you have passed context, make sure that you are running inference mode"
|
||||
assert context.shape[2] == self.pre_lookahead_len
|
||||
outputs = F.pad(
|
||||
paddle.cat([outputs, context], dim=2),
|
||||
[0, self.pre_lookahead_len - context.shape[2]],
|
||||
mode="constant",
|
||||
value=0.0,
|
||||
)
|
||||
outputs = paddle.nn.functional.leaky_relu(x=self.conv1(outputs))
|
||||
outputs = F.pad(
|
||||
outputs, [self.conv2._kernel_size[0] - 1, 0], mode="constant", value=0.0
|
||||
)
|
||||
outputs = self.conv2(outputs)
|
||||
outputs = paddle.transpose(outputs, perm=[0, 2, 1]).contiguous()
|
||||
|
||||
outputs = outputs + inputs
|
||||
return outputs
|
||||
|
||||
|
||||
class UpsampleConformerEncoder(paddle.nn.Layer):
|
||||
def __init__(
|
||||
self,
|
||||
input_size: int,
|
||||
output_size: int = 256,
|
||||
attention_heads: int = 4,
|
||||
linear_units: int = 2048,
|
||||
num_blocks: int = 6,
|
||||
dropout_rate: float = 0.1,
|
||||
positional_dropout_rate: float = 0.1,
|
||||
attention_dropout_rate: float = 0.0,
|
||||
input_layer: str = "conv2d",
|
||||
pos_enc_layer_type: str = "rel_pos",
|
||||
normalize_before: bool = True,
|
||||
static_chunk_size: int = 0,
|
||||
use_dynamic_chunk: bool = False,
|
||||
global_cmvn: paddle.nn.Layer = None,
|
||||
use_dynamic_left_chunk: bool = False,
|
||||
positionwise_conv_kernel_size: int = 1,
|
||||
macaron_style: bool = True,
|
||||
selfattention_layer_type: str = "rel_selfattn",
|
||||
activation_type: str = "swish",
|
||||
use_cnn_module: bool = True,
|
||||
cnn_module_kernel: int = 15,
|
||||
causal: bool = False,
|
||||
cnn_module_norm: str = "batch_norm",
|
||||
key_bias: bool = True,
|
||||
gradient_checkpointing: bool = False,
|
||||
):
|
||||
"""
|
||||
Args:
|
||||
input_size (int): input dim
|
||||
output_size (int): dimension of attention
|
||||
attention_heads (int): the number of heads of multi head attention
|
||||
linear_units (int): the hidden units number of position-wise feed
|
||||
forward
|
||||
num_blocks (int): the number of decoder blocks
|
||||
dropout_rate (float): dropout rate
|
||||
attention_dropout_rate (float): dropout rate in attention
|
||||
positional_dropout_rate (float): dropout rate after adding
|
||||
positional encoding
|
||||
input_layer (str): input layer type.
|
||||
optional [linear, conv2d, conv2d6, conv2d8]
|
||||
pos_enc_layer_type (str): Encoder positional encoding layer type.
|
||||
opitonal [abs_pos, scaled_abs_pos, rel_pos, no_pos]
|
||||
normalize_before (bool):
|
||||
True: use layer_norm before each sub-block of a layer.
|
||||
False: use layer_norm after each sub-block of a layer.
|
||||
static_chunk_size (int): chunk size for static chunk training and
|
||||
decoding
|
||||
use_dynamic_chunk (bool): whether use dynamic chunk size for
|
||||
training or not, You can only use fixed chunk(chunk_size > 0)
|
||||
or dyanmic chunk size(use_dynamic_chunk = True)
|
||||
global_cmvn (Optional[torch.nn.Module]): Optional GlobalCMVN module
|
||||
use_dynamic_left_chunk (bool): whether use dynamic left chunk in
|
||||
dynamic chunk training
|
||||
key_bias: whether use bias in attention.linear_k, False for whisper models.
|
||||
gradient_checkpointing: rerunning a forward-pass segment for each
|
||||
checkpointed segment during backward.
|
||||
"""
|
||||
super().__init__()
|
||||
self._output_size = output_size
|
||||
self.global_cmvn = global_cmvn
|
||||
self.embed = COSYVOICE_SUBSAMPLE_CLASSES[input_layer](
|
||||
input_size,
|
||||
output_size,
|
||||
dropout_rate,
|
||||
COSYVOICE_EMB_CLASSES[pos_enc_layer_type](
|
||||
output_size, positional_dropout_rate
|
||||
),
|
||||
)
|
||||
self.normalize_before = normalize_before
|
||||
self.after_norm = paddle.nn.LayerNorm(
|
||||
normalized_shape=output_size, epsilon=1e-05
|
||||
)
|
||||
self.static_chunk_size = static_chunk_size
|
||||
self.use_dynamic_chunk = use_dynamic_chunk
|
||||
self.use_dynamic_left_chunk = use_dynamic_left_chunk
|
||||
self.gradient_checkpointing = gradient_checkpointing
|
||||
activation = COSYVOICE_ACTIVATION_CLASSES[activation_type]()
|
||||
encoder_selfattn_layer_args = (
|
||||
attention_heads,
|
||||
output_size,
|
||||
attention_dropout_rate,
|
||||
False,
|
||||
)
|
||||
positionwise_layer_args = (output_size, linear_units, dropout_rate, activation)
|
||||
convolution_layer_args = (
|
||||
output_size,
|
||||
cnn_module_kernel,
|
||||
activation,
|
||||
cnn_module_norm,
|
||||
causal,
|
||||
)
|
||||
self.pre_lookahead_layer = PreLookaheadLayer(channels=512, pre_lookahead_len=3)
|
||||
self.encoders = paddle.nn.LayerList(
|
||||
sublayers=[
|
||||
ConformerEncoderLayer(
|
||||
output_size,
|
||||
COSYVOICE_ATTENTION_CLASSES[selfattention_layer_type](
|
||||
*encoder_selfattn_layer_args
|
||||
),
|
||||
PositionwiseFeedForward(*positionwise_layer_args),
|
||||
PositionwiseFeedForward(*positionwise_layer_args)
|
||||
if macaron_style
|
||||
else None,
|
||||
ConvolutionModule(*convolution_layer_args)
|
||||
if use_cnn_module
|
||||
else None,
|
||||
dropout_rate,
|
||||
normalize_before,
|
||||
)
|
||||
for _ in range(num_blocks)
|
||||
]
|
||||
)
|
||||
self.up_layer = Upsample1D(channels=512, out_channels=512, stride=2)
|
||||
self.up_embed = COSYVOICE_SUBSAMPLE_CLASSES[input_layer](
|
||||
input_size,
|
||||
output_size,
|
||||
dropout_rate,
|
||||
COSYVOICE_EMB_CLASSES[pos_enc_layer_type](
|
||||
output_size, positional_dropout_rate
|
||||
),
|
||||
)
|
||||
self.up_encoders = paddle.nn.LayerList(
|
||||
sublayers=[
|
||||
ConformerEncoderLayer(
|
||||
output_size,
|
||||
COSYVOICE_ATTENTION_CLASSES[selfattention_layer_type](
|
||||
*encoder_selfattn_layer_args
|
||||
),
|
||||
PositionwiseFeedForward(*positionwise_layer_args),
|
||||
PositionwiseFeedForward(*positionwise_layer_args)
|
||||
if macaron_style
|
||||
else None,
|
||||
ConvolutionModule(*convolution_layer_args)
|
||||
if use_cnn_module
|
||||
else None,
|
||||
dropout_rate,
|
||||
normalize_before,
|
||||
)
|
||||
for _ in range(4)
|
||||
]
|
||||
)
|
||||
|
||||
def output_size(self) -> int:
|
||||
return self._output_size
|
||||
|
||||
def forward(
|
||||
self,
|
||||
xs: paddle.Tensor,
|
||||
xs_lens: paddle.Tensor,
|
||||
context: paddle.Tensor = paddle.zeros([0, 0, 0]),
|
||||
decoding_chunk_size: int = 0,
|
||||
num_decoding_left_chunks: int = -1,
|
||||
streaming: bool = False,
|
||||
) -> Tuple[paddle.Tensor, paddle.Tensor]:
|
||||
"""Embed positions in tensor.
|
||||
|
||||
Args:
|
||||
xs: padded input tensor (B, T, D)
|
||||
xs_lens: input length (B)
|
||||
decoding_chunk_size: decoding chunk size for dynamic chunk
|
||||
0: default for training, use random dynamic chunk.
|
||||
<0: for decoding, use full chunk.
|
||||
>0: for decoding, use fixed chunk size as set.
|
||||
num_decoding_left_chunks: number of left chunks, this is for decoding,
|
||||
the chunk size is decoding_chunk_size.
|
||||
>=0: use num_decoding_left_chunks
|
||||
<0: use all left chunks
|
||||
Returns:
|
||||
encoder output tensor xs, and subsampled masks
|
||||
xs: padded output tensor (B, T' ~= T/subsample_rate, D)
|
||||
masks: torch.Tensor batch padding mask after subsample
|
||||
(B, 1, T' ~= T/subsample_rate)
|
||||
NOTE(xcsong):
|
||||
We pass the `__call__` method of the modules instead of `forward` to the
|
||||
checkpointing API because `__call__` attaches all the hooks of the module.
|
||||
https://discuss.pytorch.org/t/any-different-between-model-input-and-model-forward-input/3690/2
|
||||
"""
|
||||
T = xs.shape[1]
|
||||
masks = ~make_pad_mask(xs_lens, T).unsqueeze(1)
|
||||
if self.global_cmvn is not None:
|
||||
xs = self.global_cmvn(xs)
|
||||
xs, pos_emb, masks = self.embed(xs, masks)
|
||||
if context.shape[1] != 0:
|
||||
assert (
|
||||
self.training is False
|
||||
), "you have passed context, make sure that you are running inference mode"
|
||||
context_masks = paddle.ones(1, 1, context.shape[1]).to(masks)
|
||||
context, _, _ = self.embed(context, context_masks, offset=xs.shape[1])
|
||||
mask_pad = masks
|
||||
chunk_masks = add_optional_chunk_mask(
|
||||
xs,
|
||||
masks,
|
||||
False,
|
||||
False,
|
||||
0,
|
||||
self.static_chunk_size if streaming is True else 0,
|
||||
-1,
|
||||
)
|
||||
xs = self.pre_lookahead_layer(xs, context=context)
|
||||
xs = self.forward_layers(xs, chunk_masks, pos_emb, mask_pad)
|
||||
#
|
||||
xs = paddle.transpose(xs, perm=[0, 2, 1]).contiguous()
|
||||
xs, xs_lens = self.up_layer(xs, xs_lens)
|
||||
xs = paddle.transpose(xs, perm=[0, 2, 1]).contiguous()
|
||||
T = xs.shape[1]
|
||||
masks = ~make_pad_mask(xs_lens, T).unsqueeze(1)
|
||||
xs, pos_emb, masks = self.up_embed(xs, masks)
|
||||
mask_pad = masks
|
||||
chunk_masks = add_optional_chunk_mask(
|
||||
xs,
|
||||
masks,
|
||||
False,
|
||||
False,
|
||||
0,
|
||||
self.static_chunk_size * self.up_layer.stride if streaming is True else 0,
|
||||
-1,
|
||||
)
|
||||
xs = self.forward_up_layers(xs, chunk_masks, pos_emb, mask_pad)
|
||||
if self.normalize_before:
|
||||
xs = self.after_norm(xs)
|
||||
return xs, masks
|
||||
|
||||
def forward_layers(
|
||||
self,
|
||||
xs: paddle.Tensor,
|
||||
chunk_masks: paddle.Tensor,
|
||||
pos_emb: paddle.Tensor,
|
||||
mask_pad: paddle.Tensor,
|
||||
) -> paddle.Tensor:
|
||||
for layer in self.encoders:
|
||||
xs, chunk_masks, _, _ = layer(xs, chunk_masks, pos_emb, mask_pad)
|
||||
return xs
|
||||
|
||||
def forward_up_layers(
|
||||
self,
|
||||
xs: paddle.Tensor,
|
||||
chunk_masks: paddle.Tensor,
|
||||
pos_emb: paddle.Tensor,
|
||||
mask_pad: paddle.Tensor,
|
||||
) -> paddle.Tensor:
|
||||
for layer in self.up_encoders:
|
||||
xs, chunk_masks, _, _ = layer(xs, chunk_masks, pos_emb, mask_pad)
|
||||
return xs
|
||||
Loading…
Reference in new issue