FranKGraphBench 0.0.1a0__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. FranKGraphBench-0.0.1a0.dist-info/LICENSE +201 -0
  2. FranKGraphBench-0.0.1a0.dist-info/METADATA +189 -0
  3. FranKGraphBench-0.0.1a0.dist-info/RECORD +70 -0
  4. FranKGraphBench-0.0.1a0.dist-info/WHEEL +6 -0
  5. FranKGraphBench-0.0.1a0.dist-info/entry_points.txt +3 -0
  6. FranKGraphBench-0.0.1a0.dist-info/top_level.txt +2 -0
  7. data_integration/__init__.py +47 -0
  8. data_integration/__main__.py +4 -0
  9. data_integration/dataset.py +270 -0
  10. data_integration/dataset2class.py +34 -0
  11. data_integration/datasets/__init__.py +0 -0
  12. data_integration/datasets/amazon.py +140 -0
  13. data_integration/datasets/book-crossing.py +98 -0
  14. data_integration/datasets/douban-movie.py +75 -0
  15. data_integration/datasets/lastfm.py +215 -0
  16. data_integration/datasets/movielens.py +375 -0
  17. data_integration/datasets/steam.py +98 -0
  18. data_integration/datasets/worker.py +31 -0
  19. data_integration/datasets/yelp.py +156 -0
  20. framework/__init__.py +17 -0
  21. framework/__main__.py +4 -0
  22. framework/dataloader/__init__.py +0 -0
  23. framework/dataloader/dataloader.py +52 -0
  24. framework/dataloader/dataset/__init__.py +0 -0
  25. framework/dataloader/dataset/dataset.py +38 -0
  26. framework/dataloader/edge_splitter/__init__.py +0 -0
  27. framework/dataloader/edge_splitter/edge_splitter.py +163 -0
  28. framework/dataloader/graph/__init__.py +0 -0
  29. framework/dataloader/graph/graph.py +314 -0
  30. framework/dataloader/graph/node.py +80 -0
  31. framework/dataloader/preprocess/__init__.py +0 -0
  32. framework/dataloader/preprocess/methods.py +47 -0
  33. framework/evaluator/__init__.py +0 -0
  34. framework/evaluator/metric.py +39 -0
  35. framework/evaluator/metric2class.py +10 -0
  36. framework/evaluator/metrics/__init__.py +0 -0
  37. framework/evaluator/metrics/map.py +33 -0
  38. framework/evaluator/metrics/ndcg.py +49 -0
  39. framework/experiment.py +120 -0
  40. framework/recommender/__init__.py +0 -0
  41. framework/recommender/model2class.py +46 -0
  42. framework/recommender/models/__init__.py +0 -0
  43. framework/recommender/models/complEx/__init__.py +0 -0
  44. framework/recommender/models/complEx/model.py +193 -0
  45. framework/recommender/models/deep_walk_based/__init__.py +0 -0
  46. framework/recommender/models/deep_walk_based/model.py +149 -0
  47. framework/recommender/models/distMult/__init__.py +0 -0
  48. framework/recommender/models/distMult/model.py +187 -0
  49. framework/recommender/models/ePHEN/__init__.py +0 -0
  50. framework/recommender/models/ePHEN/model.py +159 -0
  51. framework/recommender/models/rESCAL/__init__.py +0 -0
  52. framework/recommender/models/rESCAL/model.py +184 -0
  53. framework/recommender/models/rotatE/__init__.py +0 -0
  54. framework/recommender/models/rotatE/model.py +195 -0
  55. framework/recommender/models/transD/__init__.py +0 -0
  56. framework/recommender/models/transD/model.py +190 -0
  57. framework/recommender/models/transE/__init__.py +0 -0
  58. framework/recommender/models/transE/model.py +194 -0
  59. framework/recommender/models/transH/__init__.py +0 -0
  60. framework/recommender/models/transH/model.py +193 -0
  61. framework/recommender/models/transR/__init__.py +0 -0
  62. framework/recommender/models/transR/model.py +190 -0
  63. framework/recommender/models/tuckER/__init__.py +0 -0
  64. framework/recommender/models/tuckER/model.py +199 -0
  65. framework/recommender/recommender.py +32 -0
  66. framework/recommender/utils/__init__.py +0 -0
  67. framework/recommender/utils/walker.py +185 -0
  68. framework/reporter/__init__.py +0 -0
  69. framework/reporter/report.py +101 -0
  70. framework/utils.py +10 -0
@@ -0,0 +1,193 @@
1
+ from framework.dataloader.graph.node import UserNode, ItemNode
2
+ from ...recommender import Recommender
3
+
4
+ from pykeen.pipeline import pipeline
5
+ from pykeen.triples import TriplesFactory
6
+ from pykeen.datasets import Dataset
7
+ from sklearn.neighbors import NearestNeighbors
8
+
9
+
10
+ import numpy as np
11
+ import torch
12
+ import typing as t
13
+
14
+ """
15
+ Recommender base class
16
+ """
17
+
18
+
19
+ class TransH(Recommender):
20
+ def __init__(
21
+ self,
22
+ config: dict,
23
+ embedding_dim: int = 50,
24
+ scoring_fct_norm: int = 1,
25
+ entity_initializer = None,
26
+ regularizer = None,
27
+ regularizer_kwargs = None,
28
+ relation_initializer = None,
29
+ relation_regularizer = None,
30
+ relation_regularizer_kwargs = None,
31
+ epochs: int = 5,
32
+ seed: int = 42,
33
+ evaluation_fallback: bool = True,
34
+ all_recs: bool = False,
35
+ triples: str = "all",
36
+ ):
37
+ super().__init__(config)
38
+ self.embedding_dim = embedding_dim
39
+ self.scoring_fct_norm = scoring_fct_norm
40
+ self.entity_initializer = entity_initializer
41
+ self.regularizer = regularizer
42
+ self.regularizer_kwargs = regularizer_kwargs
43
+ self.relation_initializer = relation_initializer
44
+ self.relation_regularizer = relation_regularizer
45
+ self.relation_regularizer_kwargs = relation_regularizer_kwargs
46
+ self.epochs = epochs
47
+ self.seed = seed
48
+ self.evaluation_fallback = evaluation_fallback
49
+ self.all_recs = all_recs
50
+ self.triples = triples
51
+ self._triples = None
52
+ self._embedding = {}
53
+
54
+ def name(self):
55
+ text = "TransH based model + cosine similarity"
56
+ text += f";embedding_dim={self.embedding_dim};scoring_fct_norm={self.scoring_fct_norm};entity_initializer={self.entity_initializer};regularizer={self.regularizer};relation_initializer={self.relation_initializer};relation_regularizer={self.relation_regularizer};epochs={self.epochs};seed={self.seed};triples={self.triples}"
57
+ return text
58
+
59
+ def train(self, G_train, ratings_train):
60
+ self.G_train = G_train
61
+ if self.triples == "all":
62
+ self._triples = G_train.get_all_triples()
63
+ elif self.triples == "ratings":
64
+ self._triples = G_train.get_ratings_triples()
65
+ self.fit()
66
+
67
+ def get_recommendations(self, k: int = 5) -> t.Dict[UserNode, t.List[ItemNode]]:
68
+ """
69
+ :param k: cutoff recommendation (int)
70
+ :return dict of recommendations for each user
71
+ of type {user1: [item1, item2]}
72
+ """
73
+ users = list(self.G_train.get_user_nodes())
74
+ items = list(self.G_train.get_item_nodes())
75
+
76
+ users_embeddings = np.array([self._embedding[user] for user in users])
77
+ items_embeddings = np.array([self._embedding[item] for item in items])
78
+
79
+ n_neighbors = self._get_n_neighbors(users, items, k)
80
+ knn = NearestNeighbors(n_neighbors=n_neighbors, metric="cosine")
81
+ knn.fit(items_embeddings)
82
+ rec_indices = knn.kneighbors(users_embeddings, return_distance=False)
83
+
84
+ recommendations = {}
85
+ for user_idx, user in enumerate(users):
86
+ rated_items = self.G_train.get_user_rated_items(user)
87
+ recs = []
88
+ for item_idx in rec_indices[user_idx]:
89
+ item = items[item_idx]
90
+ if item not in rated_items:
91
+ recs.append(item)
92
+ if not self.all_recs and len(recs) == k:
93
+ break
94
+
95
+ recommendations[user] = recs
96
+
97
+ return recommendations
98
+
99
+ def get_user_recommendation(self, user: UserNode, k: int = 5):
100
+ raise NotImplementedError(
101
+ "Override get_user_recommendation() for your model subclass."
102
+ )
103
+
104
+ def fit(self):
105
+ triples = TriplesFactory.from_labeled_triples(
106
+ self._triples[["head", "relation", "tail"]].values,
107
+ create_inverse_triples=False,
108
+ entity_to_id=None,
109
+ relation_to_id=None,
110
+ compact_id=False,
111
+ filter_out_candidate_inverse_relations=True,
112
+ metadata=None,
113
+ )
114
+
115
+ dataset = Dataset.from_tf(triples, ratios=[0.95, 0.05, 0.0])
116
+ entity_to_id = dataset.entity_to_id
117
+
118
+ result = pipeline(
119
+ dataset=dataset,
120
+ model="TransH",
121
+ model_kwargs=dict(
122
+ embedding_dim=self.embedding_dim,
123
+ scoring_fct_norm=self.scoring_fct_norm,
124
+ entity_initializer=self.entity_initializer,
125
+ regularizer=self.regularizer,
126
+ regularizer_kwargs=self.regularizer_kwargs,
127
+ relation_initializer=self.relation_initializer,
128
+ relation_regularizer=self.relation_regularizer,
129
+ relation_regularizer_kwargs=self.relation_regularizer_kwargs,
130
+ ),
131
+ epochs = self.epochs,
132
+ random_seed = self.seed,
133
+ evaluation_fallback = self.evaluation_fallback,
134
+ )
135
+ model = result.model
136
+
137
+ users_iter = self.G_train.get_user_nodes()
138
+ items_iter = self.G_train.get_item_nodes()
139
+
140
+ users = list(users_iter)
141
+ items = list(items_iter)
142
+
143
+ # deal with entities that might have not been embedded
144
+ users_indices, users_no_embedding = [], []
145
+ for user in users_iter:
146
+ try:
147
+ users_indices.append(entity_to_id[user.__str__()])
148
+ except:
149
+ users_no_embedding.append(user)
150
+ users.remove(user)
151
+ continue
152
+ users_indices = torch.LongTensor(users_indices)
153
+
154
+ items_indices, items_no_embedding = [], []
155
+ for item in items_iter:
156
+ try:
157
+ items_indices.append(entity_to_id[item.__str__()])
158
+ except:
159
+ items_no_embedding.append(item)
160
+ items.remove(item)
161
+ continue
162
+ items_indices = torch.LongTensor(items_indices)
163
+
164
+ users_embeddings = (model.entity_representations[0](indices=users_indices).detach().cpu().numpy())
165
+ items_embeddings = (model.entity_representations[0](indices=items_indices).detach().cpu().numpy())
166
+
167
+ if len(users_no_embedding) > 0:
168
+ users_embeddings = np.concatenate((users_embeddings, np.zeros((len(users_no_embedding), self.embedding_dim), dtype=users_embeddings.dtype)), axis=0)
169
+ users = users + users_no_embedding
170
+
171
+ if len(items_no_embedding) > 0:
172
+ items_embeddings = np.concatenate((items_embeddings, np.zeros((len(items_no_embedding), self.embedding_dim), dtype=items_embeddings.dtype)), axis=0)
173
+ items = items + items_no_embedding
174
+
175
+ for index, user in enumerate(users):
176
+ self._embedding[user] = users_embeddings[index]
177
+
178
+ for index, item in enumerate(items):
179
+ self._embedding[item] = items_embeddings[index]
180
+
181
+ def _get_n_neighbors(self, users, items, top_k):
182
+ n_neighbors = 0
183
+ if self.all_recs:
184
+ n_neighbors = len(items)
185
+ else:
186
+ max_recs = 0
187
+ for user in users:
188
+ rated_items = self.G_train.get_user_rated_items(user)
189
+ if len(rated_items) > max_recs:
190
+ max_recs = len(rated_items)
191
+ n_neighbors = min(max_recs + top_k, len(items))
192
+
193
+ return n_neighbors
File without changes
@@ -0,0 +1,190 @@
1
+ from framework.dataloader.graph.node import UserNode, ItemNode
2
+ from ...recommender import Recommender
3
+
4
+ from pykeen.pipeline import pipeline
5
+ from pykeen.triples import TriplesFactory
6
+ from pykeen.datasets import Dataset
7
+ from sklearn.neighbors import NearestNeighbors
8
+
9
+
10
+ import numpy as np
11
+ import torch
12
+ import typing as t
13
+
14
+ """
15
+ Recommender base class
16
+ """
17
+
18
+
19
+ class TransR(Recommender):
20
+ def __init__(
21
+ self,
22
+ config: dict,
23
+ embedding_dim: int = 50,
24
+ relation_dim: int = 30,
25
+ scoring_fct_norm: int = 1,
26
+ entity_initializer=None,
27
+ entity_constrainer=None,
28
+ relation_initializer=None,
29
+ relation_constrainer=None,
30
+ epochs: int = 5,
31
+ seed: int = 42,
32
+ evaluation_fallback: bool = True,
33
+ all_recs: bool = False,
34
+ triples: str = "all",
35
+ ):
36
+ super().__init__(config)
37
+ self.embedding_dim = embedding_dim
38
+ self.relation_dim = relation_dim
39
+ self.scoring_fct_norm = scoring_fct_norm
40
+ self.entity_initializer = entity_initializer
41
+ self.entity_constrainer = entity_constrainer
42
+ self.relation_initializer = relation_initializer
43
+ self.relation_constrainer = relation_constrainer
44
+ self.epochs = epochs
45
+ self.seed = seed
46
+ self.evaluation_fallback = evaluation_fallback
47
+ self.all_recs = all_recs
48
+ self.triples = triples
49
+ self._triples = None
50
+ self._embedding = {}
51
+
52
+ def name(self):
53
+ text = "TransR based model + cosine similarity"
54
+ text += f";embedding_dim={self.embedding_dim};relation_dim={self.relation_dim};scoring_fct_norm={self.scoring_fct_norm};entity_initializer={self.entity_initializer};entity_constrainer={self.entity_constrainer};relation_initializer={self.relation_initializer};relation_constrainer={self.relation_constrainer};epochs={self.epochs};seed={self.seed};triples={self.triples}"
55
+ return text
56
+
57
+ def train(self, G_train, ratings_train):
58
+ self.G_train = G_train
59
+ if self.triples == "all":
60
+ self._triples = G_train.get_all_triples()
61
+ elif self.triples == "ratings":
62
+ self._triples = G_train.get_ratings_triples()
63
+ self.fit()
64
+
65
+ def get_recommendations(self, k: int = 5) -> t.Dict[UserNode, t.List[ItemNode]]:
66
+ """
67
+ :param k: cutoff recommendation (int)
68
+ :return dict of recommendations for each user
69
+ of type {user1: [item1, item2]}
70
+ """
71
+ users = list(self.G_train.get_user_nodes())
72
+ items = list(self.G_train.get_item_nodes())
73
+
74
+ users_embeddings = np.array([self._embedding[user] for user in users])
75
+ items_embeddings = np.array([self._embedding[item] for item in items])
76
+
77
+ n_neighbors = self._get_n_neighbors(users, items, k)
78
+ knn = NearestNeighbors(n_neighbors=n_neighbors, metric="cosine")
79
+ knn.fit(items_embeddings)
80
+ rec_indices = knn.kneighbors(users_embeddings, return_distance=False)
81
+
82
+ recommendations = {}
83
+ for user_idx, user in enumerate(users):
84
+ rated_items = self.G_train.get_user_rated_items(user)
85
+ recs = []
86
+ for item_idx in rec_indices[user_idx]:
87
+ item = items[item_idx]
88
+ if item not in rated_items:
89
+ recs.append(item)
90
+ if not self.all_recs and len(recs) == k:
91
+ break
92
+
93
+ recommendations[user] = recs
94
+
95
+ return recommendations
96
+
97
+ def get_user_recommendation(self, user: UserNode, k: int = 5):
98
+ raise NotImplementedError(
99
+ "Override get_user_recommendation() for your model subclass."
100
+ )
101
+
102
+ def fit(self):
103
+ triples = TriplesFactory.from_labeled_triples(
104
+ self._triples[["head", "relation", "tail"]].values,
105
+ create_inverse_triples=False,
106
+ entity_to_id=None,
107
+ relation_to_id=None,
108
+ compact_id=False,
109
+ filter_out_candidate_inverse_relations=True,
110
+ metadata=None,
111
+ )
112
+
113
+ dataset = Dataset.from_tf(triples, ratios=[0.95, 0.05, 0.0])
114
+ entity_to_id = dataset.entity_to_id
115
+
116
+ result = pipeline(
117
+ dataset=dataset,
118
+ model="TransR",
119
+ model_kwargs=dict(
120
+ embedding_dim=self.embedding_dim,
121
+ relation_dim=self.relation_dim,
122
+ scoring_fct_norm=self.scoring_fct_norm,
123
+ entity_initializer=self.entity_initializer,
124
+ entity_constrainer=self.entity_constrainer,
125
+ relation_initializer=self.relation_initializer,
126
+ relation_constrainer=self.relation_constrainer,
127
+ ),
128
+ epochs = self.epochs,
129
+ random_seed = self.seed,
130
+ evaluation_fallback = self.evaluation_fallback,
131
+ )
132
+ model = result.model
133
+
134
+ users_iter = self.G_train.get_user_nodes()
135
+ items_iter = self.G_train.get_item_nodes()
136
+
137
+ users = list(users_iter)
138
+ items = list(items_iter)
139
+
140
+ # deal with entities that might have not been embedded
141
+ users_indices, users_no_embedding = [], []
142
+ for user in users_iter:
143
+ try:
144
+ users_indices.append(entity_to_id[user.__str__()])
145
+ except:
146
+ users_no_embedding.append(user)
147
+ users.remove(user)
148
+ continue
149
+ users_indices = torch.LongTensor(users_indices)
150
+
151
+ items_indices, items_no_embedding = [], []
152
+ for item in items_iter:
153
+ try:
154
+ items_indices.append(entity_to_id[item.__str__()])
155
+ except:
156
+ items_no_embedding.append(item)
157
+ items.remove(item)
158
+ continue
159
+ items_indices = torch.LongTensor(items_indices)
160
+
161
+ users_embeddings = (model.entity_representations[0](indices=users_indices).detach().cpu().numpy())
162
+ items_embeddings = (model.entity_representations[0](indices=items_indices).detach().cpu().numpy())
163
+
164
+ if len(users_no_embedding) > 0:
165
+ users_embeddings = np.concatenate((users_embeddings, np.zeros((len(users_no_embedding), self.embedding_dim), dtype=users_embeddings.dtype)), axis=0)
166
+ users = users + users_no_embedding
167
+
168
+ if len(items_no_embedding) > 0:
169
+ items_embeddings = np.concatenate((items_embeddings, np.zeros((len(items_no_embedding), self.embedding_dim), dtype=items_embeddings.dtype)), axis=0)
170
+ items = items + items_no_embedding
171
+
172
+ for index, user in enumerate(users):
173
+ self._embedding[user] = users_embeddings[index]
174
+
175
+ for index, item in enumerate(items):
176
+ self._embedding[item] = items_embeddings[index]
177
+
178
+ def _get_n_neighbors(self, users, items, top_k):
179
+ n_neighbors = 0
180
+ if self.all_recs:
181
+ n_neighbors = len(items)
182
+ else:
183
+ max_recs = 0
184
+ for user in users:
185
+ rated_items = self.G_train.get_user_rated_items(user)
186
+ if len(rated_items) > max_recs:
187
+ max_recs = len(rated_items)
188
+ n_neighbors = min(max_recs + top_k, len(items))
189
+
190
+ return n_neighbors
File without changes
@@ -0,0 +1,199 @@
1
+ from framework.dataloader.graph.node import UserNode, ItemNode
2
+ from ...recommender import Recommender
3
+
4
+ from pykeen.pipeline import pipeline
5
+ from pykeen.triples import TriplesFactory
6
+ from pykeen.datasets import Dataset
7
+ from sklearn.neighbors import NearestNeighbors
8
+
9
+
10
+ import numpy as np
11
+ import torch
12
+ import typing as t
13
+
14
+ """
15
+ Recommender base class
16
+ """
17
+
18
+
19
+ class TuckER(Recommender):
20
+ def __init__(
21
+ self,
22
+ config: dict,
23
+ embedding_dim: int = 200,
24
+ relation_dim = None,
25
+ dropout_0: float = 0.3,
26
+ dropout_1: float = 0.4,
27
+ dropout_2: float = 0.5,
28
+ apply_batch_normalization: bool = True,
29
+ entity_initializer= None,
30
+ relation_initializer = None,
31
+ core_tensor_initializer = None,
32
+ core_tensor_initializer_kwargs=None,
33
+ epochs: int = 5,
34
+ seed: int = 42,
35
+ evaluation_fallback: bool = True,
36
+ all_recs: bool = False,
37
+ triples: str = "all",
38
+ ):
39
+ super().__init__(config)
40
+ self.embedding_dim = embedding_dim
41
+ self.entity_initializer = entity_initializer
42
+ self.relation_dim = relation_dim
43
+ self.dropout_0 = dropout_0
44
+ self.dropout_1 = dropout_1
45
+ self.dropout_2 = dropout_2
46
+ self.apply_batch_normalization = apply_batch_normalization
47
+ self.relation_initializer = relation_initializer
48
+ self.core_tensor_initializer = core_tensor_initializer
49
+ self.core_tensor_initializer_kwargs = core_tensor_initializer_kwargs
50
+ self.epochs = epochs
51
+ self.seed = seed
52
+ self.evaluation_fallback = evaluation_fallback
53
+ self.all_recs = all_recs
54
+ self.triples = triples
55
+ self._triples = None
56
+ self._embedding = {}
57
+
58
+ def name(self):
59
+ text = "TuckER based model + cosine similarity"
60
+ text += f";embedding_dim={self.embedding_dim};relation_dim={self.relation_dim};dropout_0={self.dropout_0};dropout_1={self.dropout_1};dropout_2={self.dropout_2};apply_batch_normalization={self.apply_batch_normalization};relation_initializer={self.relation_initializer};core_tensor_initializer={self.core_tensor_initializer};epochs={self.epochs};seed={self.seed};triples={self.triples}"
61
+ return text
62
+
63
+ def train(self, G_train, ratings_train):
64
+ self.G_train = G_train
65
+ if self.triples == "all":
66
+ self._triples = G_train.get_all_triples()
67
+ elif self.triples == "ratings":
68
+ self._triples = G_train.get_ratings_triples()
69
+ self.fit()
70
+
71
+ def get_recommendations(self, k: int = 5) -> t.Dict[UserNode, t.List[ItemNode]]:
72
+ """
73
+ :param k: cutoff recommendation (int)
74
+ :return dict of recommendations for each user
75
+ of type {user1: [item1, item2]}
76
+ """
77
+ users = list(self.G_train.get_user_nodes())
78
+ items = list(self.G_train.get_item_nodes())
79
+
80
+ users_embeddings = np.array([self._embedding[user] for user in users])
81
+ items_embeddings = np.array([self._embedding[item] for item in items])
82
+
83
+ n_neighbors = self._get_n_neighbors(users, items, k)
84
+ knn = NearestNeighbors(n_neighbors=n_neighbors, metric="cosine")
85
+ knn.fit(items_embeddings)
86
+ rec_indices = knn.kneighbors(users_embeddings, return_distance=False)
87
+
88
+ recommendations = {}
89
+ for user_idx, user in enumerate(users):
90
+ rated_items = self.G_train.get_user_rated_items(user)
91
+ recs = []
92
+ for item_idx in rec_indices[user_idx]:
93
+ item = items[item_idx]
94
+ if item not in rated_items:
95
+ recs.append(item)
96
+ if not self.all_recs and len(recs) == k:
97
+ break
98
+
99
+ recommendations[user] = recs
100
+
101
+ return recommendations
102
+
103
+ def get_user_recommendation(self, user: UserNode, k: int = 5):
104
+ raise NotImplementedError(
105
+ "Override get_user_recommendation() for your model subclass."
106
+ )
107
+
108
+ def fit(self):
109
+ triples = TriplesFactory.from_labeled_triples(
110
+ self._triples[["head", "relation", "tail"]].values,
111
+ create_inverse_triples=False,
112
+ entity_to_id=None,
113
+ relation_to_id=None,
114
+ compact_id=False,
115
+ filter_out_candidate_inverse_relations=True,
116
+ metadata=None,
117
+ )
118
+
119
+ dataset = Dataset.from_tf(triples, ratios=[0.95, 0.05, 0.0])
120
+ entity_to_id = dataset.entity_to_id
121
+
122
+ result = pipeline(
123
+ dataset=dataset,
124
+ model="TuckER",
125
+ model_kwargs=dict(
126
+ embedding_dim=self.embedding_dim,
127
+ relation_dim=self.relation_dim,
128
+ dropout_0=self.dropout_0,
129
+ dropout_1=self.dropout_1,
130
+ dropout_2=self.dropout_2,
131
+ apply_batch_normalization=self.apply_batch_normalization,
132
+ entity_initializer=self.entity_initializer,
133
+ relation_initializer=self.relation_initializer,
134
+ core_tensor_initializer=self.core_tensor_initializer,
135
+ core_tensor_initializer_kwargs=self.core_tensor_initializer_kwargs,
136
+ ),
137
+ epochs = self.epochs,
138
+ random_seed = self.seed,
139
+ evaluation_fallback = self.evaluation_fallback,
140
+ )
141
+ model = result.model
142
+
143
+ users_iter = self.G_train.get_user_nodes()
144
+ items_iter = self.G_train.get_item_nodes()
145
+
146
+ users = list(users_iter)
147
+ items = list(items_iter)
148
+
149
+ # deal with entities that might have not been embedded
150
+ users_indices, users_no_embedding = [], []
151
+ for user in users_iter:
152
+ try:
153
+ users_indices.append(entity_to_id[user.__str__()])
154
+ except:
155
+ users_no_embedding.append(user)
156
+ users.remove(user)
157
+ continue
158
+ users_indices = torch.LongTensor(users_indices)
159
+
160
+ items_indices, items_no_embedding = [], []
161
+ for item in items_iter:
162
+ try:
163
+ items_indices.append(entity_to_id[item.__str__()])
164
+ except:
165
+ items_no_embedding.append(item)
166
+ items.remove(item)
167
+ continue
168
+ items_indices = torch.LongTensor(items_indices)
169
+
170
+ users_embeddings = (model.entity_representations[0](indices=users_indices).detach().cpu().numpy())
171
+ items_embeddings = (model.entity_representations[0](indices=items_indices).detach().cpu().numpy())
172
+
173
+ if len(users_no_embedding) > 0:
174
+ users_embeddings = np.concatenate((users_embeddings, np.zeros((len(users_no_embedding), self.embedding_dim), dtype=users_embeddings.dtype)), axis=0)
175
+ users = users + users_no_embedding
176
+
177
+ if len(items_no_embedding) > 0:
178
+ items_embeddings = np.concatenate((items_embeddings, np.zeros((len(items_no_embedding), self.embedding_dim), dtype=items_embeddings.dtype)), axis=0)
179
+ items = items + items_no_embedding
180
+
181
+ for index, user in enumerate(users):
182
+ self._embedding[user] = users_embeddings[index]
183
+
184
+ for index, item in enumerate(items):
185
+ self._embedding[item] = items_embeddings[index]
186
+
187
+ def _get_n_neighbors(self, users, items, top_k):
188
+ n_neighbors = 0
189
+ if self.all_recs:
190
+ n_neighbors = len(items)
191
+ else:
192
+ max_recs = 0
193
+ for user in users:
194
+ rated_items = self.G_train.get_user_rated_items(user)
195
+ if len(rated_items) > max_recs:
196
+ max_recs = len(rated_items)
197
+ n_neighbors = min(max_recs + top_k, len(items))
198
+
199
+ return n_neighbors
@@ -0,0 +1,32 @@
1
+ from ..dataloader.graph.graph import Graph
2
+ from ..dataloader.graph.node import UserNode, ItemNode
3
+
4
+ from ..utils import get_optional_argument
5
+
6
+ import typing as t
7
+
8
+ """
9
+ Recommender base class
10
+ """
11
+ class Recommender:
12
+ def __init__(self, config : dict = {}):
13
+ if config is not None:
14
+ self.save_weights = get_optional_argument(config, 'save_weights', False)
15
+
16
+ def train(self, G_train : Graph, ratings_train : t.Dict[UserNode, t.List[t.Tuple[ItemNode, float]]]):
17
+ raise NotImplementedError('Override train() method for your model subclass.')
18
+
19
+ def name(self):
20
+ raise NotImplementedError('Override name() method for your model subclass.')
21
+
22
+ def get_recommendations(self, k : int = 5) -> t.Dict[UserNode, t.List[ItemNode]]:
23
+ """
24
+ :param k: cutoff recommendation (int)
25
+ :return dict of recommendations for each user
26
+ of type {user1: [item1, item2]}
27
+ """
28
+ raise NotImplementedError('Override get_recommendations() for your model subclass.')
29
+
30
+ def get_user_recommendation(self, user : UserNode, k : int = 5):
31
+ raise NotImplementedError('Override get_user_recommendation() for your model subclass.')
32
+
File without changes