IF YOU WOULD LIKE TO GET AN ACCOUNT, please write an email to s dot adaszewski at gmail dot com. User accounts are meant only to report issues and/or generate pull requests. This is a purpose-specific Git hosting for ADARED projects. Thank you for your understanding!
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

107 lignes
3.4KB

  1. #
  2. # Copyright (C) Stanislaw Adaszewski, 2020
  3. # License: GPLv3
  4. #
  5. import torch
  6. from .data import Data
  7. from .trainprep import PreparedData, \
  8. TrainValTest
  9. from typing import Type, \
  10. List, \
  11. Callable, \
  12. Union, \
  13. Dict, \
  14. Tuple
  15. from .decode import DEDICOMDecoder
  16. from dataclasses import dataclass
  17. @dataclass
  18. class RelationPredictions(object):
  19. edges_pos: TrainValTest
  20. edges_neg: TrainValTest
  21. edges_back_pos: TrainValTest
  22. edges_back_neg: TrainValTest
  23. @dataclass
  24. class RelationFamilyPredictions(object):
  25. relation_types: List[RelationPredictions]
  26. @dataclass
  27. class Predictions(object):
  28. relation_families: List[RelationFamilyPredictions]
  29. class DecodeLayer(torch.nn.Module):
  30. def __init__(self,
  31. input_dim: List[int],
  32. data: PreparedData,
  33. keep_prob: float = 1.,
  34. activation: Callable[[torch.Tensor], torch.Tensor] = torch.sigmoid,
  35. **kwargs) -> None:
  36. super().__init__(**kwargs)
  37. if not isinstance(input_dim, list):
  38. raise TypeError('input_dim must be a List')
  39. if len(input_dim) != len(data.node_types):
  40. raise ValueError('input_dim must have length equal to num_node_types')
  41. if not all([ a == input_dim[0] for a in input_dim ]):
  42. raise ValueError('All elements of input_dim must have the same value')
  43. if not isinstance(data, PreparedData):
  44. raise TypeError('data must be an instance of PreparedData')
  45. self.input_dim = input_dim[0]
  46. self.output_dim = 1
  47. self.data = data
  48. self.keep_prob = keep_prob
  49. self.activation = activation
  50. self.decoders = None
  51. self.build()
  52. def build(self) -> None:
  53. self.decoders = []
  54. for fam in self.data.relation_families:
  55. dec = fam.decoder_class(self.input_dim, len(fam.relation_types),
  56. self.keep_prob, self.activation)
  57. self.decoders.append(dec)
  58. def _get_tvt(self, r, edge_list_attr_names, row, column, k, last_layer_repr, dec):
  59. pred = []
  60. for p in edge_list_attr_names:
  61. tvt = []
  62. for t in ['train', 'val', 'test']:
  63. # print('r:', r)
  64. edges = getattr(getattr(r, p), t)
  65. inputs_row = last_layer_repr[row][edges[:, 0]]
  66. inputs_column = last_layer_repr[column][edges[:, 1]]
  67. tvt.append(dec(inputs_row, inputs_column, k))
  68. tvt = TrainValTest(*tvt)
  69. pred.append(tvt)
  70. return pred
  71. def forward(self, last_layer_repr: List[torch.Tensor]) -> List[List[torch.Tensor]]:
  72. res = []
  73. for i, fam in enumerate(self.data.relation_families):
  74. fam_pred = []
  75. for k, r in enumerate(fam.relation_types):
  76. pred = []
  77. pred += self._get_tvt(r, ['edges_pos', 'edges_neg'],
  78. r.node_type_row, r.node_type_column, k, last_layer_repr, self.decoders[i])
  79. pred += self._get_tvt(r, ['edges_back_pos', 'edges_back_neg'],
  80. r.node_type_column, r.node_type_row, k, last_layer_repr, self.decoders[i])
  81. pred = RelationPredictions(*pred)
  82. fam_pred.append(pred)
  83. fam_pred = RelationFamilyPredictions(fam_pred)
  84. res.append(fam_pred)
  85. res = Predictions(res)
  86. return res