예제 #1
0
    def train_one_epoch(self, criterion, data_loaders, phases=('train', 'test')):
        epoch_beg = time.time()
        self.model.to(self.device)
        dataset_sizes = {x: len(data_loaders[x].dataset)
                         for x in phases}
        batch_sizes = {x: data_loaders[x].batch_size for x in phases}
        try:
            m = (1 - self.params_dict['warmup_initial_scale'])/(self.params_dict['warmup_num_epochs'] - 1)
            c = self.params_dict['warmup_initial_scale']
        except ZeroDivisionError:
            m = 1
            c = 0
        lr_scale = m * self.elapsed_epochs() + c
        if self.elapsed_epochs() < self.params_dict['warmup_num_epochs']:
            self.optimizer.param_groups[0]['lr'] *= lr_scale
        self.loss_history[str(self.elapsed_epochs())] = {}
        print('Epoch {}/{} - lr={}'.format(self.elapsed_epochs(), self.params_dict['num_epochs'],
                                           self.optimizer.param_groups[0]['lr'])
              )
        for phase in phases:
            print('\t{} '.format(phase.title()), end='')
            phase_beg = time.time()
            if phase == 'train':
                self.model.train()
            else:
                self.model.eval()
            running_loss = 0.
            running_dist_sum = 0.
            running_count = 0.
            running_count_per_class = torch.zeros(self.model.num_centroids)

            for batch_no, batch_data in enumerate(data_loaders[phase]):
                self.optimizer.zero_grad()
                data_batch, label_batch, speaker_ids = batch_data
                data_batch = data_batch.to(self.device)
                label_batch = label_batch.to(self.device)
                speaker_ids = speaker_ids.to(self.device)
                with torch.set_grad_enabled(phase == 'train'):
                    encoded = self.model.encoder(data_batch).contiguous()
                    quantized, alignment = self.model.quantize(encoded, return_alignment=True)
                    count_per_class = torch.tensor([(alignment == i).sum()
                                                    for i in range(self.model.num_centroids)])
                    running_count_per_class += count_per_class
                    output = self.model.decoder(quantized)
                    predicted_centroids = self.model.centroids[alignment]
                    encoded = encoded.view(-1, encoded.size(-1))

                    new_length = output.size(1)
                    old_length = label_batch.size(1)
                    # Try to correct slight mismatches from down-sampling and up-sampling.
                    # Be careful in case of down-sampling without up-sampling
                    if old_length > new_length:
                        label_batch = label_batch[:, :new_length]
                    elif new_length > old_length:
                        output = output[:, :old_length]

                    distance_loss = criterion['dis_loss'](encoded, predicted_centroids.detach())
                    commitment_loss = criterion['com_loss'](predicted_centroids, encoded.detach())
                    reconstruction_loss = criterion['rec_loss'](output, label_batch)
                    if self.model.use_ma:
                        total_loss = reconstruction_loss + distance_loss
                    else:
                        total_loss = reconstruction_loss + distance_loss + commitment_loss
                    # Not part of the graph, just metrics to be monitored
                    mask = (label_batch != data_loaders[phase].dataset.pad_value).float()
                    numel = 1  # torch.sum(mask).item()
                    running_loss += reconstruction_loss.item()
                    running_dist_sum += distance_loss.item()
                    running_count += numel

                    class0_sum = running_dist_sum / running_count
                    px = running_count_per_class / running_count_per_class.sum()
                    px.clamp_min_(1e-20)
                    entropy = -(px * torch.log2(px)).sum().item()
                if phase == 'train':
                    total_loss.backward()
                    if self.params_dict['gradient_clip']:
                        torch.nn.utils.clip_grad_norm_(self.model.parameters(),
                                                       self.params_dict['gradient_clip'])
                    self.optimizer.step()
                phase_elapse = since(phase_beg)
                eta = int(phase_elapse
                          * (dataset_sizes[phase] // batch_sizes[phase]
                             - batch_no - 1)
                          / (batch_no + 1))
                if self.params_dict['verbose']:
                    print('\r\t{} batch: {}/{} batches - ETA: {}s - loss: {:.4f} - dist: {:.4f} - '
                          'entropy: {:.4f}'.format(phase.title(),
                                                   batch_no + 1,
                                                   dataset_sizes[phase] // batch_sizes[phase] + 1,
                                                   eta, running_loss/running_count,
                                                   class0_sum, entropy
                                                   ), end='')
            epoch_loss = running_loss/running_count
            print(" - loss: {:.4f} - dist: {:.4f} - entropy: {:.4f}".format(epoch_loss, class0_sum,
                                                                            entropy))
            self.loss_history[str(self.elapsed_epochs() - 1)][phase] = (epoch_loss,
                                                                        class0_sum, entropy,
                                                                        running_count)
        print('\tTime: {}s'.format(int(since(epoch_beg))))
        if self.elapsed_epochs() <= self.params_dict['warmup_num_epochs']:
            self.optimizer.param_groups[0]['lr'] /= lr_scale
예제 #2
0
def test_since_second():
    ref = datetime.datetime(2019, 5, 16, 13, 35, 15)
    now = datetime.datetime(2019, 5, 16, 13, 35, 16)
    assert utils.since(now, ref) == '1 second'
예제 #3
0
def test_since_hour_and_minutes_and_seconds():
    ref = datetime.datetime(2019, 5, 16, 13, 35, 15)
    now = datetime.datetime(2019, 5, 16, 14, 37, 21)
    assert utils.since(now, ref) == '1 hour 2 minutes 6 seconds'
예제 #4
0
def test_since_days_hours_and_minutes_and_seconds():
    ref = datetime.datetime(2019, 5, 16, 13, 35, 15)
    now = datetime.datetime(2019, 5, 19, 15, 37, 21)
    assert utils.since(now, ref) == '3 days 2 hours 2 minutes 6 seconds'
예제 #5
0
def test_since_minute_and_seconds():
    ref = datetime.datetime(2019, 5, 16, 13, 35, 15)
    now = datetime.datetime(2019, 5, 16, 13, 36, 21)
    assert utils.since(now, ref) == '1 minute 6 seconds'