-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathedges.py
More file actions
95 lines (69 loc) · 2.89 KB
/
Copy pathedges.py
File metadata and controls
95 lines (69 loc) · 2.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
from abc import ABC, abstractmethod
from functools import reduce
from itertools import combinations_with_replacement
from gensim.models import KeyedVectors
import numpy as np
from tqdm import tqdm
class EdgeEmbedder(ABC):
def __init__(self, keyed_vectors, quiet=False):
"""
:param keyed_vectors: (KeyedVectors) containing nodes and embeddings to calculate edge embeddings
:param quiet:
"""
self.keyed_vectors = keyed_vectors
self.quiet = quiet
@abstractmethod
def _embed(self, edge):
"""
Abstract embedding method
:param edge: (tuple) of two nodes
:return: (np.ndarray) Edge embedding
"""
pass
def __getitem__(self, item):
if not isinstance(item, tuple) or not len(item) == 2:
raise ValueError('Edge must be a tuple of two nodes')
if item[0] not in self.keyed_vectors.index2word:
raise KeyError('Node {} does not exist in given KeyedVectors'.format(item[0]))
if item[1] not in self.keyed_vectors.index2word:
raise KeyError('Node {} does not exist in given KeyedVectors'.format(item[1]))
return self._embed(item)
def as_keyed_vectors(self):
"""
Generate a KeyedVectors instance with all nodes
:return:
"""
generator = combinations_with_replacement(self.keyed_vectors.index2word, r=2)
if not self.quiet:
vocab_size = len(self.keyed_vectors.vocab)
total_size = (reduce(lambda x, y: x * y, range(1, vocab_size + 2)) /
(2 * reduce(lambda x, y: x * y, range(1, vocab_size))))
generator = tqdm(generator, desc='Generating edge features', total=total_size)
# Generate features
tokens = []
features = []
for edge in generator:
token = str(tuple(sorted(edge)))
embedding = self._embed(edge)
tokens.append(token)
features.append(embedding)
# Build KeyedVectors instance
edge_kv = KeyedVectors(vector_size=self.keyed_vectors.vector_size)
edge_kv.add(entities=tokens, weights=features)
return edge_kv
class AverageEmbedder(EdgeEmbedder):
""" Averaged node features """
def _embed(self, edge):
return (self.keyed_vectors[edge[0]] + self.keyed_vectors[edge[1]]) / 2
class HadamardEmbedder(EdgeEmbedder):
""" Hadamard product of node features """
def _embed(self, edge):
return self.keyed_vectors[edge[0]] * self.keyed_vectors[edge[1]]
class WeightedL1Embedder(EdgeEmbedder):
""" Weighted L1 node features """
def _embed(self, edge):
return np.abs(self.keyed_vectors[edge[0]] - self.keyed_vectors[edge[1]])
class WeightedL2Embedder(EdgeEmbedder):
""" Weighted L2 node features """
def _embed(self, edge):
return (self.keyed_vectors[edge[0]] - self.keyed_vectors[edge[1]]) ** 2