|
|
from typing import Sequence |
|
|
from dataclasses import dataclass |
|
|
import math |
|
|
import torch |
|
|
import torch.nn as nn |
|
|
import torch.nn.functional as F |
|
|
from torch.nn import Parameter |
|
|
|
|
|
from utils.torch_utilities import create_mask_from_length |
|
|
from utils.diffsinger_utilities import denorm_f0, f0_to_coarse |
|
|
|
|
|
|
|
|
def make_positions(tensor, padding_idx): |
|
|
"""Replace non-padding symbols with their position numbers. |
|
|
Position numbers begin at padding_idx+1. Padding symbols are ignored. |
|
|
""" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
mask = tensor.ne(padding_idx).int() |
|
|
return (torch.cumsum(mask, dim=1).type_as(mask) * |
|
|
mask).long() + padding_idx |
|
|
|
|
|
|
|
|
def softmax(x, dim): |
|
|
return F.softmax(x, dim=dim, dtype=torch.float32) |
|
|
|
|
|
|
|
|
def LayerNorm( |
|
|
normalized_shape, eps=1e-5, elementwise_affine=True, export=False |
|
|
): |
|
|
if not export and torch.cuda.is_available(): |
|
|
try: |
|
|
from apex.normalization import FusedLayerNorm |
|
|
return FusedLayerNorm(normalized_shape, eps, elementwise_affine) |
|
|
except ImportError: |
|
|
pass |
|
|
return torch.nn.LayerNorm(normalized_shape, eps, elementwise_affine) |
|
|
|
|
|
|
|
|
def Linear(in_features, out_features, bias=True): |
|
|
m = nn.Linear(in_features, out_features, bias) |
|
|
nn.init.xavier_uniform_(m.weight) |
|
|
if bias: |
|
|
nn.init.constant_(m.bias, 0.) |
|
|
return m |
|
|
|
|
|
|
|
|
def Embedding(num_embeddings, embedding_dim, padding_idx=None): |
|
|
m = nn.Embedding(num_embeddings, embedding_dim, padding_idx=padding_idx) |
|
|
nn.init.normal_(m.weight, mean=0, std=embedding_dim**-0.5) |
|
|
if padding_idx is not None: |
|
|
nn.init.constant_(m.weight[padding_idx], 0) |
|
|
return m |
|
|
|
|
|
|
|
|
class BatchNorm1dTBC(nn.Module): |
|
|
def __init__(self, c): |
|
|
super(BatchNorm1dTBC, self).__init__() |
|
|
self.bn = nn.BatchNorm1d(c) |
|
|
|
|
|
def forward(self, x): |
|
|
""" |
|
|
|
|
|
:param x: [T, B, C] |
|
|
:return: [T, B, C] |
|
|
""" |
|
|
x = x.permute(1, 2, 0) |
|
|
x = self.bn(x) |
|
|
x = x.permute(2, 0, 1) |
|
|
return x |
|
|
|
|
|
|
|
|
class PositionalEncoding(nn.Module): |
|
|
"""Positional encoding. |
|
|
Args: |
|
|
d_model (int): Embedding dimension. |
|
|
dropout_rate (float): Dropout rate. |
|
|
max_len (int): Maximum input length. |
|
|
reverse (bool): Whether to reverse the input position. |
|
|
""" |
|
|
def __init__(self, d_model, dropout_rate, max_len=5000, reverse=False): |
|
|
"""Construct an PositionalEncoding object.""" |
|
|
super(PositionalEncoding, self).__init__() |
|
|
self.d_model = d_model |
|
|
self.reverse = reverse |
|
|
self.xscale = math.sqrt(self.d_model) |
|
|
self.dropout = torch.nn.Dropout(p=dropout_rate) |
|
|
self.pe = None |
|
|
self.extend_pe(torch.tensor(0.0).expand(1, max_len)) |
|
|
|
|
|
def extend_pe(self, x): |
|
|
"""Reset the positional encodings.""" |
|
|
if self.pe is not None: |
|
|
if self.pe.size(1) >= x.size(1): |
|
|
if self.pe.dtype != x.dtype or self.pe.device != x.device: |
|
|
self.pe = self.pe.to(dtype=x.dtype, device=x.device) |
|
|
return |
|
|
pe = torch.zeros(x.size(1), self.d_model) |
|
|
if self.reverse: |
|
|
position = torch.arange( |
|
|
x.size(1) - 1, -1, -1.0, dtype=torch.float32 |
|
|
).unsqueeze(1) |
|
|
else: |
|
|
position = torch.arange(0, x.size(1), |
|
|
dtype=torch.float32).unsqueeze(1) |
|
|
div_term = torch.exp( |
|
|
torch.arange(0, self.d_model, 2, dtype=torch.float32) * |
|
|
-(math.log(10000.0) / self.d_model) |
|
|
) |
|
|
pe[:, 0::2] = torch.sin(position * div_term) |
|
|
pe[:, 1::2] = torch.cos(position * div_term) |
|
|
pe = pe.unsqueeze(0) |
|
|
self.pe = pe.to(device=x.device, dtype=x.dtype) |
|
|
|
|
|
def forward(self, x: torch.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 + self.pe[:, :x.size(1)] |
|
|
return self.dropout(x) |
|
|
|
|
|
|
|
|
class SinusoidalPositionalEmbedding(nn.Module): |
|
|
"""This module produces sinusoidal positional embeddings of any length. |
|
|
|
|
|
Padding symbols are ignored. |
|
|
""" |
|
|
def __init__(self, d_model, padding_idx, init_size=2048): |
|
|
super().__init__() |
|
|
self.d_model = d_model |
|
|
self.padding_idx = padding_idx |
|
|
self.weights = SinusoidalPositionalEmbedding.get_embedding( |
|
|
init_size, |
|
|
d_model, |
|
|
padding_idx, |
|
|
) |
|
|
self.register_buffer('_float_tensor', torch.FloatTensor(1)) |
|
|
|
|
|
@staticmethod |
|
|
def get_embedding(num_embeddings, d_model, padding_idx=None): |
|
|
"""Build sinusoidal embeddings. |
|
|
|
|
|
This matches the implementation in tensor2tensor, but differs slightly |
|
|
from the description in Section 3.5 of "Attention Is All You Need". |
|
|
""" |
|
|
half_dim = d_model // 2 |
|
|
emb = math.log(10000) / (half_dim - 1) |
|
|
emb = torch.exp(torch.arange(half_dim, dtype=torch.float) * -emb) |
|
|
emb = torch.arange(num_embeddings, |
|
|
dtype=torch.float).unsqueeze(1) * emb.unsqueeze(0) |
|
|
emb = torch.cat([torch.sin(emb), torch.cos(emb)], |
|
|
dim=1).view(num_embeddings, -1) |
|
|
if d_model % 2 == 1: |
|
|
|
|
|
emb = torch.cat([emb, torch.zeros(num_embeddings, 1)], dim=1) |
|
|
if padding_idx is not None: |
|
|
emb[padding_idx, :] = 0 |
|
|
return emb |
|
|
|
|
|
def forward( |
|
|
self, |
|
|
x, |
|
|
lengths, |
|
|
incremental_state=None, |
|
|
timestep=None, |
|
|
positions=None, |
|
|
**kwargs |
|
|
): |
|
|
"""Input is expected to be of size [bsz x seqlen].""" |
|
|
bsz, seq_len = x.shape[:2] |
|
|
max_pos = self.padding_idx + 1 + seq_len |
|
|
if self.weights is None or max_pos > self.weights.size(0): |
|
|
|
|
|
self.weights = SinusoidalPositionalEmbedding.get_embedding( |
|
|
max_pos, |
|
|
self.d_model, |
|
|
self.padding_idx, |
|
|
) |
|
|
self.weights = self.weights.to(self._float_tensor) |
|
|
|
|
|
if incremental_state is not None: |
|
|
|
|
|
pos = timestep.view(-1)[0] + 1 if timestep is not None else seq_len |
|
|
return self.weights[self.padding_idx + pos, :].expand(bsz, 1, -1) |
|
|
|
|
|
positions = create_mask_from_length( |
|
|
lengths, max_length=x.shape[1] |
|
|
) * (torch.arange(x.shape[1]) + 1).unsqueeze(0).expand(x.shape[0], -1) |
|
|
positions = positions.to(self.weights.device) |
|
|
pos_emb = self.weights.index_select(0, positions.view(-1)).view( |
|
|
bsz, seq_len, -1 |
|
|
).detach() |
|
|
return x + pos_emb |
|
|
|
|
|
def max_positions(self): |
|
|
"""Maximum number of supported positions.""" |
|
|
return int(1e5) |
|
|
|
|
|
|
|
|
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, dropout_rate, max_len=5000): |
|
|
"""Initialize class.""" |
|
|
super().__init__(d_model, dropout_rate, max_len, reverse=True) |
|
|
|
|
|
def forward(self, x, lengths): |
|
|
"""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.extend_pe(x) |
|
|
x = x * self.xscale |
|
|
pos_emb = self.pe[:, :x.size(1)] |
|
|
return self.dropout(x) + self.dropout(pos_emb) |
|
|
|
|
|
|
|
|
class MultiheadAttention(nn.Module): |
|
|
def __init__( |
|
|
self, |
|
|
embed_dim, |
|
|
num_heads, |
|
|
kdim=None, |
|
|
vdim=None, |
|
|
dropout=0., |
|
|
bias=True, |
|
|
add_bias_kv=False, |
|
|
add_zero_attn=False, |
|
|
self_attention=False, |
|
|
encoder_decoder_attention=False |
|
|
): |
|
|
super().__init__() |
|
|
self.embed_dim = embed_dim |
|
|
self.kdim = kdim if kdim is not None else embed_dim |
|
|
self.vdim = vdim if vdim is not None else embed_dim |
|
|
self.qkv_same_dim = self.kdim == embed_dim and self.vdim == embed_dim |
|
|
|
|
|
self.num_heads = num_heads |
|
|
self.dropout = dropout |
|
|
self.head_dim = embed_dim // num_heads |
|
|
assert self.head_dim * num_heads == self.embed_dim, "embed_dim must be divisible by num_heads" |
|
|
self.scaling = self.head_dim**-0.5 |
|
|
|
|
|
self.self_attention = self_attention |
|
|
self.encoder_decoder_attention = encoder_decoder_attention |
|
|
|
|
|
assert not self.self_attention or self.qkv_same_dim, 'Self-attention requires query, key and ' \ |
|
|
'value to be of the same size' |
|
|
|
|
|
if self.qkv_same_dim: |
|
|
self.in_proj_weight = Parameter( |
|
|
torch.Tensor(3 * embed_dim, embed_dim) |
|
|
) |
|
|
else: |
|
|
self.k_proj_weight = Parameter(torch.Tensor(embed_dim, self.kdim)) |
|
|
self.v_proj_weight = Parameter(torch.Tensor(embed_dim, self.vdim)) |
|
|
self.q_proj_weight = Parameter(torch.Tensor(embed_dim, embed_dim)) |
|
|
|
|
|
if bias: |
|
|
self.in_proj_bias = Parameter(torch.Tensor(3 * embed_dim)) |
|
|
else: |
|
|
self.register_parameter('in_proj_bias', None) |
|
|
|
|
|
self.out_proj = nn.Linear(embed_dim, embed_dim, bias=bias) |
|
|
|
|
|
if add_bias_kv: |
|
|
self.bias_k = Parameter(torch.Tensor(1, 1, embed_dim)) |
|
|
self.bias_v = Parameter(torch.Tensor(1, 1, embed_dim)) |
|
|
else: |
|
|
self.bias_k = self.bias_v = None |
|
|
|
|
|
self.add_zero_attn = add_zero_attn |
|
|
|
|
|
self.reset_parameters() |
|
|
|
|
|
self.enable_torch_version = False |
|
|
if hasattr(F, "multi_head_attention_forward"): |
|
|
self.enable_torch_version = True |
|
|
else: |
|
|
self.enable_torch_version = False |
|
|
self.last_attn_probs = None |
|
|
|
|
|
def reset_parameters(self): |
|
|
if self.qkv_same_dim: |
|
|
nn.init.xavier_uniform_(self.in_proj_weight) |
|
|
else: |
|
|
nn.init.xavier_uniform_(self.k_proj_weight) |
|
|
nn.init.xavier_uniform_(self.v_proj_weight) |
|
|
nn.init.xavier_uniform_(self.q_proj_weight) |
|
|
|
|
|
nn.init.xavier_uniform_(self.out_proj.weight) |
|
|
if self.in_proj_bias is not None: |
|
|
nn.init.constant_(self.in_proj_bias, 0.) |
|
|
nn.init.constant_(self.out_proj.bias, 0.) |
|
|
if self.bias_k is not None: |
|
|
nn.init.xavier_normal_(self.bias_k) |
|
|
if self.bias_v is not None: |
|
|
nn.init.xavier_normal_(self.bias_v) |
|
|
|
|
|
def forward( |
|
|
self, |
|
|
query, |
|
|
key, |
|
|
value, |
|
|
key_padding_mask=None, |
|
|
incremental_state=None, |
|
|
need_weights=True, |
|
|
static_kv=False, |
|
|
attn_mask=None, |
|
|
before_softmax=False, |
|
|
need_head_weights=False, |
|
|
enc_dec_attn_constraint_mask=None, |
|
|
reset_attn_weight=None |
|
|
): |
|
|
"""Input shape: Time x Batch x Channel |
|
|
|
|
|
Args: |
|
|
key_padding_mask (ByteTensor, optional): mask to exclude |
|
|
keys that are pads, of shape `(batch, src_len)`, where |
|
|
padding elements are indicated by 1s. |
|
|
need_weights (bool, optional): return the attention weights, |
|
|
averaged over heads (default: False). |
|
|
attn_mask (ByteTensor, optional): typically used to |
|
|
implement causal attention, where the mask prevents the |
|
|
attention from looking forward in time (default: None). |
|
|
before_softmax (bool, optional): return the raw attention |
|
|
weights and values before the attention softmax. |
|
|
need_head_weights (bool, optional): return the attention |
|
|
weights for each head. Implies *need_weights*. Default: |
|
|
return the average attention weights over all heads. |
|
|
""" |
|
|
if need_head_weights: |
|
|
need_weights = True |
|
|
|
|
|
tgt_len, bsz, embed_dim = query.size() |
|
|
assert embed_dim == self.embed_dim |
|
|
assert list(query.size()) == [tgt_len, bsz, embed_dim] |
|
|
|
|
|
if self.enable_torch_version and incremental_state is None and not static_kv and reset_attn_weight is None: |
|
|
if self.qkv_same_dim: |
|
|
return F.multi_head_attention_forward( |
|
|
query, key, value, self.embed_dim, self.num_heads, |
|
|
self.in_proj_weight, self.in_proj_bias, self.bias_k, |
|
|
self.bias_v, self.add_zero_attn, self.dropout, |
|
|
self.out_proj.weight, self.out_proj.bias, self.training, |
|
|
key_padding_mask, need_weights, attn_mask |
|
|
) |
|
|
else: |
|
|
return F.multi_head_attention_forward( |
|
|
query, |
|
|
key, |
|
|
value, |
|
|
self.embed_dim, |
|
|
self.num_heads, |
|
|
torch.empty([0]), |
|
|
self.in_proj_bias, |
|
|
self.bias_k, |
|
|
self.bias_v, |
|
|
self.add_zero_attn, |
|
|
self.dropout, |
|
|
self.out_proj.weight, |
|
|
self.out_proj.bias, |
|
|
self.training, |
|
|
key_padding_mask, |
|
|
need_weights, |
|
|
attn_mask, |
|
|
use_separate_proj_weight=True, |
|
|
q_proj_weight=self.q_proj_weight, |
|
|
k_proj_weight=self.k_proj_weight, |
|
|
v_proj_weight=self.v_proj_weight |
|
|
) |
|
|
|
|
|
if incremental_state is not None: |
|
|
print('Not implemented error.') |
|
|
exit() |
|
|
else: |
|
|
saved_state = None |
|
|
|
|
|
if self.self_attention: |
|
|
|
|
|
q, k, v = self.in_proj_qkv(query) |
|
|
elif self.encoder_decoder_attention: |
|
|
|
|
|
q = self.in_proj_q(query) |
|
|
if key is None: |
|
|
assert value is None |
|
|
k = v = None |
|
|
else: |
|
|
k = self.in_proj_k(key) |
|
|
v = self.in_proj_v(key) |
|
|
|
|
|
else: |
|
|
q = self.in_proj_q(query) |
|
|
k = self.in_proj_k(key) |
|
|
v = self.in_proj_v(value) |
|
|
q *= self.scaling |
|
|
|
|
|
if self.bias_k is not None: |
|
|
assert self.bias_v is not None |
|
|
k = torch.cat([k, self.bias_k.repeat(1, bsz, 1)]) |
|
|
v = torch.cat([v, self.bias_v.repeat(1, bsz, 1)]) |
|
|
if attn_mask is not None: |
|
|
attn_mask = torch.cat( |
|
|
[attn_mask, |
|
|
attn_mask.new_zeros(attn_mask.size(0), 1)], |
|
|
dim=1 |
|
|
) |
|
|
if key_padding_mask is not None: |
|
|
key_padding_mask = torch.cat( |
|
|
[ |
|
|
key_padding_mask, |
|
|
key_padding_mask.new_zeros( |
|
|
key_padding_mask.size(0), 1 |
|
|
) |
|
|
], |
|
|
dim=1 |
|
|
) |
|
|
|
|
|
q = q.contiguous().view(tgt_len, bsz * self.num_heads, |
|
|
self.head_dim).transpose(0, 1) |
|
|
if k is not None: |
|
|
k = k.contiguous().view(-1, bsz * self.num_heads, |
|
|
self.head_dim).transpose(0, 1) |
|
|
if v is not None: |
|
|
v = v.contiguous().view(-1, bsz * self.num_heads, |
|
|
self.head_dim).transpose(0, 1) |
|
|
|
|
|
if saved_state is not None: |
|
|
print('Not implemented error.') |
|
|
exit() |
|
|
|
|
|
src_len = k.size(1) |
|
|
|
|
|
|
|
|
|
|
|
if key_padding_mask is not None and key_padding_mask.shape == torch.Size( |
|
|
[] |
|
|
): |
|
|
key_padding_mask = None |
|
|
|
|
|
if key_padding_mask is not None: |
|
|
assert key_padding_mask.size(0) == bsz |
|
|
assert key_padding_mask.size(1) == src_len |
|
|
|
|
|
if self.add_zero_attn: |
|
|
src_len += 1 |
|
|
k = torch.cat( |
|
|
[k, k.new_zeros((k.size(0), 1) + k.size()[2:])], dim=1 |
|
|
) |
|
|
v = torch.cat( |
|
|
[v, v.new_zeros((v.size(0), 1) + v.size()[2:])], dim=1 |
|
|
) |
|
|
if attn_mask is not None: |
|
|
attn_mask = torch.cat( |
|
|
[attn_mask, |
|
|
attn_mask.new_zeros(attn_mask.size(0), 1)], |
|
|
dim=1 |
|
|
) |
|
|
if key_padding_mask is not None: |
|
|
key_padding_mask = torch.cat( |
|
|
[ |
|
|
key_padding_mask, |
|
|
torch.zeros(key_padding_mask.size(0), |
|
|
1).type_as(key_padding_mask) |
|
|
], |
|
|
dim=1 |
|
|
) |
|
|
|
|
|
attn_weights = torch.bmm(q, k.transpose(1, 2)) |
|
|
attn_weights = self.apply_sparse_mask( |
|
|
attn_weights, tgt_len, src_len, bsz |
|
|
) |
|
|
|
|
|
assert list(attn_weights.size()) == [ |
|
|
bsz * self.num_heads, tgt_len, src_len |
|
|
] |
|
|
|
|
|
if attn_mask is not None: |
|
|
if len(attn_mask.shape) == 2: |
|
|
attn_mask = attn_mask.unsqueeze(0) |
|
|
elif len(attn_mask.shape) == 3: |
|
|
attn_mask = attn_mask[:, None].repeat( |
|
|
[1, self.num_heads, 1, 1] |
|
|
).reshape(bsz * self.num_heads, tgt_len, src_len) |
|
|
attn_weights = attn_weights + attn_mask |
|
|
|
|
|
if enc_dec_attn_constraint_mask is not None: |
|
|
attn_weights = attn_weights.view( |
|
|
bsz, self.num_heads, tgt_len, src_len |
|
|
) |
|
|
attn_weights = attn_weights.masked_fill( |
|
|
enc_dec_attn_constraint_mask.unsqueeze(2).bool(), |
|
|
-1e9, |
|
|
) |
|
|
attn_weights = attn_weights.view( |
|
|
bsz * self.num_heads, tgt_len, src_len |
|
|
) |
|
|
|
|
|
if key_padding_mask is not None: |
|
|
|
|
|
attn_weights = attn_weights.view( |
|
|
bsz, self.num_heads, tgt_len, src_len |
|
|
) |
|
|
attn_weights = attn_weights.masked_fill( |
|
|
key_padding_mask.unsqueeze(1).unsqueeze(2), |
|
|
-1e9, |
|
|
) |
|
|
attn_weights = attn_weights.view( |
|
|
bsz * self.num_heads, tgt_len, src_len |
|
|
) |
|
|
|
|
|
attn_logits = attn_weights.view(bsz, self.num_heads, tgt_len, src_len) |
|
|
|
|
|
if before_softmax: |
|
|
return attn_weights, v |
|
|
|
|
|
attn_weights_float = softmax(attn_weights, dim=-1) |
|
|
attn_weights = attn_weights_float.type_as(attn_weights) |
|
|
attn_probs = F.dropout( |
|
|
attn_weights_float.type_as(attn_weights), |
|
|
p=self.dropout, |
|
|
training=self.training |
|
|
) |
|
|
|
|
|
if reset_attn_weight is not None: |
|
|
if reset_attn_weight: |
|
|
self.last_attn_probs = attn_probs.detach() |
|
|
else: |
|
|
assert self.last_attn_probs is not None |
|
|
attn_probs = self.last_attn_probs |
|
|
attn = torch.bmm(attn_probs, v) |
|
|
assert list(attn.size()) == [ |
|
|
bsz * self.num_heads, tgt_len, self.head_dim |
|
|
] |
|
|
attn = attn.transpose(0, 1).contiguous().view(tgt_len, bsz, embed_dim) |
|
|
attn = self.out_proj(attn) |
|
|
|
|
|
if need_weights: |
|
|
attn_weights = attn_weights_float.view( |
|
|
bsz, self.num_heads, tgt_len, src_len |
|
|
).transpose(1, 0) |
|
|
if not need_head_weights: |
|
|
|
|
|
attn_weights = attn_weights.mean(dim=0) |
|
|
else: |
|
|
attn_weights = None |
|
|
|
|
|
return attn, (attn_weights, attn_logits) |
|
|
|
|
|
def in_proj_qkv(self, query): |
|
|
return self._in_proj(query).chunk(3, dim=-1) |
|
|
|
|
|
def in_proj_q(self, query): |
|
|
if self.qkv_same_dim: |
|
|
return self._in_proj(query, end=self.embed_dim) |
|
|
else: |
|
|
bias = self.in_proj_bias |
|
|
if bias is not None: |
|
|
bias = bias[:self.embed_dim] |
|
|
return F.linear(query, self.q_proj_weight, bias) |
|
|
|
|
|
def in_proj_k(self, key): |
|
|
if self.qkv_same_dim: |
|
|
return self._in_proj( |
|
|
key, start=self.embed_dim, end=2 * self.embed_dim |
|
|
) |
|
|
else: |
|
|
weight = self.k_proj_weight |
|
|
bias = self.in_proj_bias |
|
|
if bias is not None: |
|
|
bias = bias[self.embed_dim:2 * self.embed_dim] |
|
|
return F.linear(key, weight, bias) |
|
|
|
|
|
def in_proj_v(self, value): |
|
|
if self.qkv_same_dim: |
|
|
return self._in_proj(value, start=2 * self.embed_dim) |
|
|
else: |
|
|
weight = self.v_proj_weight |
|
|
bias = self.in_proj_bias |
|
|
if bias is not None: |
|
|
bias = bias[2 * self.embed_dim:] |
|
|
return F.linear(value, weight, bias) |
|
|
|
|
|
def _in_proj(self, input, start=0, end=None): |
|
|
weight = self.in_proj_weight |
|
|
bias = self.in_proj_bias |
|
|
weight = weight[start:end, :] |
|
|
if bias is not None: |
|
|
bias = bias[start:end] |
|
|
return F.linear(input, weight, bias) |
|
|
|
|
|
def apply_sparse_mask(self, attn_weights, tgt_len, src_len, bsz): |
|
|
return attn_weights |
|
|
|
|
|
|
|
|
class TransformerFFNLayer(nn.Module): |
|
|
def __init__( |
|
|
self, |
|
|
hidden_size, |
|
|
filter_size, |
|
|
padding="SAME", |
|
|
kernel_size=1, |
|
|
dropout=0., |
|
|
act='gelu' |
|
|
): |
|
|
super().__init__() |
|
|
self.kernel_size = kernel_size |
|
|
self.dropout = dropout |
|
|
self.act = act |
|
|
if padding == 'SAME': |
|
|
self.ffn_1 = nn.Conv1d( |
|
|
hidden_size, |
|
|
filter_size, |
|
|
kernel_size, |
|
|
padding=kernel_size // 2 |
|
|
) |
|
|
elif padding == 'LEFT': |
|
|
self.ffn_1 = nn.Sequential( |
|
|
nn.ConstantPad1d((kernel_size - 1, 0), 0.0), |
|
|
nn.Conv1d(hidden_size, filter_size, kernel_size) |
|
|
) |
|
|
self.ffn_2 = nn.Linear(filter_size, hidden_size) |
|
|
|
|
|
def forward( |
|
|
self, |
|
|
x, |
|
|
): |
|
|
|
|
|
x = self.ffn_1(x.permute(1, 2, 0)).permute(2, 0, 1) |
|
|
x = x * self.kernel_size**-0.5 |
|
|
|
|
|
if self.act == 'gelu': |
|
|
x = F.gelu(x) |
|
|
if self.act == 'relu': |
|
|
x = F.relu(x) |
|
|
if self.act == 'swish': |
|
|
x = F.silu(x) |
|
|
x = F.dropout(x, self.dropout, training=self.training) |
|
|
x = self.ffn_2(x) |
|
|
return x |
|
|
|
|
|
|
|
|
class EncoderSelfAttentionLayer(nn.Module): |
|
|
def __init__( |
|
|
self, |
|
|
c, |
|
|
num_heads, |
|
|
dropout, |
|
|
attention_dropout=0.1, |
|
|
relu_dropout=0.1, |
|
|
kernel_size=9, |
|
|
padding='SAME', |
|
|
norm='ln', |
|
|
act='gelu', |
|
|
padding_set_zero=True |
|
|
): |
|
|
super().__init__() |
|
|
self.c = c |
|
|
self.dropout = dropout |
|
|
self.num_heads = num_heads |
|
|
self.padding_set_zero = padding_set_zero |
|
|
if num_heads > 0: |
|
|
if norm == 'ln': |
|
|
self.layer_norm1 = LayerNorm(c) |
|
|
elif norm == 'bn': |
|
|
self.layer_norm1 = BatchNorm1dTBC(c) |
|
|
self.self_attn = MultiheadAttention( |
|
|
self.c, |
|
|
num_heads=num_heads, |
|
|
self_attention=True, |
|
|
dropout=attention_dropout, |
|
|
bias=False, |
|
|
) |
|
|
if norm == 'ln': |
|
|
self.layer_norm2 = LayerNorm(c) |
|
|
elif norm == 'bn': |
|
|
self.layer_norm2 = BatchNorm1dTBC(c) |
|
|
self.ffn = TransformerFFNLayer( |
|
|
c, |
|
|
4 * c, |
|
|
kernel_size=kernel_size, |
|
|
dropout=relu_dropout, |
|
|
padding=padding, |
|
|
act=act |
|
|
) |
|
|
|
|
|
def forward(self, x, encoder_padding_mask=None, **kwargs): |
|
|
layer_norm_training = kwargs.get('layer_norm_training', None) |
|
|
if layer_norm_training is not None: |
|
|
self.layer_norm1.training = layer_norm_training |
|
|
self.layer_norm2.training = layer_norm_training |
|
|
if self.num_heads > 0: |
|
|
residual = x |
|
|
x = self.layer_norm1(x) |
|
|
x, _, = self.self_attn( |
|
|
query=x, key=x, value=x, key_padding_mask=encoder_padding_mask |
|
|
) |
|
|
x = F.dropout(x, self.dropout, training=self.training) |
|
|
x = residual + x |
|
|
if self.padding_set_zero: |
|
|
x = x * (1 - encoder_padding_mask.float()).transpose(0, |
|
|
1)[..., |
|
|
None] |
|
|
|
|
|
residual = x |
|
|
x = self.layer_norm2(x) |
|
|
x = self.ffn(x) |
|
|
x = F.dropout(x, self.dropout, training=self.training) |
|
|
x = residual + x |
|
|
if self.padding_set_zero: |
|
|
x = x * (1 - encoder_padding_mask.float()).transpose(0, 1)[..., |
|
|
None] |
|
|
return x |
|
|
|
|
|
|
|
|
class TransformerEncoderLayer(nn.Module): |
|
|
def __init__( |
|
|
self, |
|
|
hidden_size, |
|
|
dropout, |
|
|
kernel_size, |
|
|
num_heads=2, |
|
|
norm='ln', |
|
|
padding_set_zero=True, |
|
|
): |
|
|
super().__init__() |
|
|
self.hidden_size = hidden_size |
|
|
self.dropout = dropout |
|
|
self.num_heads = num_heads |
|
|
self.op = EncoderSelfAttentionLayer( |
|
|
hidden_size, |
|
|
num_heads, |
|
|
dropout=dropout, |
|
|
attention_dropout=0.0, |
|
|
relu_dropout=dropout, |
|
|
kernel_size=kernel_size, |
|
|
padding="SAME", |
|
|
norm=norm, |
|
|
act="gelu", |
|
|
padding_set_zero=padding_set_zero |
|
|
) |
|
|
|
|
|
def forward(self, x, **kwargs): |
|
|
return self.op(x, **kwargs) |
|
|
|
|
|
|
|
|
class FFTBlocks(nn.Module): |
|
|
def __init__( |
|
|
self, |
|
|
hidden_size, |
|
|
num_layers, |
|
|
ffn_kernel_size=9, |
|
|
dropout=0.1, |
|
|
num_heads=2, |
|
|
use_last_norm=True, |
|
|
padding_set_zero=True, |
|
|
): |
|
|
super().__init__() |
|
|
self.num_layers = num_layers |
|
|
embed_dim = self.hidden_size = hidden_size |
|
|
self.dropout = dropout |
|
|
self.use_last_norm = use_last_norm |
|
|
self.padding_set_zero = padding_set_zero |
|
|
|
|
|
self.layers = nn.ModuleList([]) |
|
|
self.layers.extend( |
|
|
[ |
|
|
TransformerEncoderLayer( |
|
|
self.hidden_size, |
|
|
self.dropout, |
|
|
kernel_size=ffn_kernel_size, |
|
|
num_heads=num_heads, |
|
|
padding_set_zero=padding_set_zero, |
|
|
) for _ in range(self.num_layers) |
|
|
] |
|
|
) |
|
|
if self.use_last_norm: |
|
|
self.layer_norm = nn.LayerNorm(embed_dim) |
|
|
else: |
|
|
self.layer_norm = None |
|
|
|
|
|
def forward(self, x, padding_mask=None, attn_mask=None): |
|
|
""" |
|
|
:param x: [B, T, C] |
|
|
:param padding_mask: [B, T] |
|
|
:return: [B, T, C] or [L, B, T, C] |
|
|
""" |
|
|
if padding_mask is None: |
|
|
padding_mask = torch.zeros(x.size(0), x.size(1)).to(x.device) |
|
|
nonpadding_mask_TB = 1 - padding_mask.transpose(0, 1).float( |
|
|
)[:, :, None] |
|
|
|
|
|
x = x.transpose(0, 1) |
|
|
if self.padding_set_zero: |
|
|
x = x * nonpadding_mask_TB |
|
|
for layer in self.layers: |
|
|
x = layer( |
|
|
x, encoder_padding_mask=padding_mask, attn_mask=attn_mask |
|
|
) |
|
|
if self.padding_set_zero: |
|
|
x = x * nonpadding_mask_TB |
|
|
if self.use_last_norm: |
|
|
x = self.layer_norm(x) |
|
|
if self.padding_set_zero: |
|
|
x = x * nonpadding_mask_TB |
|
|
|
|
|
x = x.transpose(0, 1) |
|
|
return x |
|
|
|
|
|
|
|
|
class FastSpeech2EncoderBase(nn.Module): |
|
|
def __init__( |
|
|
self, |
|
|
d_model: int, |
|
|
num_layers: int, |
|
|
num_heads: int, |
|
|
ffn_kernel_size: int, |
|
|
d_out: int, |
|
|
dropout: float = 0.1, |
|
|
rel_pos: bool = True, |
|
|
padding_set_zero: bool = True |
|
|
): |
|
|
super().__init__() |
|
|
self.rel_pos = rel_pos |
|
|
|
|
|
if self.rel_pos: |
|
|
self.pos_encoding = RelPositionalEncoding( |
|
|
d_model, dropout_rate=0.0 |
|
|
) |
|
|
else: |
|
|
self.pos_encoding = SinusoidalPositionalEmbedding( |
|
|
d_model, padding_idx=0 |
|
|
) |
|
|
self.dropout = dropout |
|
|
self.embed_scale = math.sqrt(d_model) |
|
|
|
|
|
self.layers = FFTBlocks( |
|
|
hidden_size=d_model, |
|
|
num_layers=num_layers, |
|
|
ffn_kernel_size=ffn_kernel_size, |
|
|
dropout=dropout, |
|
|
num_heads=num_heads, |
|
|
use_last_norm=True, |
|
|
padding_set_zero=padding_set_zero |
|
|
) |
|
|
|
|
|
self.out_proj = nn.Linear(d_model, d_out) |
|
|
self.apply(self.init_weights) |
|
|
|
|
|
def init_weights(self, m): |
|
|
if isinstance(m, nn.Linear): |
|
|
nn.init.xavier_uniform_(m.weight) |
|
|
if m.bias is not None: |
|
|
nn.init.constant_(m.bias, 0.) |
|
|
elif isinstance(m, nn.Embedding): |
|
|
nn.init.normal_(m.weight, mean=0, std=m.embedding_dim**-0.5) |
|
|
|
|
|
|
|
|
@dataclass |
|
|
class SpkConfig: |
|
|
encoding_format: str |
|
|
num_spk: int | None = None |
|
|
spk_embed_dim: int | None = None |
|
|
|
|
|
def __post_init__(self): |
|
|
allowed_formats = {"id", "embedding"} |
|
|
assert self.encoding_format in allowed_formats, f"mode must be one of {allowed_formats}, got '{self.encoding_format}'" |
|
|
if self.encoding_format == "id": |
|
|
assert self.num_spk is not None |
|
|
if self.encoding_format == "embedding": |
|
|
assert self.spk_embed_dim is not None |
|
|
|
|
|
|
|
|
class FastSpeech2PhonemeEncoder(FastSpeech2EncoderBase): |
|
|
def __init__( |
|
|
self, |
|
|
phone_vocab_size, |
|
|
d_model, |
|
|
num_layers, |
|
|
num_heads, |
|
|
ffn_kernel_size, |
|
|
d_out, |
|
|
dropout=0.1, |
|
|
rel_pos=False, |
|
|
spk_config: SpkConfig | None = None, |
|
|
padding_set_zero: bool = True |
|
|
): |
|
|
super().__init__( |
|
|
d_model=d_model, |
|
|
num_layers=num_layers, |
|
|
num_heads=num_heads, |
|
|
ffn_kernel_size=ffn_kernel_size, |
|
|
d_out=d_out, |
|
|
dropout=dropout, |
|
|
rel_pos=rel_pos, |
|
|
padding_set_zero=padding_set_zero |
|
|
) |
|
|
self.phone_embed = Embedding(phone_vocab_size, d_model) |
|
|
self.spk_config = spk_config |
|
|
if spk_config is not None: |
|
|
if spk_config.encoding_format == "id": |
|
|
self.spk_embed_proj = Embedding( |
|
|
spk_config.num_spk + 1, d_model |
|
|
) |
|
|
elif spk_config.encoding_format == "embedding": |
|
|
self.spk_embed_proj = Linear(spk_config.spk_embed_dim, d_model) |
|
|
|
|
|
def forward( |
|
|
self, phoneme: torch.Tensor, lengths: Sequence[int], spk: torch.Tensor |
|
|
): |
|
|
x = self.embed_scale * self.phone_embed(phoneme) |
|
|
x = self.pos_encoding(x, lengths) |
|
|
x = F.dropout(x, p=self.dropout, training=self.training) |
|
|
|
|
|
padding_mask = ~create_mask_from_length(lengths).to(phoneme.device) |
|
|
x = self.layers(x, padding_mask=padding_mask) |
|
|
|
|
|
if self.spk_config is not None: |
|
|
spk_embed = self.spk_embed_proj(spk).unsqueeze(1) |
|
|
x = x + spk_embed |
|
|
|
|
|
x = self.out_proj(x) |
|
|
|
|
|
return {"output": x, "mask": ~padding_mask} |
|
|
|
|
|
|
|
|
class FastSpeech2MIDIEncoder(FastSpeech2PhonemeEncoder): |
|
|
def __init__( |
|
|
self, |
|
|
phone_vocab_size: int, |
|
|
midi_vocab_size: int, |
|
|
slur_vocab_size: int, |
|
|
spk_config: SpkConfig | None, |
|
|
d_model: int, |
|
|
num_layers: int, |
|
|
num_heads: int, |
|
|
ffn_kernel_size: int, |
|
|
d_out: int, |
|
|
dropout: float = 0.1, |
|
|
rel_pos: bool = True, |
|
|
padding_set_zero: bool = True |
|
|
): |
|
|
super().__init__( |
|
|
phone_vocab_size=phone_vocab_size, |
|
|
d_model=d_model, |
|
|
num_layers=num_layers, |
|
|
num_heads=num_heads, |
|
|
ffn_kernel_size=ffn_kernel_size, |
|
|
d_out=d_out, |
|
|
dropout=dropout, |
|
|
rel_pos=rel_pos, |
|
|
spk_config=spk_config, |
|
|
padding_set_zero=padding_set_zero |
|
|
) |
|
|
self.midi_embed = Embedding(midi_vocab_size, d_model, padding_idx=0) |
|
|
self.midi_dur_embed = Linear(1, d_model) |
|
|
self.is_slur_embed = Embedding(slur_vocab_size, d_model) |
|
|
|
|
|
def forward( |
|
|
self, |
|
|
phoneme: torch.Tensor, |
|
|
midi: torch.Tensor, |
|
|
midi_duration: torch.Tensor, |
|
|
is_slur: torch.Tensor, |
|
|
lengths: Sequence[int], |
|
|
spk: torch.Tensor | None = None, |
|
|
): |
|
|
x = self.embed_scale * self.phone_embed(phoneme) |
|
|
midi_embedding = self.midi_embed(midi) |
|
|
midi_dur_embedding = self.midi_dur_embed(midi_duration[:, :, None]) |
|
|
slur_embedding = self.is_slur_embed(is_slur) |
|
|
|
|
|
x = x + midi_embedding + midi_dur_embedding + slur_embedding |
|
|
x = self.pos_encoding(x, lengths) |
|
|
x = F.dropout(x, p=self.dropout, training=self.training) |
|
|
|
|
|
padding_mask = ~create_mask_from_length(lengths).to(phoneme.device) |
|
|
x = self.layers(x, padding_mask=padding_mask) |
|
|
|
|
|
if self.spk_config is not None: |
|
|
spk_embed = self.spk_embed_proj(spk).unsqueeze(1) |
|
|
x = x + spk_embed |
|
|
|
|
|
x = self.out_proj(x) |
|
|
|
|
|
return {"output": x, "mask": ~padding_mask} |
|
|
|
|
|
|
|
|
class FastSpeech2PitchEncoder(FastSpeech2EncoderBase): |
|
|
def __init__( |
|
|
self, |
|
|
phone_vocab_size, |
|
|
d_model, |
|
|
num_layers, |
|
|
num_heads, |
|
|
ffn_kernel_size, |
|
|
d_out, |
|
|
dropout=0.1, |
|
|
rel_pos=False, |
|
|
padding_set_zero=True |
|
|
): |
|
|
super().__init__( |
|
|
d_model=d_model, |
|
|
num_layers=num_layers, |
|
|
num_heads=num_heads, |
|
|
ffn_kernel_size=ffn_kernel_size, |
|
|
d_out=d_out, |
|
|
dropout=dropout, |
|
|
rel_pos=rel_pos, |
|
|
padding_set_zero=padding_set_zero |
|
|
) |
|
|
self.phone_embed = Embedding(phone_vocab_size, d_model) |
|
|
self.pitch_embed = Embedding(300, d_model) |
|
|
|
|
|
def forward(self, phoneme: torch.Tensor, lengths: Sequence[int]): |
|
|
x = self.embed_scale * self.phone_embed(phoneme) |
|
|
x = self.pos_encoding(x, lengths) |
|
|
x = F.dropout(x, p=self.dropout, training=self.training) |
|
|
|
|
|
padding_mask = ~create_mask_from_length(lengths).to(phoneme.device) |
|
|
x = self.layers(x, padding_mask=padding_mask) |
|
|
|
|
|
x = self.out_proj(x) |
|
|
|
|
|
return {"output": x, "mask": ~padding_mask} |
|
|
|
|
|
def encode_pitch(self, f0, uv): |
|
|
|
|
|
f0_denorm = denorm_f0(f0, uv) |
|
|
pitch = f0_to_coarse(f0_denorm) |
|
|
pitch_embed = self.pitch_embed(pitch) |
|
|
return {"output": pitch_embed} |
|
|
|