-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathaggregators.py
99 lines (71 loc) · 3.6 KB
/
aggregators.py
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
96
97
import tensorflow as tf
from abc import abstractmethod
LAYER_IDS = {}
def get_layer_id(layer_name=''):
if layer_name not in LAYER_IDS:
LAYER_IDS[layer_name] = 0
return 0
else:
LAYER_IDS[layer_name] += 1
return LAYER_IDS[layer_name]
class Aggregator(object):
def __init__(self, batch_size, seq_len,dim, dropout, act, name):
if not name:
layer = self.__class__.__name__.lower()
name = layer + '_' + str(get_layer_id(layer))
self.name = name
self.dropout = dropout
self.act = act
self.batch_size = batch_size
self.seq_len = seq_len
self.dim = dim
def __call__(self, self_vectors, neighbor_vectors, question_embeddings):
outputs = self._call(self_vectors, neighbor_vectors, question_embeddings)
return outputs
@abstractmethod
def _call(self, self_vectors, neighbor_vectors, question_embeddings):
# dimension:
# self_vectors: [batch_size, -1, dim]
# neighbor_vectors: [batch_size, -1, n_neighbor, dim]
# neighbor_relations: [batch_size, -1, n_neighbor, dim]
# user_embeddings: [batch_size, dim]
pass
class SumAggregator(Aggregator):
def __init__(self, batch_size, seq_len,dim, dropout=0., act=tf.nn.relu, name=None):
super(SumAggregator, self).__init__(batch_size,seq_len,dim, dropout, act, name)
with tf.variable_scope(self.name):
self.weights = tf.get_variable(
shape=[self.dim, self.dim], initializer=tf.contrib.layers.xavier_initializer(), name='weights')
self.bias = tf.get_variable(shape=[self.dim], initializer=tf.zeros_initializer(), name='bias')
def _call(self,self_vectors, neighbor_vectors, question_embeddings):
# [batch_size,seq_len, -1, dim]
neighbors_agg = tf.reduce_mean(neighbor_vectors, axis=-2)
output = tf.reshape(self_vectors + neighbors_agg, [-1, self.dim])
#neighbors_agg = tf.concat([tf.reshape(self_vectors,[self.batch_size,self.seq_len,-1,1,self.dim]),neighbor_vectors],-2)
# [-1, dim]
#output = tf.reshape(tf.reduce_mean(neighbors_agg,-2), [-1, self.dim])
output = tf.nn.dropout(output, keep_prob=self.dropout)
output = tf.matmul(output, self.weights) + self.bias
# [batch_size,seq_len, -1, dim]
output = tf.reshape(output, [self.batch_size,self.seq_len, -1, self.dim])
return self.act(output)
class ConcatAggregator(Aggregator):
def __init__(self, batch_size,seq_len, dim, dropout=0., act=tf.nn.relu, name=None):
super(ConcatAggregator, self).__init__(batch_size, seq_len,dim, dropout, act, name)
with tf.variable_scope(self.name):
self.weights = tf.get_variable(
shape=[self.dim * 2, self.dim], initializer=tf.contrib.layers.xavier_initializer(), name='weights')
self.bias = tf.get_variable(shape=[self.dim], initializer=tf.zeros_initializer(), name='bias')
def _call(self, self_vectors, neighbor_vectors, question_embeddings):
# [batch_size,seq_len, -1, dim]
neighbors_agg = tf.reduce_mean(neighbor_vectors, axis=-2)
# [batch_size,seq_len, -1, dim * 2]
output = tf.concat([self_vectors, neighbors_agg], axis=-1)
# [-1, dim * 2]
output = tf.reshape(output, [-1, self.dim * 2])
output = tf.nn.dropout(output, keep_prob=1-self.dropout)
# [-1, dim]
output = tf.matmul(output, self.weights) + self.bias
# [batch_size, -1, dim]
output = tf.reshape(output, [self.batch_size,self.seq_len, -1, self.dim])
return self.act(output)