def test_iloc(self):
     torch.manual_seed(123)
     a = [torch.randn((i, j)) for i, j in [(5, 3), (5, 2)]]
     a = tuplefy(a, torch.randint(10, (5, )))
     b = tuplefy((a[0][0][:2], a[0][1][:2]), a[1][:2])
     a = a.iloc[:2]
     assert_tupletree_equal(a, b)
Exemple #2
0
 def _to_device(self, data) -> TupleTree:
     """Move `data` to self.device.
     If `data` is a tensor, it will be returned as a `TupleTree`.
     """
     if data is None:
         return tuplefy(data)
     return tuplefy(data).to_device(self.device)
 def test_stack_shapes(self):
     torch.manual_seed(123)
     a = [torch.randn((i, j)) for i, j in [(5, 3), (5, 2)]]
     a = tuplefy(a, torch.randint(10, (5, )))
     b = tuplefy((torch.Size([3, 5, 3]), torch.Size([3, 5, 2])),
                 torch.Size([3, 5]))
     assert_tupletree_equal(a.repeat(3).stack().shapes(), b)
def test_make_data_loader_sorted(batch_size, num_workers):
    torch.manual_seed(123)
    a = tuplefy(torch.randn(10, 3), torch.randn(10))
    dl = make_dataloader(a, batch_size, False, num_workers)
    b = tuplefy()
    for inp, tar in dl:
        b = b + tuplefy(inp, tar).add_root()
    assert_tupletree_equal(b.cat(), a)
Exemple #5
0
def test_dataloader_input_only():
    n = 10
    input = tuplefy(torch.randn(n, 3), torch.randn(n, 2))
    target = torch.randn(n)
    dl = tuplefy(input, target).make_dataloader(4, False)
    dl_input = dataloader_input_only(dl)
    for (inp, tar), inp2 in zip(dl, dl_input):
        assert_tupletree_equal(inp, inp2)
def test_make_data_loader_unsorted(batch_size, num_workers):
    torch.manual_seed(123)
    a = tuplefy(torch.randn(10, 3), torch.randn(10))
    dl = make_dataloader(a, batch_size, True, num_workers)
    b = tuplefy()
    for inp, tar in dl:
        b = b + tuplefy(inp, tar).add_root()
    b = b.cat()
    assert_tupletree_equal(b.shapes(), a.shapes())
    assert (tuplefy(a, b).apply(sum).zip_leaf().apply(
        lambda x: x[0] - x[1]).apply(lambda x: x.max()).pipe(max) < 1e-6)
Exemple #7
0
 def _to_device(self, data):
     """Move data to self.device.
     
     Arguments:
         data {tensor or tuple} -- Data
     
     Returns:
         tensor or tuple -- Data moved to device.
     """
     if data is None:
         return tuplefy(data)
     return tuplefy(data).to_device(self.device)
Exemple #8
0
    def _predict_func_dl(self,
                         func,
                         dataloader,
                         numpy=False,
                         eval_=True,
                         grads=False,
                         to_cpu=False):
        """Get predictions from `dataloader`.
        `func` can be anything and is not concatenated to `self.net` or `self.net.predict`.
        This is different from `predict` and `predict_net` which both use call `self.net`.
        """
        if hasattr(self, "fit_info") and (self.make_dataloader is
                                          self.make_dataloader_predict):
            data = _get_element_in_dataloader(dataloader)
            if data is not None:
                input = tuplefy(data)
                input_train = self.fit_info.get("input")
                if input_train is not None:
                    if input.to_levels() != input_train.get("levels"):
                        warnings.warn(
                            """The input from the dataloader is different from
                        the 'input' during trainig. Make sure to remove 'target' from dataloader.
                        Can be done with 'torchtuples.data.dataloader_input_only'."""
                        )
                    if input.shapes().apply(
                            lambda x: x[1:]) != input_train.get("shapes"):
                        warnings.warn(
                            """The input from the dataloader is different from
                        the 'input' during trainig. The shapes are different."""
                        )

        if eval_:
            self.net.eval()
        with torch.set_grad_enabled(grads):
            preds = []
            for input in dataloader:
                input = tuplefy(input).to_device(self.device)
                preds_batch = tuplefy(func(*input))
                if numpy or to_cpu:
                    preds_batch = preds_batch.to_device("cpu")
                preds.append(preds_batch)
        if eval_:
            self.net.train()
        preds = tuplefy(preds).cat()
        if numpy:
            preds = preds.to_numpy()
        if len(preds) == 1:
            preds = preds[0]
        return preds
Exemple #9
0
 def predict(self,
             input,
             batch_size=8224,
             numpy=None,
             eval_=True,
             grads=False,
             to_cpu=False,
             num_workers=0):
     """Get predictions from 'input'.
     
     Arguments:
         input {tuple, np.ndarra, or torch.tensor} -- Input to net.
     
     Keyword Arguments:
         batch_size {int} -- Batch size (default: {8224})
         numpy {bool} -- 'False' gives tensor, 'True' gives numpy, and None give same as input
             (default: {None})
         eval_ {bool} -- If 'True', use 'eval' modede on net. (default: {True})
         grads {bool} -- If gradients should be computed (default: {False})
         to_cpu {bool} -- For larger data sets we need to move the results to cpu
             (default: {False})
         num_workers {int} -- Number of workes in created dataloader (default: {0})
     
     Returns:
         [TupleTree, np.ndarray or tensor] -- Predictions
     """
     if numpy is None:
         numpy = tuplefy(input).type() is not torch.Tensor
     dataloader = self.make_dataloader_predict(input,
                                               batch_size,
                                               shuffle=False,
                                               num_workers=num_workers)
     preds = self.predict_dataloader(dataloader, numpy, eval_, grads,
                                     to_cpu)
     return preds
    def compute_metrics(self, data, metrics=None) -> Dict[str, torch.Tensor]:
        """Function for computing the loss and other metrics.

        Arguments:
            data {tensor or tuple} -- A batch of data. Typically the tuple `(input, target)`.
        Keyword Arguments:
            metrics {dict} -- A dictionary with metrics. If `None` use `self.metrics`. (default: {None})
        """
        return_metrics = {}
        if metrics is None:
            metrics = self.metrics
        if (self.loss is None) and (self.loss in metrics.values()):
            raise RuntimeError(f"Need to set `self.loss`.")

        input, target = data
        input = self._to_device(input)
        target = self._to_device(target)
        #         out1, out2 = self.net(input)
        combined = self.net(input)
        #         print(combined.shape)
        combined = tuplefy(combined)
        #         out1 = tuplefy(out1)
        #         out2 = tuplefy(out2)

        #         resnet_loss = self.loss(*out1, *target)
        #         clinical_loss = self.loss(*out2, *target)
        loss = self.loss(*combined, *target)
        #         loss = resnet_loss + clinical_loss

        return {'loss': loss}
 def test_reorder(self):
     a = tuplefy((('a', 'b', 'c', 'd'), ('e', 'f')))
     order = (0, (
         1,
         2,
     ), (5, ))
     assert a.reorder(order) == ('a', ('b', 'c'), ('f', ))
 def test_reduce(self):
     a = (
         (1, (2, 3), 4),
         (1, (2, 3), 4),
         (1, (2, 3), 4),
     )
     b = (3, (6, 9), 12)
     a = tuplefy(a)
     assert a.reduce(lambda x, y: x + y) == b
 def test_np2torch2np(self):
     np.random.seed(123)
     a = [
         np.random.normal(size=(i, j)).astype('float32')
         for i, j in [(2, 3), (1, 2)]
     ]
     a = tuplefy(a, np.random.choice(10, size=(4, )))
     b = a.to_tensor().to_numpy()
     assert_tupletree_equal(a, b)
Exemple #14
0
 def test_next_iter(self, batch_size, num_workers):
     torch.manual_seed(123)
     n = 20
     a = ((torch.randn(n, 3), torch.randint(200, (n, 2))), torch.randn(n))
     a = tuplefy(a)
     ds = DatasetTuple(*a)
     dl = DataLoaderBatch(ds, batch_size, False, num_workers=num_workers)
     a = a.iloc[:batch_size]
     b = next(iter(dl))
     assert_tupletree_equal(a, b)
Exemple #15
0
def assert_tupletree_equal(a, b, check_dtypes=True):
    assert type(a) == type(b) == TupleTree, 'Not TupleTree'
    assert a.numerate() == b.numerate(), 'Not same structure'
    assert a.types() == b.types(), 'Not same types'
    if check_dtypes:
        ad, bd = (tuplefy(a, b).apply(
            lambda x: x.dtype if hasattr(x, 'dtype') else 'not_tensor'))
        assert ad == bd, 'Not same dtype'

    for aa, bb in zip(a.flatten(), b.flatten()):
        if hasattr(aa, 'dtype'):
            assert (aa == bb).all(), 'Not equal values'
        else:
            assert aa == bb, 'Not equal values'
Exemple #16
0
    def compute_metrics(self, input, target, metrics):
        """Function for computing loss.
        Is rather general, but can be reimpliemented by sub classes.
        
        Arguments:
            input {tensor or tuple} -- This should be passed to self.net.
            target {tensor or tuple} -- This is the targets that should be used in self.loss.
            metrics (dictionary with funcs) -- Metrics that should be computed.

        Returns:
            tensor -- Results of self.loss()
        """
        if (self.loss is None) and (self.loss in metrics.values()):
            raise RuntimeError(
                f"Need to specify a loss (self.loss). It's currently None")
        input = self._to_device(input)
        target = self._to_device(target)
        out = self.net(*input)
        out = tuplefy(out)
        res = {name: metric(*out, *target) for name, metric in metrics.items()}
        return res
Exemple #17
0
    def compute_metrics(self, data, metrics=None) -> Dict[str, torch.Tensor]:
        """Function for computing the loss and other metrics.
        
        Arguments:
            data {tensor or tuple} -- A batch of data. Typically the tuple `(input, target)`.

        Keyword Arguments:
            metrics {dict} -- A dictionary with metrics. If `None` use `self.metrics`. (default: {None})
        """
        if metrics is None:
            metrics = self.metrics
        if (self.loss is None) and (self.loss in metrics.values()):
            raise RuntimeError(f"Need to set `self.loss`.")

        input, target = data
        input = self._to_device(input)
        target = self._to_device(target)
        out = self.net(*input)
        out = tuplefy(out)
        return {
            name: metric(*out, *target)
            for name, metric in metrics.items()
        }
import pytest
import numpy as np
import torch
from torchtuples.tupletree import tuplefy
from torchtuples.testing import assert_tupletree_equal


@pytest.mark.parametrize('a, b, ex_string', [
    ((1, 2), (1, ), 'Not TupleTree'),
    (tuplefy(1, 2), tuplefy(1, (2, )), 'Not same structure'),
    (tuplefy(np.arange(5)), tuplefy(torch.arange(5)), 'Not same types'),
    (tuplefy(np.arange(5)), tuplefy(
        np.arange(5).astype('float')), 'Not same dtype'),
    (tuplefy(torch.arange(5)), tuplefy(
        torch.arange(5).float()), 'Not same dtype'),
    (tuplefy(np.arange(5)), tuplefy(np.arange(1, 6)), 'Not equal values'),
    (tuplefy(torch.arange(5)), tuplefy(torch.arange(1,
                                                    6)), 'Not equal values'),
])
def test_assert_tupletree_equal_fails(a, b, ex_string):
    with pytest.raises(AssertionError) as ex:
        assert_tupletree_equal(a, b)
    assert str(ex.value) == ex_string


@pytest.mark.parametrize('a, b, check_dtypes', [
    (tuplefy(1, 2), tuplefy(1, 2), True),
    (tuplefy(np.arange(5),
             (1, 2)), tuplefy(np.arange(5).astype('float'), (1, 2)), False),
])
def test_assert_tupletree_equal_pass(a, b, check_dtypes):
Exemple #19
0
 def _tuple_info(tuple_):
     tuple_ = tuplefy(tuple_)
     return {
         'levels': tuple_.to_levels(),
         'shapes': tuple_.shapes().apply(lambda x: x[1:])
     }
Exemple #20
0
    def predict_dataloader(self,
                           dataloader,
                           numpy=True,
                           eval_=True,
                           grads=False,
                           to_cpu=False):
        """Get predictions from dataloader.
        
        Arguments:
            dataloader {DataLoader} -- Dataloader with inputs to net.
        
        Keyword Arguments:
            numpy {bool} -- If 'False', tensor is returned (default: {True})
            eval_ {bool} -- If 'True', use 'eval' modede on net. (default: {True})
            grads {bool} -- If gradients should be computed (default: {False})
            to_cpu {bool} -- For larger data sets we need to move the results to cpu
                (default: {False})
        
        Returns:
            [TupleTree, np.ndarray or tensor] -- Predictions
        """
        if hasattr(self, 'fit_info') and (self.make_dataloader is
                                          self.make_dataloader_predict):
            # input = tuplefy(dataloader.dataset[0])
            data = _get_element_in_dataloader(dataloader)
            if data is not None:
                input = tuplefy(data)
                input_train = self.fit_info['input']
                if input.to_levels() != input_train['levels']:
                    raise RuntimeError(
                        """The input from the dataloader is different from
                    the 'input' during trainig. Make sure to remove 'target' from dataloader.
                    Can be done with 'torchtuples.data.dataloader_input_only'."""
                    )
                if input.shapes().apply(
                        lambda x: x[1:]) != input_train['shapes']:
                    raise RuntimeError(
                        """The input from the dataloader is different from
                    the 'input' during trainig. The shapes are different.""")

        if not eval_:
            warnings.warn(
                "We still don't shuffle the data here... event though 'eval_' is True."
            )
        if eval_:
            self.net.eval()
        with torch.set_grad_enabled(grads):
            preds = []
            for input in dataloader:
                input = tuplefy(input).to_device(self.device)
                preds_batch = tuplefy(self.net(*input))
                if numpy or to_cpu:
                    preds_batch = preds_batch.to_device('cpu')
                preds.append(preds_batch)
        if eval_:
            self.net.eval()
        preds = tuplefy(preds).cat()
        if numpy:
            preds = preds.to_numpy()
        if len(preds) == 1:
            preds = preds[0]
        return preds
 def test_apply(self):
     a = (1, (2, 3), (4, (5, )))
     a = tuplefy(a)
     b = (2, (4, 6), (8, (10, )))
     assert a.apply(lambda x: x * 2) == b
 def test_levels(self):
     a = (1, (2, 3), (4, (5, )))
     a = tuplefy(a)
     assert a.levels == (0, (1, 1), (1, (2, )))
 def test_types(self):
     a = ('a', (1, 4.5), {})
     b = (str, (int, float), dict)
     a = tuplefy(a)
     assert a.types() == b
 def test_cat_lens(self):
     torch.manual_seed(123)
     a = [torch.randn((i, j)) for i, j in [(5, 3), (5, 2)]]
     a = tuplefy(a, torch.randint(10, (5, )))
     assert a.repeat(3).cat().lens() == ((15, 15), 15)
 def test_numerate(self):
     a = (1, (2, 3), (4, (5, )))
     order = (0, (1, 2), (3, (4, )))
     a = tuplefy(a)
     assert a.numerate() == order
 def test_enumerate(self):
     a = tuplefy(list('abcd'), list('ef'))
     a = tuplefy((('a', 'b', 'c', 'd'), ('e', 'f')))
     assert a.enumerate() == (([0, 'a'], [1, 'b'], [2, 'c'], [3, 'd']),
                              ([4, 'e'], [5, 'f']))
 def test_repeat(self):
     a = (1, (2, 3))
     b = ((1, (2, 3)), (1, (2, 3)), (1, (2, 3)))
     assert tuplefy(a).repeat(3) == b
 def test_add_root(self):
     a = tuplefy(1, 2, 3)
     assert a == a.add_root()[0]
def test_tuplefy_type(inp):
    t = tuplefy(inp)
    assert type(t) is TupleTree
 def test_cat_split(self):
     torch.manual_seed(123)
     a = [torch.randn((i, j)) for i, j in [(5, 3), (5, 2)]]
     a = tuplefy(a, torch.randint(10, (5, )))
     for sub in a.repeat(3).cat().split(5):
         assert_tupletree_equal(a, sub)