Exemple #1
0
    def visualize_attention_weights(self, epoch):
        """
        Visualize attention of the model saved during an epoch
        
        :param epoch: The epoch
        """

        #TODO: Add a node name mapping for easily readable visualization

        nodes = self._args.nodes
        assert len(nodes) == 2
        src, trg = nodes
        utils.log(
            f"Generating attention weight visualization between source = {src} and target = {trg} nodes"
        )
        self._load_best_model(best_epoch=epoch)

        batch = {
            "source_neighborhood": self._neighborhood[src].unsqueeze(0),
            "target_neighborhood": self._neighborhood[trg].unsqueeze(0),
            "source_mask": self._mask[src].unsqueeze(0),
            "target_mask": self._mask[trg].unsqueeze(0),
        }
        self._model(**utils.to(batch, self._device))
        src_mask = self._mask[src] == 0
        trg_mask = self._mask[trg] == 0
        source_atn = self._model.source_atn.squeeze().detach().cpu().numpy(
        )[src_mask]
        target_atn = self._model.target_atn.squeeze().detach().cpu().numpy(
        )[trg_mask]
        source_nbh = batch["source_neighborhood"].squeeze()[src_mask]
        target_nbh = batch["source_neighborhood"].squeeze()[trg_mask]

        params = self._params
        data_dir = osp.join(
            params["root"],
            params["name"]) if "name" in params else params["root"]
        src_path = osp.join(data_dir, "results", f"source_atn_vis_{src}.html")
        trg_path = osp.join(data_dir, "results", f"target_atn_vis_{trg}.html")
        utils.visualize_attention_weights(path=src_path,
                                          neighborhood=source_nbh,
                                          weights=source_atn,
                                          node_id=src)
        utils.visualize_attention_weights(path=trg_path,
                                          neighborhood=target_nbh,
                                          weights=target_atn,
                                          node_id=trg)
Exemple #2
0
    def _fit(self, loader):
        """
        Fits the GOAT model using data from a specified loader
        
        :param loader: The loader
        """
        sources, targets, source_atn, target_atn, source_features, target_features = [], [], [], [], [], []
        for bc, batch in self._test_loader:
            sources.append(batch["source"].cpu().numpy())
            targets.append(batch["target"].cpu().numpy())

            true_source_feature, true_target_feature, _, _ = self._model(
                **utils.to(batch, self._device))

            source_atn.append(
                self._model.source_atn.squeeze().detach().cpu().numpy())
            target_atn.append(
                self._model.target_atn.squeeze().detach().cpu().numpy())
            source_features.append(true_source_feature.detach().cpu().numpy())
            target_features.append(true_target_feature.detach().cpu().numpy())

        sources = np.concatenate(sources)
        targets = np.concatenate(targets)
        source_atn = np.concatenate([
            utils.expand_if(atn_v, 0,
                            len(atn_v.shape) == 1) for atn_v in source_atn
        ])
        target_atn = np.concatenate([
            utils.expand_if(atn_v, 0,
                            len(atn_v.shape) == 1) for atn_v in target_atn
        ])
        true_source_feature = np.concatenate([
            utils.expand_if(f, 0,
                            len(f.shape) == 1) for f in source_features
        ])
        true_target_feature = np.concatenate([
            utils.expand_if(f, 0,
                            len(f.shape) == 1) for f in target_features
        ])

        return sources, targets, source_atn, target_atn, true_source_feature, true_target_feature
Exemple #3
0
    def _fit_false_pairs(self, num_false_samples=None):
        """
        Inference using false pairs. Useful for validating and testing the quality of link prediction.
        
        :param num_false_samples: The number of false pairs.
        """
        if num_false_samples:
            false_pairs = self._negative_pairs[:num_false_samples]
        else:
            false_pairs = self._negative_pairs
            num_false_samples = false_pairs.shape[0]

        source_features, target_features = [], []
        batch_size = self._args.batch
        for i in range(0, num_false_samples, batch_size):
            end = i + batch_size if num_false_samples - batch_size > i else num_false_samples
            false_data = {
                "source_neighborhood":
                self._neighborhood[self._negative_pairs[i:end, 0]],
                "target_neighborhood":
                self._neighborhood[self._negative_pairs[i:end, 1]],
                "source_mask":
                self._mask[self._negative_pairs[i:end, 0]],
                "target_mask":
                self._mask[self._negative_pairs[i:end, 1]],
            }
            false_source_feature, false_target_feature, _, _ = self._model(
                **utils.to(false_data, self._device))
            source_features.append(false_source_feature.detach().cpu().numpy())
            target_features.append(false_target_feature.detach().cpu().numpy())

        false_source_feature = np.concatenate([
            utils.expand_if(f, 0,
                            len(f.shape) == 1) for f in source_features
        ])
        false_target_feature = np.concatenate([
            utils.expand_if(f, 0,
                            len(f.shape) == 1) for f in target_features
        ])
        return false_source_feature, false_target_feature
Exemple #4
0
# Higher level interface for interacting with specific classes of events
import pyalm as alm
import cleanup
from utils import dictmapper, MappingRule as to

ContributorBase = dictmapper(
    'ContributorBase', {
        'contributor_role': ['contributor_role'],
        'first_author': to(['first_author'], cleanup._text_to_bool),
        'given_name': ['given_name'],
        'sequence': ['sequence'],
        'surname': ['surname']
    })


class Contributor(ContributorBase):
    def __repr__(self):
        return '<%s: %s%s>' % (type(self).__name__, self.given_name,
                               self.surname)


CrossrefBase = dictmapper(
    'CrossrefBase', {
        'article_title': ['event', 'article_title'],
        'doi': ['event', 'doi'],
        'fl_count':
        to(['event', 'fl_count'], cleanup._parse_numbers_to_int),
        'issn': ['event', 'issn'],
        'journal_abbreviation': ['event', 'journal_abbreviation'],
        'journal_title': ['event', 'journal_title'],
        'publication_type': ['event', 'publication_type'],
Exemple #5
0
import requests
from utils import dictmapper, MappingRule as to
import cleanup
import config

BASE_HEADERS = {'Accept': 'application/json'}

MetricsBase = dictmapper(
    'MetricsBase', {
        'citations': to(['citations'], cleanup._parse_numbers_to_int),
        'comments': to(['comments'], cleanup._parse_numbers_to_int),
        'html': to(['html'], cleanup._parse_numbers_to_int),
        'likes': to(['likes'], cleanup._parse_numbers_to_int),
        'pdf': to(['pdf'], cleanup._parse_numbers_to_int),
        'readers': to(['readers'], cleanup._parse_numbers_to_int),
        'shares': to(['shares'], cleanup._parse_numbers_to_int),
        'total': to(['total'], cleanup._parse_numbers_to_int)
    })


class Metrics(MetricsBase):
    def __repr__(self):
        return """
<%s total:%s readers:%s pdf:%s html:%s comments:%s likes:%s>
""" % (type(self).__name__, self.total, self.readers, self.pdf, self.html,
        self.comments, self.likes)


SourceBase = dictmapper(
    'SourceBase', {
        'name': ['name'],
Exemple #6
0
# Higher level interface for interacting with specific classes of events
import pyalm as alm
import cleanup
from utils import dictmapper, MappingRule as to

ContributorBase = dictmapper('ContributorBase',
                              {
                               'contributor_role' : ['contributor_role'],
                               'first_author': to(['first_author'],
                                                    cleanup._text_to_bool),
                               'given_name': ['given_name'],
                               'sequence': ['sequence'],
                               'surname': ['surname']
                              }
                            )

class Contributor(ContributorBase):
    def __repr__(self):
        return '<%s: %s%s>' % (type(self).__name__, self.given_name, self.surname)


CrossrefBase = dictmapper('CrossrefBase',
                            {
                             'article_title' : ['event','article_title'],
                             'doi' : ['event','doi'],
                             'fl_count' : to(['event','fl_count'],
                                        cleanup._parse_numbers_to_int),
                             'issn' : ['event','issn'],
                             'journal_abbreviation' : ['event','journal_abbreviation'],
                             'journal_title' : ['event','journal_title'],
                             'publication_type' : ['event','publication_type'],
Exemple #7
0
import requests
from utils import dictmapper, MappingRule as to
import cleanup
import config

BASE_HEADERS = {'Accept': 'application/json'}

MetricsBase = dictmapper('MetricsBase',
                         {'citations': to(['citations'],
                                          cleanup._parse_numbers_to_int),
                          'comments': to(['comments'],
                                         cleanup._parse_numbers_to_int),
                          'html': to(['html'],
                                       cleanup._parse_numbers_to_int),
                          'likes': to(['likes'],
                                      cleanup._parse_numbers_to_int),
                          'pdf': to(['pdf'],
                                    cleanup._parse_numbers_to_int),
                          'readers': to(['readers'],
                                    cleanup._parse_numbers_to_int),
                          'shares': to(['shares'],
                                       cleanup._parse_numbers_to_int),
                          'total': to(['total'],
                                      cleanup._parse_numbers_to_int)
                         }
)


class Metrics(MetricsBase):
    def __repr__(self):
        return """
Exemple #8
0
# Higher level interface for interacting with specific classes of events
import pyalm as alm
import cleanup
from utils import dictmapper, MappingRule as to

ContributorBase = dictmapper('ContributorBase',
                              {
                               'contributor_role' : ['contributor_role'],
                               'first_author': to(['first_author'],
                                                    cleanup._text_to_bool),
                               'given_name': ['given_name'],
                               'sequence': ['sequence'],
                               'surname': ['surname']
                              }
                            )

class Contributor(ContributorBase):
    def __repr__(self):
        return '<%s: %s%s>' % (type(self).__name__, self.given_name, self.surname)


CitationBase = dictmapper('CitationBase',
                            {
                             'article_title' : ['event','article_title'],
                             'doi' : ['event','doi'],
                             'fl_count' : to(['event','fl_count'],
                                        cleanup._parse_numbers_to_int),
                             'issn' : ['event','issn'],
                             'journal_abbreviation' : ['event','journal_abbreviation'],
                             'journal_title' : ['event','journal_title'],
                             'publication_type' : ['event','publication_type'],
Exemple #9
0
import requests
from utils import dictmapper, MappingRule as to
import cleanup
import config

BASE_HEADERS = {'Accept': 'application/json'}

MetricsBase = dictmapper('MetricsBase',
                         {'citations': to(['citations'],
                                          cleanup._parse_numbers_to_int),
                          'comments': to(['comments'],
                                         cleanup._parse_numbers_to_int),
                          'groups': to(['groups'],
                                       cleanup._parse_numbers_to_int),
                          'likes': to(['likes'],
                                      cleanup._parse_numbers_to_int),
                          'pdf': to(['pdf'],
                                    cleanup._parse_numbers_to_int),
                          'shares': to(['shares'],
                                       cleanup._parse_numbers_to_int),
                          'total': to(['total'],
                                      cleanup._parse_numbers_to_int)
                         }
)


class Metrics(MetricsBase):
    def __repr__(self):
        return """
<%s total:%s shares:%s citations:%s comments:%s>
""" % (type(self).__name__, self.total, self.shares, self.citations, self.comments)
Exemple #10
0
    def fit(self, trainloader, validloader, num_epochs=1000):        

        # . . logs
        logs = {}

        # . . number of batches
        num_train_batch = len(trainloader)
        num_valid_batch = len(validloader)

        # . . register num batches to logs
        logs['num_train_batch'] = num_train_batch
        logs['num_valid_batch'] = num_valid_batch

        # . . 
        # . . set the callback handler
        callback_handler = CallbackHandler(self.callbacks)

        # . . keep track of the losses        
        train_losses = []
        valid_losses = []


        # . . call the callback function on_train_begin(): load the best model
        callback_handler.on_train_begin(logs=logs, model=self.model)

        for epoch in range(num_epochs):
            #scheduler.step()
            train_loss = 0.
            valid_loss = 0.
          
            # . . activate the training mode
            self.model.train()

            # . . get the next batch of training data
            for batch, (center, left, right) in enumerate(trainloader):                                

                # . . the training loss for the current batch
                batch_loss = 0.

                # . . send the batch to GPU
                center, left, right = utils.to(center, self.device), utils.to(left, self.device), utils.to(right, self.device)                

                # . . zero the parameter gradients
                self.optimizer.zero_grad()

                # . . iterate over cameras
                cameras = [center, left, right]                
                for camera in cameras:
                    image, steering = camera
                    
                    # . . feed-forward network to predict the steering angle
                    angle = self.model(image)

                    #log_angle = torch.log10(1.0 + angle)

                    # . . calculate the loss function
                    loss = self.criterion(angle, steering.unsqueeze(1))

                    # . . backpropagate the loss
                    #loss.backward()
                    # . . backpropogate the scaled physics loss
                    with amp.scale_loss(loss, self.optimizer) as scaled_loss:
                        scaled_loss.backward()

                    # . . update weights
                    self.optimizer.step()
                    
                    # . . training loss for the current batch: accumulate over cameras
                    batch_loss += loss.item()

                    # . . accumulate the training loss
                    train_loss += loss.item()

                # . . register the batch training loss
                logs['batch_loss'] = batch_loss

                # . . call the callback functions on_epoch_end()                
                callback_handler.on_batch_end(batch, logs=logs, model=self.model)

            # . . activate the evaluation (validation) mode
            self.model.eval()
            # . . turn off the gradient for performance
            with torch.set_grad_enabled(False):
                # . . get the next batch of validation data
                for batch, (center, left, right) in enumerate(validloader): 

                    # . . send the batch to GPU
                    center, left, right = utils.to(center, self.device), utils.to(left, self.device), utils.to(right, self.device)                    
                
                    # . . iterate over cameras
                    cameras = [center, left, right]
                    for camera in cameras:
                        image, steering = camera

                        # . . feed-forward network to predict the steering angle
                        angle = self.model(image)

                        # . . calculate the loss function
                        loss = self.criterion(angle, steering.unsqueeze(1))                

                        # . . accumulate the training loss
                        valid_loss += loss.item()

            # . . normalize the training and validation losses
            train_loss /= (num_train_batch*3)
            valid_loss /= (num_valid_batch*3)

            # . . on epoch end
            train_losses.append(train_loss)
            valid_losses.append(valid_loss)

            # . . update the epoch statistics (logs)
            logs["train_loss"] = train_loss
            logs["valid_loss"] = valid_loss

            # . . call the callback functions on_epoch_end()                
            callback_handler.on_epoch_end(epoch, logs=logs, model=self.model)
    
            # . . check if the training should continue
            if self.model._stop_training:
                break

        # . . call the callback function on_train_end(): load the best model
        callback_handler.on_train_end(logs=logs, model=self.model)

        return train_losses, valid_losses