diff --git a/src/icosagon/convlayer.py b/src/icosagon/convlayer.py index d356afc..3fe1313 100644 --- a/src/icosagon/convlayer.py +++ b/src/icosagon/convlayer.py @@ -80,7 +80,10 @@ class DecagonLayer(torch.nn.Module): repr_ = sum(repr_) repr_ = torch.nn.functional.normalize(repr_, p=2, dim=1) next_layer_repr[node_type_row].append(repr_) - next_layer_repr[node_type_row] = sum(next_layer_repr[node_type_row]) - next_layer_repr[node_type_row] = self.layer_activation(next_layer_repr[node_type_row]) + if len(next_layer_repr[node_type_row]) == 0: + next_layer_repr[node_type_row] = torch.zeros(self.output_dim[node_type_row]) + else: + next_layer_repr[node_type_row] = sum(next_layer_repr[node_type_row]) + next_layer_repr[node_type_row] = self.layer_activation(next_layer_repr[node_type_row]) return next_layer_repr diff --git a/src/icosagon/input.py b/src/icosagon/input.py index 4f7dd73..8c686b1 100644 --- a/src/icosagon/input.py +++ b/src/icosagon/input.py @@ -16,7 +16,7 @@ class InputLayer(torch.nn.Module): output_dim = output_dim or \ list(map(lambda a: a.count, data.node_types)) - + if not isinstance(output_dim, list): output_dim = [output_dim,] * len(data.node_types) @@ -72,7 +72,7 @@ class OneHotInputLayer(torch.nn.Module): def __repr__(self) -> str: s = '' - s += 'One-hot Icosagon input layer\n' + s += 'Icosagon one-hot input layer\n' s += ' # of node types: %d\n' % len(self.data.node_types) for nt in self.data.node_types: s += ' - %s (%d)\n' % (nt.name, nt.count) diff --git a/tests/icosagon/test_declayer.py b/tests/icosagon/test_declayer.py index fb29831..2649759 100644 --- a/tests/icosagon/test_declayer.py +++ b/tests/icosagon/test_declayer.py @@ -43,8 +43,47 @@ def test_decode_layer_02(): seq = torch.nn.Sequential(in_layer, d_layer, dec_layer) pred_adj_matrices = seq(None) - + assert isinstance(pred_adj_matrices, dict) assert len(pred_adj_matrices) == 1 assert isinstance(pred_adj_matrices[0, 0], list) assert len(pred_adj_matrices[0, 0]) == 1 + + +def test_decode_layer_03(): + d = Data() + d.add_node_type('Dummy 1', 100) + d.add_node_type('Dummy 2', 100) + d.add_relation_type('Dummy Relation 1', 0, 1, + torch.rand((100, 100), dtype=torch.float32).round().to_sparse()) + + in_layer = OneHotInputLayer(d) + d_layer = DecagonLayer(in_layer.output_dim, 32, d) + dec_layer = DecodeLayer(input_dim=d_layer.output_dim, data=d, keep_prob=1., + decoder_class={(0, 1): DEDICOMDecoder}, activation=lambda x: x) + seq = torch.nn.Sequential(in_layer, d_layer, dec_layer) + + pred_adj_matrices = seq(None) + assert isinstance(pred_adj_matrices, dict) + assert len(pred_adj_matrices) == 2 + assert isinstance(pred_adj_matrices[0, 1], list) + assert isinstance(pred_adj_matrices[1, 0], list) + assert len(pred_adj_matrices[0, 1]) == 1 + assert len(pred_adj_matrices[1, 0]) == 1 + + +def test_decode_layer_04(): + d = Data() + d.add_node_type('Dummy', 100) + assert len(d.relation_types[0, 0]) == 0 + + in_layer = OneHotInputLayer(d) + d_layer = DecagonLayer(in_layer.output_dim, 32, d) + dec_layer = DecodeLayer(input_dim=d_layer.output_dim, data=d, keep_prob=1., + decoder_class=DEDICOMDecoder, activation=lambda x: x) + seq = torch.nn.Sequential(in_layer, d_layer, dec_layer) + + pred_adj_matrices = seq(None) + + assert isinstance(pred_adj_matrices, dict) + assert len(pred_adj_matrices) == 0 diff --git a/tests/icosagon/test_input.py b/tests/icosagon/test_input.py index 3e73ce1..1e9cfbf 100644 --- a/tests/icosagon/test_input.py +++ b/tests/icosagon/test_input.py @@ -70,6 +70,13 @@ def test_input_layer_03(): assert layer.node_reps[1].device == device +def test_input_layer_04(): + d = _some_data() + layer = InputLayer(d, 32) + s = repr(layer) + assert s.startswith('Icosagon input layer') + + def test_one_hot_input_layer_01(): d = _some_data() layer = OneHotInputLayer(d) @@ -104,3 +111,10 @@ def test_one_hot_input_layer_03(): # assert layer.device.type == 'cuda:0' assert layer.node_reps[0].device == device assert layer.node_reps[1].device == device + + +def test_one_hot_input_layer_04(): + d = _some_data() + layer = OneHotInputLayer(d) + s = repr(layer) + assert s.startswith('Icosagon one-hot input layer')