Esempio n. 1
0
    def validation(self,
                   dataloader,
                   use_cuda,
                   verbose=True,
                   prob=1.0,
                   accuracy=False,
                   parameters=None):
        """
        Compute the avaraged loss per event of a generalized Hawkes process
        given observed sequences and current model
        :param dataloader: a pytorch batch-based data loader
        :param use_cuda: use cuda (true) or not (false)
        """
        device = torch.device('cuda:0' if use_cuda else 'cpu')
        self.lambda_model_validation.to(device)
        self.lambda_model_validation.eval()

        Cs = torch.LongTensor(
            list(range(len(dataloader.dataset.database['type2idx']))))
        Cs = Cs.view(-1, 1)
        Cs = Cs.to(device)

        if dataloader.dataset.database['event_features'] is not None:
            all_event_feature = torch.from_numpy(
                dataloader.dataset.database['event_features'])
            FCs = all_event_feature.type(torch.FloatTensor)
            FCs = torch.t(FCs)  # (num_type, dim_features)
            FCs = FCs.to(device)
        else:
            FCs = None
        if not accuracy:
            start = time.time()
            loss = 0
            prob = np.array([prob])
            prob_tensor = torch.from_numpy(prob).type(torch.FloatTensor)
            with torch.no_grad():
                for batch_idx, samples in enumerate(dataloader):
                    ci, batch_dict = samples2dict(samples, device, Cs, FCs)
                    lambda_t, Lambda_t = self.lambda_model_validation(
                        batch_dict)
                    lambda_t /= prob_tensor
                    Lambda_t /= prob_tensor
                    loss += self.loss_function(lambda_t, Lambda_t, ci)

                    # display training processes
                    if verbose:
                        if batch_idx % 100 == 0:
                            logger.info(
                                'Validation [{}/{} ({:.0f}%)]\t Time={:.2f}sec.'
                                .format(batch_idx * ci.size(0),
                                        len(dataloader.dataset),
                                        100. * batch_idx / len(dataloader),
                                        time.time() - start))
            return loss / len(dataloader.dataset)
        else:
            with torch.no_grad():
                loss = np.linalg.norm(
                    list(self.lambda_model_validation.parameters())
                    [1].data.numpy() - parameters) / self.num_type**2
            return loss
Esempio n. 2
0
    def validation(self, dataloader, use_cuda):
        """
        Compute the avaraged loss per event of a generalized Hawkes process given observed sequences and current model
        :param dataloader: a pytorch batch-based data loader
        :param use_cuda: use cuda (true) or not (false)
        """
        device = torch.device('cuda:0' if use_cuda else 'cpu')
        self.lambda_model.to(device)
        self.lambda_model.eval()

        Cs = torch.LongTensor(
            list(range(len(dataloader.dataset.database['type2idx']))))
        Cs = Cs.view(-1, 1)
        Cs = Cs.to(device)

        if dataloader.dataset.database['event_features'] is not None:
            all_event_feature = torch.from_numpy(
                dataloader.dataset.database['event_features'])
            FCs = all_event_feature.type(torch.FloatTensor)
            FCs = torch.t(FCs)  # (num_type, dim_features)
            FCs = FCs.to(device)
        else:
            FCs = None

        start = time.time()
        loss = 0
        for batch_idx, samples in enumerate(dataloader):
            ci, batch_dict = samples2dict(samples, device, Cs, FCs)
            loss = 0
            for m in range(self.num_cluster):
                weight = self.responsibility[batch_dict['sn'][:, 0],
                                             m]  # (batch_size, )
                lambda_t, Lambda_t = self.lambda_model[m](batch_dict)
                loss_m = self.loss_function(lambda_t, Lambda_t,
                                            ci)  # (batch_size, )
                loss += (weight * loss_m).sum() / loss_m.size(0)

            # display training processes
            if batch_idx % 100 == 0:
                logger.info(
                    'Validation [{}/{} ({:.0f}%)]\t Time={:.2f}sec.'.format(
                        batch_idx * ci.size(0), len(dataloader.dataset),
                        100. * batch_idx / len(dataloader),
                        time.time() - start))
        return loss / len(dataloader.dataset)
Esempio n. 3
0
    def fit_ot(self, dataloader, optimizer, epochs: int,
               trans: torch.Tensor, mu_t: torch.Tensor, A_t: torch.Tensor, p_s: torch.Tensor, p_t: torch.Tensor,
               sample_dict1, sample_dict2, gamma, alpha,
               scheduler=None, sparsity: float=None, nonnegative=None,
               use_cuda: bool=False, validation_set=None):
        """
        Learn parameters of a generalized Hawkes process given observed sequences
        :param dataloader: a pytorch batch-based data loader
        :param optimizer: the sgd optimization method defined by PyTorch
        :param epochs: the number of training epochs
        :param trans: fixed optimal transport
        :param mu_t: base intensity of target Hawkes process
        :param A_t: infectivity of target Hawkes process
        :param p_s: the distribution of event types in source Hawkes process
        :param p_t: the distribution of event types in target Hawkes process
        :param scheduler: the method adjusting the learning rate of SGD defined by PyTorch
        :param sparsity: None or a float weight of L1 regularizer
        :param nonnegative: None or a float lower bound, typically the lower bound = 0
        :param use_cuda: use cuda (true) or not (false)
        :param validation_set: None or a validation dataloader
        """
        device = torch.device('cuda:0' if use_cuda else 'cpu')
        self.lambda_model.to(device)
        best_model = None
        self.lambda_model.train()

        if nonnegative is not None:
            clipper = LowerBoundClipper(nonnegative)

        Cs = torch.LongTensor(list(range(len(dataloader.dataset.database['type2idx']))))
        Cs = Cs.view(-1, 1)
        Cs = Cs.to(device)

        if dataloader.dataset.database['event_features'] is not None:
            all_event_feature = torch.from_numpy(dataloader.dataset.database['event_features'])
            FCs = all_event_feature.type(torch.FloatTensor)
            FCs = torch.t(FCs)    # (num_type, dim_features)
            FCs = FCs.to(device)
        else:
            FCs = None

        if validation_set is not None:
            validation_loss = self.validation(validation_set, use_cuda)
            logger.info('In the beginning, validation loss per event: {:.6f}.\n'.format(validation_loss))
            best_loss = validation_loss
        else:
            best_loss = np.inf

        for epoch in range(epochs):
            if scheduler is not None:
                scheduler.step()
            start = time.time()
            for batch_idx, samples in enumerate(dataloader):
                ci, batch_dict = samples2dict(samples, device, Cs, FCs)
                optimizer.zero_grad()
                lambda_t, Lambda_t = self.lambda_model(batch_dict)
                loss = self.loss_function(lambda_t, Lambda_t, ci) / lambda_t.size(0)
                reg = 0
                if sparsity is not None:
                    for parameter in self.lambda_model.parameters():
                        reg += sparsity * torch.sum(torch.abs(parameter))

                base_intensity = self.lambda_model.exogenous_intensity.intensity(sample_dict1)
                infectivity = self.lambda_model.endogenous_intensity.granger_causality(sample_dict2).squeeze(2)
                d_gw = self.dgw(infectivity, A_t, trans, p_s, p_t)
                d_w = self.dw(base_intensity, mu_t, trans, p_s, p_t)
                loss_total = loss + reg + gamma * (alpha*d_w + (1-alpha)*d_gw)
                loss_total.backward()
                optimizer.step()
                if nonnegative is not None:
                    self.lambda_model.apply(clipper)

                # display training processes
                if batch_idx % 100 == 0:
                    logger.info('Train Epoch: {} [{}/{} ({:.0f}%)]'.format(
                        epoch, batch_idx * ci.size(0), len(dataloader.dataset), 100. * batch_idx / len(dataloader)))
                    if sparsity is not None:
                        logger.info('Loss per event: {:.6f}, Regularizer: {:.6f} Time={:.2f}sec'.format(
                            loss.data, reg.data, time.time() - start))
                    else:
                        logger.info('Loss per event: {:.6f}, Regularizer: {:.6f} Time={:.2f}sec'.format(
                            loss.data, 0, time.time() - start))

            if validation_set is not None:
                validation_loss = self.validation(validation_set, use_cuda)
                logger.info('After Epoch: {}, validation loss per event: {:.6f}.\n'.format(epoch, validation_loss))
                if validation_loss < best_loss:
                    best_model = copy.deepcopy(self.lambda_model)
                    best_loss = validation_loss

        if best_model is not None:
            self.lambda_model = copy.deepcopy(best_model)
Esempio n. 4
0
    def fit(self,
            dataloader,
            optimizer,
            epochs: int,
            scheduler=None,
            sparsity: float = None,
            nonnegative=None,
            use_cuda: bool = False,
            validation_set=None,
            verbose=True,
            prob: float = 1.0,
            accuracy=False,
            parameters=None):
        """
        Learn parameters of a generalized Hawkes process given observed sequences
        :param dataloader: a pytorch batch-based data loader
        :param optimizer: the sgd optimization method defined by PyTorch
        :param epochs: the number of training epochs
        :param scheduler: the method adjusting the learning rate of SGD defined by PyTorch
        :param sparsity: None or a float weight of L1 regularizer
        :param nonnegative: None or a float lower bound, typically the lower bound = 0
        :param use_cuda: use cuda (true) or not (false)
        :param validation_set: None or a validation dataloader
        """
        device = torch.device('cuda:0' if use_cuda else 'cpu')
        self.lambda_model.to(device)
        best_model = None
        self.lambda_model.train()
        self.mu_path.append(
            copy.deepcopy(list(self.lambda_model.parameters())[0].data))
        self.alpha_path.append(
            copy.deepcopy(list(self.lambda_model.parameters())[1].data))

        if nonnegative is not None:
            clipper = LowerBoundClipper(nonnegative)

        Cs = torch.LongTensor(
            list(range(len(dataloader.dataset.database['type2idx']))))
        Cs = Cs.view(-1, 1)
        Cs = Cs.to(device)

        if dataloader.dataset.database['event_features'] is not None:
            all_event_feature = torch.from_numpy(
                dataloader.dataset.database['event_features'])
            FCs = all_event_feature.type(torch.FloatTensor)
            FCs = torch.t(FCs)  # (num_type, dim_features)
            FCs = FCs.to(device)
        else:
            FCs = None

        if validation_set is not None:
            validation_loss = self.validation(validation_set, use_cuda,
                                              verbose, prob, accuracy,
                                              parameters)
            logger.info(
                'In the beginning, validation loss per event: {:.6f}.\n'.
                format(validation_loss))
            best_loss = validation_loss
            self.learning_path.append(validation_loss)
        else:
            best_loss = np.inf

        start0 = time.time()

        self.training_time.append(time.time() - start0)
        for epoch in range(epochs):
            if scheduler is not None:
                scheduler.step()
            start = time.time()

            for batch_idx, samples in enumerate(dataloader):
                ci, batch_dict = samples2dict(samples, device, Cs, FCs)
                optimizer.zero_grad()
                lambda_t, Lambda_t = self.lambda_model(batch_dict)
                loss = self.loss_function(lambda_t, Lambda_t,
                                          ci) / lambda_t.size(0)
                reg = 0
                if sparsity is not None:
                    for parameter in self.lambda_model.parameters():
                        reg += sparsity * torch.sum(torch.abs(parameter))
                loss_total = loss + reg
                loss_total.backward()
                optimizer.step()
                if nonnegative is not None:
                    self.lambda_model.apply(clipper)

                if validation_set is not None:
                    validation_loss = self.validation(validation_set, use_cuda,
                                                      verbose, prob, accuracy,
                                                      parameters)
                    if verbose:
                        logger.info(
                            'After Epoch: {}, validation loss per event: {:.6f}.\n'
                            .format(epoch, validation_loss))
                    if validation_loss < best_loss:
                        best_model = copy.deepcopy(self.lambda_model)
                        best_loss = validation_loss

                esti_loss = loss_total.data

                # display training processes
                if verbose:
                    if batch_idx % 100 == 0:
                        logger.info('Train Epoch: {} [{}/{} ({:.0f}%)]'.format(
                            epoch, batch_idx * ci.size(0),
                            len(dataloader.dataset),
                            100. * batch_idx / len(dataloader)))
                        if sparsity is not None:
                            logger.info(
                                'Loss per event: {:.3f}, Regularizer: {:.3f}, Validate Loss: {:.3f}, Time={:.2f}sec'
                                .format(esti_loss.data, reg.data,
                                        validation_loss,
                                        time.time() - start))
                        else:
                            logger.info(
                                'Loss per event: {:.3f}, Regularizer: {:.3f}, Loss: {:.6f}, Time={:.2f}sec'
                                .format(esti_loss.data, 0, validation_loss,
                                        time.time() - start))

                self.learning_path.append(loss_total)
                self.validation_path.append(validation_loss)
                self.training_time.append(time.time() - start0)
                self.mu_path.append(
                    copy.deepcopy(
                        list(self.lambda_model.parameters())[0].data))
                self.alpha_path.append(
                    copy.deepcopy(
                        list(self.lambda_model.parameters())[1].data))
                self.lambda_path.append(lambda_t)
                self.Lambda_path.append(Lambda_t)

            logger.info(
                'Epoch : {}/{}, Used time: {: .2f} min, Estimated Time to finish: {: .2f} min, train loss: {: .3f}, validation loss: {: .3f}'
                .format((epoch + 1), epochs, self.training_time[-1] / 60,
                        self.training_time[-1] / 60 / (epoch + 1) *
                        (epochs - epoch - 1), loss_total, validation_loss))

        if best_model is not None:
            self.lambda_model = copy.deepcopy(best_model)
Esempio n. 5
0
    def fit(self,
            dataloader,
            optimizer,
            epochs: int,
            scheduler=None,
            sparsity: float = None,
            nonnegative=None,
            use_cuda: bool = False,
            validation_set=None,
            track_diagnostics=False):
        """
        Learn parameters of a generalized Hawkes process given observed sequences
        :param dataloader: a pytorch batch-based data loader
        :param optimizer: the sgd optimization method defined by PyTorch
        :param epochs: the number of training epochs
        :param scheduler: the method adjusting the learning rate of SGD defined by PyTorch
        :param sparsity: None or a float weight of L1 regularizer
        :param nonnegative: None or a float lower bound, typically the lower bound = 0
        :param use_cuda: use cuda (true) or not (false)
        :param validation_set: None or a validation dataloader
        :param track_diagnostics: Set to True to return historical loss values and weights.
        """
        device = torch.device('cuda:0' if use_cuda else 'cpu')
        self.lambda_model.to(device)
        best_model = None
        self.lambda_model.train()

        if nonnegative is not None:
            clipper = LowerBoundClipper(nonnegative)

        Cs = torch.LongTensor(
            list(range(len(dataloader.dataset.database['type2idx']))))
        Cs = Cs.view(-1, 1)
        Cs = Cs.to(device)

        if dataloader.dataset.database['event_features'] is not None:
            all_event_feature = torch.from_numpy(
                dataloader.dataset.database['event_features'])
            FCs = all_event_feature.type(torch.FloatTensor)
            FCs = torch.t(FCs)  # (num_type, dim_features)
            FCs = FCs.to(device)
        else:
            FCs = None

        if validation_set is not None:
            validation_loss = self.validation(validation_set, use_cuda)
            logger.info(
                'In the beginning, validation loss per event: {:.6f}.\n'.
                format(validation_loss))
            best_loss = validation_loss
        else:
            best_loss = np.inf

        if track_diagnostics:
            self.diagnostics = Diagnostics()

        for epoch in range(epochs):
            if scheduler is not None:
                scheduler.step()
            start = time.time()
            for batch_idx, samples in enumerate(dataloader):
                ci, batch_dict = samples2dict(samples, device, Cs, FCs)
                optimizer.zero_grad()
                lambda_t, Lambda_t = self.lambda_model(batch_dict)
                loss = self.loss_function(lambda_t, Lambda_t,
                                          ci) / lambda_t.size(0)
                reg = 0
                if sparsity is not None:
                    for parameter in self.lambda_model.parameters():
                        reg += sparsity * torch.sum(torch.abs(parameter))
                loss_total = loss + reg
                loss_total.backward()
                optimizer.step()
                if nonnegative is not None:
                    self.lambda_model.apply(clipper)

                if track_diagnostics:
                    self.diagnostics.loss.append(loss.data.item())
                    self.diagnostics.mu.append(
                        self.lambda_model.exogenous_intensity.emb.weight.
                        squeeze().tolist())
                    self.diagnostics.alpha.append(
                        self.lambda_model.endogenous_intensity.basis[0].weight.
                        squeeze().tolist())

                # display training processes
                if batch_idx % 100 == 0:
                    logger.info('Train Epoch: {} [{}/{} ({:.0f}%)]'.format(
                        epoch, batch_idx * ci.size(0), len(dataloader.dataset),
                        100. * batch_idx / len(dataloader)))
                    if sparsity is not None:
                        logger.info(
                            'Loss per event: {:.6f}, Regularizer: {:.6f} Time={:.2f}sec'
                            .format(loss.data, reg.data,
                                    time.time() - start))
                    else:
                        logger.info(
                            'Loss per event: {:.6f}, Regularizer: {:.6f} Time={:.2f}sec'
                            .format(loss.data, 0,
                                    time.time() - start))

            if validation_set is not None:
                validation_loss = self.validation(validation_set, use_cuda)
                logger.info(
                    'After Epoch: {}, validation loss per event: {:.6f}.\n'.
                    format(epoch, validation_loss))
                if validation_loss < best_loss:
                    best_model = copy.deepcopy(self.lambda_model)
                    best_loss = validation_loss

        if best_model is not None:
            self.lambda_model = copy.deepcopy(best_model)
Esempio n. 6
0
    def fit(self,
            dataloader,
            optimizer,
            epochs: int,
            scheduler=None,
            sparsity: float = None,
            nonnegative=None,
            use_cuda: bool = False,
            validation_set=None):
        """
        Learn parameters of a generalized Hawkes process given observed sequences
        :param dataloader: a pytorch batch-based data loader
        :param optimizer: the sgd optimization method
        :param epochs: the number of training epochs
        :param scheduler: the method adjusting the learning rate of SGD
        :param sparsity: None or a float weight of L1 regularizer
        :param nonnegative: None or a float lower bound
        :param use_cuda: use cuda (true) or not (false)
        :param validation_set: None or a validation dataloader
        """
        device = torch.device('cuda:0' if use_cuda else 'cpu')
        self.lambda_model.to(device)
        self.responsibility = self.responsibility.to(device)
        self.prob_cluster = self.prob_cluster.to(device)
        best_model = None
        self.lambda_model.train()

        if nonnegative is not None:
            clipper = LowerBoundClipper(nonnegative)

        Cs = torch.LongTensor(
            list(range(len(dataloader.dataset.database['type2idx']))))
        Cs = Cs.view(-1, 1)
        Cs = Cs.to(device)

        if dataloader.dataset.database['event_features'] is not None:
            all_event_feature = torch.from_numpy(
                dataloader.dataset.database['event_features'])
            FCs = all_event_feature.type(torch.FloatTensor)
            FCs = torch.t(FCs)  # (num_type, dim_features)
            FCs = FCs.to(device)
        else:
            FCs = None

        if validation_set is not None:
            validation_loss = self.validation(validation_set, use_cuda)
            logger.info(
                'In the beginning, validation loss per event: {:.6f}.\n'.
                format(validation_loss))
            best_loss = validation_loss
        else:
            best_loss = np.inf

        # EM algorithm
        for epoch in range(epochs):
            if scheduler is not None:
                scheduler.step()
            start = time.time()

            log_weight = self.prob_cluster.log().view(1,
                                                      self.num_cluster).repeat(
                                                          self.num_sequence, 1)
            log_responsibility = 0 * self.responsibility
            num_responsibllity = 0 * self.responsibility
            log_responsibility = log_responsibility.to(device)
            num_responsibllity = num_responsibllity.to(device)
            for batch_idx, samples in enumerate(dataloader):
                ci, batch_dict = samples2dict(samples, device, Cs, FCs)
                optimizer.zero_grad()
                loss = 0
                for m in range(self.num_cluster):
                    weight = self.responsibility[batch_dict['sn'][:, 0],
                                                 m]  # (batch_size, )
                    lambda_t, Lambda_t = self.lambda_model[m](batch_dict)
                    loss_m = self.loss_function(lambda_t, Lambda_t,
                                                ci)  # (batch_size, )
                    loss += (weight * loss_m).sum() / loss_m.size(0)
                    for i in range(loss_m.size(0)):
                        sn = batch_dict['sn'][i, 0]
                        log_responsibility[sn, m] += loss_m.data[i]
                        num_responsibllity[sn, m] += 1

                reg = 0
                if sparsity is not None:
                    for parameter in self.lambda_model.parameters():
                        reg += sparsity * torch.sum(torch.abs(parameter))
                loss_total = loss + reg
                loss_total.backward()
                optimizer.step()
                if nonnegative is not None:
                    self.lambda_model.apply(clipper)

                # display training processes
                if batch_idx % 100 == 0:
                    logger.info('Train Epoch: {} [{}/{} ({:.0f}%)]'.format(
                        epoch, batch_idx * ci.size(0), len(dataloader.dataset),
                        100. * batch_idx / len(dataloader)))
                    if sparsity is not None:
                        logger.info(
                            'Loss per event: {:.6f}, Regularizer: {:.6f} Time={:.2f}sec'
                            .format(loss.data, reg.data,
                                    time.time() - start))
                    else:
                        logger.info(
                            'Loss per event: {:.6f}, Regularizer: {:.6f} Time={:.2f}sec'
                            .format(loss.data, 0,
                                    time.time() - start))
                    logger.info('Distribution of clusters')
                    for m in range(self.num_cluster):
                        logger.info('Cluster {}, prob={:.6f}'.format(
                            m, self.prob_cluster[m]))

            # update responsibility
            log_responsibility /= (num_responsibllity + 1e-7)
            self.responsibility = F.softmax(log_responsibility + log_weight,
                                            dim=1)
            self.prob_cluster = self.responsibility.sum(0)
            self.prob_cluster = self.prob_cluster / self.prob_cluster.sum()

            if validation_set is not None:
                validation_loss = self.validation(validation_set, use_cuda)
                logger.info(
                    'After Epoch: {}, validation loss per event: {:.6f}.\n'.
                    format(epoch, validation_loss))
                if validation_loss < best_loss:
                    best_model = copy.deepcopy(self.lambda_model)
                    best_loss = validation_loss

        if best_model is not None:
            self.lambda_model = copy.deepcopy(best_model)