Spaces:
Running
Running
| from math import sqrt | |
| import torch | |
| import torch.distributions as distr | |
| from torch.autograd import Variable | |
| from torch import nn | |
| from torch.nn import functional as F | |
| from .layers import ConvNorm, LinearNorm, GlobalAvgPool | |
| from .utils import to_gpu, get_mask_from_lengths | |
| class LocationLayer(nn.Module): | |
| def __init__(self, attention_n_filters, attention_kernel_size, | |
| attention_dim): | |
| super(LocationLayer, self).__init__() | |
| padding = int((attention_kernel_size - 1) / 2) | |
| self.location_conv = ConvNorm(2, attention_n_filters, | |
| kernel_size=attention_kernel_size, | |
| padding=padding, bias=False, stride=1, | |
| dilation=1) | |
| self.location_dense = LinearNorm(attention_n_filters, attention_dim, | |
| bias=False, w_init_gain='tanh') | |
| def forward(self, attention_weights_cat): | |
| processed_attention = self.location_conv(attention_weights_cat) | |
| processed_attention = processed_attention.transpose(1, 2) | |
| processed_attention = self.location_dense(processed_attention) | |
| return processed_attention | |
| class Attention(nn.Module): | |
| def __init__(self, attention_rnn_dim, embedding_dim, attention_dim, | |
| attention_location_n_filters, attention_location_kernel_size): | |
| super(Attention, self).__init__() | |
| self.query_layer = LinearNorm(attention_rnn_dim, attention_dim, | |
| bias=False, w_init_gain='tanh') | |
| self.memory_layer = LinearNorm(embedding_dim, attention_dim, bias=False, | |
| w_init_gain='tanh') | |
| self.v = LinearNorm(attention_dim, 1, bias=False) | |
| self.location_layer = LocationLayer(attention_location_n_filters, | |
| attention_location_kernel_size, | |
| attention_dim) | |
| self.score_mask_value = -float("inf") | |
| def get_alignment_energies(self, query, processed_memory, | |
| attention_weights_cat): | |
| """ | |
| PARAMS | |
| ------ | |
| query: decoder output (batch, n_mel_channels * n_frames_per_step) | |
| processed_memory: processed encoder outputs (B, T_in, attention_dim) | |
| attention_weights_cat: cumulative and prev. att weights (B, 2, max_time) | |
| RETURNS | |
| ------- | |
| alignment (batch, max_time) | |
| """ | |
| processed_query = self.query_layer(query.unsqueeze(1)) | |
| processed_attention_weights = self.location_layer(attention_weights_cat) | |
| energies = self.v(torch.tanh( | |
| processed_query + processed_attention_weights + processed_memory)) | |
| energies = energies.squeeze(-1) | |
| return energies | |
| def forward(self, attention_hidden_state, memory, processed_memory, | |
| attention_weights_cat, mask): | |
| """ | |
| PARAMS | |
| ------ | |
| attention_hidden_state: attention rnn last output | |
| memory: encoder outputs | |
| processed_memory: processed encoder outputs | |
| attention_weights_cat: previous and cummulative attention weights | |
| mask: binary mask for padded data | |
| """ | |
| alignment = self.get_alignment_energies( | |
| attention_hidden_state, processed_memory, attention_weights_cat) | |
| if mask is not None: | |
| alignment.data.masked_fill_(mask, self.score_mask_value) | |
| attention_weights = F.softmax(alignment, dim=1) | |
| attention_context = torch.bmm(attention_weights.unsqueeze(1), memory) | |
| attention_context = attention_context.squeeze(1) | |
| return attention_context, attention_weights | |
| class Prenet(nn.Module): | |
| def __init__(self, in_dim, sizes): | |
| super(Prenet, self).__init__() | |
| in_sizes = [in_dim] + sizes[:-1] | |
| self.layers = nn.ModuleList( | |
| [LinearNorm(in_size, out_size, bias=False) | |
| for (in_size, out_size) in zip(in_sizes, sizes)]) | |
| def forward(self, x): | |
| for linear in self.layers: | |
| x = F.dropout(F.relu(linear(x)), p=0.5, training=True) | |
| return x | |
| class Postnet(nn.Module): | |
| """Postnet | |
| - Five 1-d convolution with 512 channels and kernel size 5 | |
| """ | |
| def __init__(self, hparams): | |
| super(Postnet, self).__init__() | |
| self.convolutions = nn.ModuleList() | |
| self.convolutions.append( | |
| nn.Sequential( | |
| ConvNorm(hparams.n_mel_channels, hparams.postnet_embedding_dim, | |
| kernel_size=hparams.postnet_kernel_size, stride=1, | |
| padding=int((hparams.postnet_kernel_size - 1) / 2), | |
| dilation=1, w_init_gain='tanh'), | |
| nn.BatchNorm1d(hparams.postnet_embedding_dim)) | |
| ) | |
| for i in range(1, hparams.postnet_n_convolutions - 1): | |
| self.convolutions.append( | |
| nn.Sequential( | |
| ConvNorm(hparams.postnet_embedding_dim, | |
| hparams.postnet_embedding_dim, | |
| kernel_size=hparams.postnet_kernel_size, stride=1, | |
| padding=int((hparams.postnet_kernel_size - 1) / 2), | |
| dilation=1, w_init_gain='tanh'), | |
| nn.BatchNorm1d(hparams.postnet_embedding_dim)) | |
| ) | |
| self.convolutions.append( | |
| nn.Sequential( | |
| ConvNorm(hparams.postnet_embedding_dim, hparams.n_mel_channels, | |
| kernel_size=hparams.postnet_kernel_size, stride=1, | |
| padding=int((hparams.postnet_kernel_size - 1) / 2), | |
| dilation=1, w_init_gain='linear'), | |
| nn.BatchNorm1d(hparams.n_mel_channels)) | |
| ) | |
| def forward(self, x): | |
| for i in range(len(self.convolutions) - 1): | |
| x = F.dropout(torch.tanh(self.convolutions[i](x)), 0.5, self.training) | |
| x = F.dropout(self.convolutions[-1](x), 0.5, self.training) | |
| return x | |
| class Encoder(nn.Module): | |
| """Encoder module: | |
| - Three 1-d convolution banks | |
| - Bidirectional LSTM | |
| """ | |
| def __init__(self, hparams): | |
| super(Encoder, self).__init__() | |
| convolutions = [] | |
| for _ in range(hparams.encoder_n_convolutions): | |
| conv_layer = nn.Sequential( | |
| ConvNorm(hparams.encoder_embedding_dim, | |
| hparams.encoder_embedding_dim, | |
| kernel_size=hparams.encoder_kernel_size, stride=1, | |
| padding=int((hparams.encoder_kernel_size - 1) / 2), | |
| dilation=1, w_init_gain='relu'), | |
| nn.BatchNorm1d(hparams.encoder_embedding_dim)) | |
| convolutions.append(conv_layer) | |
| self.convolutions = nn.ModuleList(convolutions) | |
| self.lstm = nn.LSTM(hparams.encoder_embedding_dim, | |
| int(hparams.encoder_embedding_dim / 2), 1, | |
| batch_first=True, bidirectional=True) | |
| def forward(self, x, input_lengths): | |
| for conv in self.convolutions: | |
| x = F.dropout(F.relu(conv(x)), 0.5, self.training) | |
| x = x.transpose(1, 2) | |
| # pytorch tensor are not reversible, hence the conversion | |
| input_lengths = input_lengths.cpu().numpy() | |
| x = nn.utils.rnn.pack_padded_sequence( | |
| x, input_lengths, batch_first=True) | |
| self.lstm.flatten_parameters() | |
| outputs, _ = self.lstm(x) | |
| outputs, _ = nn.utils.rnn.pad_packed_sequence( | |
| outputs, batch_first=True) | |
| return outputs | |
| def inference(self, x): | |
| for conv in self.convolutions: | |
| x = F.dropout(F.relu(conv(x)), 0.5, self.training) | |
| x = x.transpose(1, 2) | |
| self.lstm.flatten_parameters() | |
| outputs, _ = self.lstm(x) | |
| return outputs | |
| class AudioEncoder(nn.Module): | |
| def __init__(self, hparams): | |
| super(AudioEncoder, self).__init__() | |
| assert hparams.lat_dim > 0 | |
| convolutions = [] | |
| inp_dim = hparams.n_mel_channels | |
| for _ in range(hparams.lat_n_convolutions): | |
| conv_layer = nn.Sequential( | |
| ConvNorm(inp_dim, hparams.lat_n_filters, | |
| kernel_size=hparams.lat_kernel_size, stride=1, | |
| padding=int((hparams.lat_kernel_size - 1) / 2), | |
| dilation=1, w_init_gain='tanh'), | |
| nn.BatchNorm1d(hparams.lat_n_filters)) | |
| inp_dim = hparams.lat_n_filters | |
| convolutions.append(conv_layer) | |
| self.convolutions = nn.ModuleList(convolutions) | |
| self.lstm = nn.LSTM(hparams.lat_n_filters, | |
| int(hparams.lat_n_filters / 2), | |
| hparams.lat_n_blstms, batch_first=True, | |
| bidirectional=True) | |
| self.pool = GlobalAvgPool() | |
| self.mu_proj = LinearNorm(hparams.lat_n_filters, hparams.lat_dim) | |
| self.logvar_proj = LinearNorm(hparams.lat_n_filters, hparams.lat_dim) | |
| self.lat_dim = hparams.lat_dim | |
| def forward(self, x, lengths): | |
| """ | |
| Args: | |
| x (torch.Tensor): (B, F, T) | |
| """ | |
| for conv in self.convolutions: | |
| x = F.dropout(F.tanh(conv(x)), 0.5, self.training) | |
| x = x.transpose(1, 2) # (B, T, D) | |
| # x may not be sorted by length. Sort->process->unsort | |
| max_len = x.size(1) | |
| assert max_len == torch.max(lengths).item() | |
| lengths, perm_idx = lengths.sort(0, descending=True) | |
| x = x[perm_idx] | |
| x = nn.utils.rnn.pack_padded_sequence(x, lengths, batch_first=True) | |
| self.lstm.flatten_parameters() | |
| outputs, _ = self.lstm(x) | |
| outputs, _ = nn.utils.rnn.pad_packed_sequence(outputs, batch_first=True) | |
| _, unperm_idx = perm_idx.sort(0) | |
| outputs = outputs[unperm_idx] # (B, T, D) | |
| lengths = lengths[unperm_idx] # (B, T, D) | |
| outputs = self.pool(outputs, lengths) # (B, D) | |
| mu = self.mu_proj(outputs) | |
| logvar = self.logvar_proj(outputs) | |
| z = distr.Normal(mu, logvar).rsample() | |
| return z, mu, logvar | |
| class Decoder(nn.Module): | |
| def __init__(self, hparams): | |
| super(Decoder, self).__init__() | |
| self.n_mel_channels = hparams.n_mel_channels | |
| self.n_frames_per_step = hparams.n_frames_per_step | |
| self.encoder_embedding_dim = hparams.encoder_embedding_dim | |
| self.obs_dim = hparams.obs_dim | |
| self.lat_dim = hparams.lat_dim | |
| self.attention_rnn_dim = hparams.attention_rnn_dim | |
| self.decoder_rnn_dim = hparams.decoder_rnn_dim | |
| self.prenet_dim = hparams.prenet_dim | |
| self.max_decoder_steps = hparams.max_decoder_steps | |
| self.gate_threshold = hparams.gate_threshold | |
| self.p_attention_dropout = hparams.p_attention_dropout | |
| self.p_decoder_dropout = hparams.p_decoder_dropout | |
| self.prenet = Prenet( | |
| hparams.n_mel_channels * hparams.n_frames_per_step, | |
| [hparams.prenet_dim, hparams.prenet_dim]) | |
| self.attention_rnn = nn.LSTMCell( | |
| hparams.prenet_dim + hparams.encoder_embedding_dim, | |
| hparams.attention_rnn_dim) | |
| self.attention_layer = Attention( | |
| hparams.attention_rnn_dim, hparams.encoder_embedding_dim, | |
| hparams.attention_dim, hparams.attention_location_n_filters, | |
| hparams.attention_location_kernel_size) | |
| encoder_tot_dim = (hparams.encoder_embedding_dim + \ | |
| hparams.lat_dim + hparams.obs_dim) | |
| self.decoder_rnn = nn.LSTMCell( | |
| hparams.attention_rnn_dim + encoder_tot_dim, | |
| hparams.decoder_rnn_dim, 1) | |
| self.linear_projection = LinearNorm( | |
| hparams.decoder_rnn_dim + encoder_tot_dim, | |
| hparams.n_mel_channels * hparams.n_frames_per_step) | |
| self.gate_layer = LinearNorm( | |
| hparams.decoder_rnn_dim + encoder_tot_dim, 1, | |
| bias=True, w_init_gain='sigmoid') | |
| def get_go_frame(self, memory): | |
| """ Gets all zeros frames to use as first decoder input | |
| PARAMS | |
| ------ | |
| memory: decoder outputs | |
| RETURNS | |
| ------- | |
| decoder_input: all zeros frames | |
| """ | |
| B = memory.size(0) | |
| decoder_input = Variable(memory.data.new( | |
| B, self.n_mel_channels * self.n_frames_per_step).zero_()) | |
| return decoder_input | |
| def initialize_decoder_states(self, memory, obs_and_lat, mask): | |
| """ Initializes attention rnn states, decoder rnn states, attention | |
| weights, attention cumulative weights, attention context, stores memory | |
| and stores processed memory | |
| PARAMS | |
| ------ | |
| memory: Encoder outputs | |
| obs_and_lat: Observed and latent attribute embeddings | |
| mask: Mask for padded data if training, expects None for inference | |
| """ | |
| B = memory.size(0) | |
| MAX_TIME = memory.size(1) | |
| self.attention_hidden = Variable(memory.data.new( | |
| B, self.attention_rnn_dim).zero_()) | |
| self.attention_cell = Variable(memory.data.new( | |
| B, self.attention_rnn_dim).zero_()) | |
| self.decoder_hidden = Variable(memory.data.new( | |
| B, self.decoder_rnn_dim).zero_()) | |
| self.decoder_cell = Variable(memory.data.new( | |
| B, self.decoder_rnn_dim).zero_()) | |
| self.attention_weights = Variable(memory.data.new( | |
| B, MAX_TIME).zero_()) | |
| self.attention_weights_cum = Variable(memory.data.new( | |
| B, MAX_TIME).zero_()) | |
| self.attention_context = Variable(memory.data.new( | |
| B, self.encoder_embedding_dim).zero_()) | |
| self.memory = memory | |
| self.processed_memory = self.attention_layer.memory_layer(memory) | |
| self.obs_and_lat = obs_and_lat | |
| self.mask = mask | |
| def parse_decoder_inputs(self, decoder_inputs): | |
| """ Prepares decoder inputs, i.e. mel outputs | |
| PARAMS | |
| ------ | |
| decoder_inputs: inputs used for teacher-forced training, i.e. mel-specs | |
| RETURNS | |
| ------- | |
| inputs: processed decoder inputs | |
| """ | |
| # (B, n_mel_channels, T_out) -> (B, T_out, n_mel_channels) | |
| decoder_inputs = decoder_inputs.transpose(1, 2) | |
| decoder_inputs = decoder_inputs.view( | |
| decoder_inputs.size(0), | |
| int(decoder_inputs.size(1)/self.n_frames_per_step), -1) | |
| # (B, T_out, n_mel_channels) -> (T_out, B, n_mel_channels) | |
| decoder_inputs = decoder_inputs.transpose(0, 1) | |
| return decoder_inputs | |
| def parse_decoder_outputs(self, mel_outputs, gate_outputs, alignments): | |
| """ Prepares decoder outputs for output | |
| PARAMS | |
| ------ | |
| mel_outputs: | |
| gate_outputs: gate output energies | |
| alignments: | |
| RETURNS | |
| ------- | |
| mel_outputs: | |
| gate_outpust: gate output energies | |
| alignments: | |
| """ | |
| # (T_out, B) -> (B, T_out) | |
| alignments = torch.stack(alignments).transpose(0, 1) | |
| # (T_out, B) -> (B, T_out) | |
| gate_outputs = torch.stack(gate_outputs).transpose(0, 1) | |
| gate_outputs = gate_outputs.contiguous() | |
| # (T_out, B, n_mel_channels) -> (B, T_out, n_mel_channels) | |
| mel_outputs = torch.stack(mel_outputs).transpose(0, 1).contiguous() | |
| # decouple frames per step | |
| mel_outputs = mel_outputs.view( | |
| mel_outputs.size(0), -1, self.n_mel_channels) | |
| # (B, T_out, n_mel_channels) -> (B, n_mel_channels, T_out) | |
| mel_outputs = mel_outputs.transpose(1, 2) | |
| return mel_outputs, gate_outputs, alignments | |
| def decode(self, decoder_input): | |
| """ Decoder step using stored states, attention and memory | |
| PARAMS | |
| ------ | |
| decoder_input: previous mel output | |
| RETURNS | |
| ------- | |
| mel_output: | |
| gate_output: gate output energies | |
| attention_weights: | |
| """ | |
| cell_input = torch.cat((decoder_input, self.attention_context), -1) | |
| self.attention_hidden, self.attention_cell = self.attention_rnn( | |
| cell_input, (self.attention_hidden, self.attention_cell)) | |
| self.attention_hidden = F.dropout( | |
| self.attention_hidden, self.p_attention_dropout, self.training) | |
| attention_weights_cat = torch.cat( | |
| (self.attention_weights.unsqueeze(1), | |
| self.attention_weights_cum.unsqueeze(1)), dim=1) | |
| self.attention_context, self.attention_weights = self.attention_layer( | |
| self.attention_hidden, self.memory, self.processed_memory, | |
| attention_weights_cat, self.mask) | |
| self.attention_weights_cum += self.attention_weights | |
| decoder_input = torch.cat( | |
| (self.attention_hidden, self.attention_context), -1) | |
| if self.obs_and_lat is not None: | |
| decoder_input = torch.cat((decoder_input, self.obs_and_lat), -1) | |
| self.decoder_hidden, self.decoder_cell = self.decoder_rnn( | |
| decoder_input, (self.decoder_hidden, self.decoder_cell)) | |
| self.decoder_hidden = F.dropout( | |
| self.decoder_hidden, self.p_decoder_dropout, self.training) | |
| decoder_hidden_attention_context = torch.cat( | |
| (self.decoder_hidden, self.attention_context), dim=1) | |
| if self.obs_and_lat is not None: | |
| decoder_hidden_attention_context = torch.cat( | |
| (decoder_hidden_attention_context, self.obs_and_lat), dim=1) | |
| decoder_output = self.linear_projection( | |
| decoder_hidden_attention_context) | |
| gate_prediction = self.gate_layer(decoder_hidden_attention_context) | |
| return decoder_output, gate_prediction, self.attention_weights | |
| def forward(self, memory, obs_and_lat, decoder_inputs, memory_lengths): | |
| """ Decoder forward pass for training | |
| PARAMS | |
| ------ | |
| memory: Encoder outputs | |
| obs_and_lat: Observed and latent attribute embeddings | |
| decoder_inputs: Decoder inputs for teacher forcing. i.e. mel-specs | |
| memory_lengths: Encoder output lengths for attention masking. | |
| RETURNS | |
| ------- | |
| mel_outputs: mel outputs from the decoder | |
| gate_outputs: gate outputs from the decoder | |
| alignments: sequence of attention weights from the decoder | |
| """ | |
| decoder_input = self.get_go_frame(memory).unsqueeze(0) | |
| decoder_inputs = self.parse_decoder_inputs(decoder_inputs) | |
| decoder_inputs = torch.cat((decoder_input, decoder_inputs), dim=0) | |
| decoder_inputs = self.prenet(decoder_inputs) | |
| self.initialize_decoder_states( | |
| memory, obs_and_lat, mask=~get_mask_from_lengths(memory_lengths)) | |
| mel_outputs, gate_outputs, alignments = [], [], [] | |
| while len(mel_outputs) < decoder_inputs.size(0) - 1: | |
| decoder_input = decoder_inputs[len(mel_outputs)] | |
| mel_output, gate_output, attention_weights = self.decode( | |
| decoder_input) | |
| mel_outputs += [mel_output.squeeze(1)] | |
| gate_outputs += [gate_output.squeeze()] | |
| alignments += [attention_weights] | |
| mel_outputs, gate_outputs, alignments = self.parse_decoder_outputs( | |
| mel_outputs, gate_outputs, alignments) | |
| return mel_outputs, gate_outputs, alignments | |
| def inference(self, memory, obs_and_lat, ret_has_eos=False): | |
| """ Decoder inference | |
| PARAMS | |
| ------ | |
| memory: Encoder outputs | |
| obs_and_lat: Observed and latent attribute embeddings | |
| RETURNS | |
| ------- | |
| mel_outputs: mel outputs from the decoder | |
| gate_outputs: gate outputs from the decoder | |
| alignments: sequence of attention weights from the decoder | |
| """ | |
| decoder_input = self.get_go_frame(memory) | |
| self.initialize_decoder_states(memory, obs_and_lat, mask=None) | |
| mel_outputs, gate_outputs, alignments = [], [], [] | |
| has_eos = False | |
| while True: | |
| decoder_input = self.prenet(decoder_input) | |
| mel_output, gate_output, alignment = self.decode(decoder_input) | |
| mel_outputs += [mel_output.squeeze(1)] | |
| gate_outputs += [gate_output] | |
| alignments += [alignment] | |
| if torch.sigmoid(gate_output.data) > self.gate_threshold: | |
| has_eos = True | |
| break | |
| elif len(mel_outputs) == self.max_decoder_steps: | |
| # print("Warning! Reached max decoder steps") | |
| break | |
| decoder_input = mel_output | |
| mel_outputs, gate_outputs, alignments = self.parse_decoder_outputs( | |
| mel_outputs, gate_outputs, alignments) | |
| if ret_has_eos: | |
| return mel_outputs, gate_outputs, alignments, has_eos | |
| else: | |
| return mel_outputs, gate_outputs, alignments | |
| class Tacotron2(nn.Module): | |
| def __init__(self, hparams): | |
| super(Tacotron2, self).__init__() | |
| self.mask_padding = hparams.mask_padding | |
| self.fp16_run = hparams.fp16_run | |
| self.n_mel_channels = hparams.n_mel_channels | |
| self.n_frames_per_step = hparams.n_frames_per_step | |
| # initialize text encoder embedding | |
| self.embedding = nn.Embedding( | |
| hparams.n_symbols, hparams.symbols_embedding_dim) | |
| std = sqrt(2.0 / (hparams.n_symbols + hparams.symbols_embedding_dim)) | |
| val = sqrt(3.0) * std # uniform bounds for std | |
| self.embedding.weight.data.uniform_(-val, val) | |
| # initialize observed attribute embedding | |
| self.obs_embedding = None | |
| if hparams.obs_dim > 0: | |
| self.obs_embedding = nn.Embedding( | |
| hparams.obs_n_class, hparams.obs_dim) | |
| std = sqrt(2.0 / (hparams.obs_n_class + hparams.obs_dim)) | |
| val = sqrt(3.0) * std # uniform bounds for std | |
| self.obs_embedding.weight.data.uniform_(-val, val) | |
| self.encoder = Encoder(hparams) | |
| self.decoder = Decoder(hparams) | |
| self.postnet = Postnet(hparams) | |
| self.lat_encoder = None | |
| if hparams.lat_dim > 0: | |
| self.lat_encoder = AudioEncoder(hparams) | |
| def parse_batch(self, batch): | |
| (text_padded, input_lengths, obs_labels, | |
| mel_padded, gate_padded, output_lengths) = batch | |
| text_padded = to_gpu(text_padded).long() | |
| input_lengths = to_gpu(input_lengths).long() | |
| obs_labels = to_gpu(obs_labels).long() | |
| max_len = torch.max(input_lengths.data).item() | |
| mel_padded = to_gpu(mel_padded).float() | |
| gate_padded = to_gpu(gate_padded).float() | |
| output_lengths = to_gpu(output_lengths).long() | |
| return ( | |
| (text_padded, input_lengths, obs_labels, | |
| mel_padded, max_len, output_lengths), | |
| (mel_padded, gate_padded)) | |
| def parse_output(self, outputs, output_lengths=None): | |
| if self.mask_padding and output_lengths is not None: | |
| mask = ~get_mask_from_lengths(output_lengths) | |
| mask = mask.expand(self.n_mel_channels, mask.size(0), mask.size(1)) | |
| mask = mask.permute(1, 0, 2) | |
| outputs[0].data.masked_fill_(mask, 0.0) | |
| outputs[1].data.masked_fill_(mask, 0.0) | |
| outputs[2].data.masked_fill_(mask[:, 0, :], 1e3) # gate energies | |
| return outputs | |
| def forward(self, inputs): | |
| (text_inputs, text_lengths, obs_labels, | |
| mels, max_len, output_lengths) = inputs | |
| text_lengths, output_lengths = text_lengths.data, output_lengths.data | |
| embedded_inputs = self.embedding(text_inputs).transpose(1, 2) | |
| encoder_outputs = self.encoder(embedded_inputs, text_lengths) | |
| obs = None | |
| if self.obs_embedding is not None: | |
| obs = self.obs_embedding(obs_labels) | |
| lat, lat_mu, lat_logvar = None, None, None | |
| if self.lat_encoder is not None: | |
| (lat, lat_mu, lat_logvar) = self.lat_encoder(mels, output_lengths) | |
| obs_and_lat = [x for x in [obs, lat] if x is not None] | |
| if bool(obs_and_lat): | |
| obs_and_lat = torch.cat(obs_and_lat, dim=-1) | |
| else: | |
| obs_and_lat = None | |
| mel_outputs, gate_outputs, alignments = self.decoder( | |
| encoder_outputs, obs_and_lat, mels, memory_lengths=text_lengths) | |
| mel_outputs_postnet = self.postnet(mel_outputs) | |
| mel_outputs_postnet = mel_outputs + mel_outputs_postnet | |
| return self.parse_output( | |
| [mel_outputs, mel_outputs_postnet, gate_outputs, alignments, | |
| lat_mu, lat_logvar], | |
| output_lengths) | |
| def inference(self, inputs, obs_labels=None, lat=None, ret_has_eos=False): | |
| embedded_inputs = self.embedding(inputs).transpose(1, 2) | |
| encoder_outputs = self.encoder.inference(embedded_inputs) | |
| if obs_labels is None: | |
| obs_labels = torch.LongTensor(len(inputs)) | |
| obs_labels = obs_labels.to(inputs.device).zero_() | |
| obs = None | |
| if self.obs_embedding is not None: | |
| obs = self.obs_embedding(obs_labels) | |
| if self.lat_encoder is not None: | |
| if lat is None: | |
| lat = torch.FloatTensor(len(inputs), self.lat_encoder.lat_dim) | |
| lat = lat.to(inputs.device).zero_().type(encoder_outputs.type()) | |
| obs_and_lat = [x for x in [obs, lat] if x is not None] | |
| if bool(obs_and_lat): | |
| obs_and_lat = torch.cat(obs_and_lat, dim=-1) | |
| else: | |
| obs_and_lat = None | |
| mel_outputs, gate_outputs, alignments, has_eos = self.decoder.inference( | |
| encoder_outputs, obs_and_lat, ret_has_eos=True) | |
| mel_outputs_postnet = self.postnet(mel_outputs) | |
| mel_outputs_postnet = mel_outputs + mel_outputs_postnet | |
| outputs = self.parse_output( | |
| [mel_outputs, mel_outputs_postnet, gate_outputs, alignments]) | |
| if ret_has_eos: | |
| return outputs + [has_eos] | |
| else: | |
| return outputs | |