(query, facts, attention_size, mask, stag='null', mode='LIST', softmax_stag=1, time_major=False, return_alphas=False)
| 273 | |
| 274 | |
| 275 | def attention(query, facts, attention_size, mask, stag='null', mode='LIST', softmax_stag=1, time_major=False, return_alphas=False): |
| 276 | if isinstance(facts, tuple): |
| 277 | # In case of Bi-RNN, concatenate the forward and the backward RNN outputs. |
| 278 | facts = tf.concat(facts, 2) |
| 279 | |
| 280 | if time_major: |
| 281 | # (T,B,D) => (B,T,D) |
| 282 | facts = tf.array_ops.transpose(facts, [1, 0, 2]) |
| 283 | |
| 284 | mask = tf.equal(mask, tf.ones_like(mask)) |
| 285 | hidden_size = facts.get_shape().as_list()[-1] # D value - hidden size of the RNN layer |
| 286 | input_size = query.get_shape().as_list()[-1] |
| 287 | |
| 288 | # Trainable parameters |
| 289 | w1 = tf.Variable(tf.random_normal([hidden_size, attention_size], stddev=0.1)) |
| 290 | w2 = tf.Variable(tf.random_normal([input_size, attention_size], stddev=0.1)) |
| 291 | b = tf.Variable(tf.random_normal([attention_size], stddev=0.1)) |
| 292 | v = tf.Variable(tf.random_normal([attention_size], stddev=0.1)) |
| 293 | |
| 294 | with tf.name_scope('v'): |
| 295 | # Applying fully connected layer with non-linear activation to each of the B*T timestamps; |
| 296 | # the shape of `tmp` is (B,T,D)*(D,A)=(B,T,A), where A=attention_size |
| 297 | tmp1 = tf.tensordot(facts, w1, axes=1) |
| 298 | tmp2 = tf.tensordot(query, w2, axes=1) |
| 299 | tmp2 = tf.reshape(tmp2, [-1, 1, tf.shape(tmp2)[-1]]) |
| 300 | tmp = tf.tanh((tmp1 + tmp2) + b) |
| 301 | |
| 302 | # For each of the timestamps its vector of size A from `tmp` is reduced with `v` vector |
| 303 | v_dot_tmp = tf.tensordot(tmp, v, axes=1, name='v_dot_tmp') # (B,T) shape |
| 304 | key_masks = mask # [B, 1, T] |
| 305 | # key_masks = tf.expand_dims(mask, 1) # [B, 1, T] |
| 306 | paddings = tf.ones_like(v_dot_tmp) * (-2 ** 32 + 1) |
| 307 | v_dot_tmp = tf.where(key_masks, v_dot_tmp, paddings) # [B, 1, T] |
| 308 | alphas = tf.nn.softmax(v_dot_tmp, name='alphas') # (B,T) shape |
| 309 | |
| 310 | # Output of (Bi-)RNN is reduced with attention vector; the result has (B,D) shape |
| 311 | #output = tf.reduce_sum(facts * tf.expand_dims(alphas, -1), 1) |
| 312 | output = facts * tf.expand_dims(alphas, -1) |
| 313 | output = tf.reshape(output, tf.shape(facts)) |
| 314 | # output = output / (facts.get_shape().as_list()[-1] ** 0.5) |
| 315 | if not return_alphas: |
| 316 | return output |
| 317 | else: |
| 318 | return output, alphas |
| 319 | |
| 320 | |
| 321 | def din_fcn_attention(query, facts, attention_size, mask, stag='null', mode='SUM', softmax_stag=1, time_major=False, return_alphas=False, forCnn=False): |
nothing calls this directly
no outgoing calls
no test coverage detected