code: def weighted_sum(matrix, attention):
      """
      Takes a matrix of vectors and a set of weights over the rows in the matrix (which we call an
      "attention" vector), and returns a weighted sum of the rows in the matrix.  This is the typical
      computation performed after an attention mechanism.
  
      Note that while we call this a "matrix" of vectors and an attention "vector", we also handle
      higher-order tensors.  We always sum over the second-to-last dimension of the "matrix", and we
      assume that all dimensions in the "matrix" prior to the last dimension are matched in the
      "vector".  Non-matched dimensions in the "vector" must be `directly after the batch dimension`.
  
      For example, say I have a "matrix" with dimensions ``(batch_size, num_queries, num_words,
      embedding_dim)``.  The attention "vector" then must have at least those dimensions, and could
      have more. Both:
  
          - ``(batch_size, num_queries, num_words)`` (distribution over words for each query)
          - ``(batch_size, num_documents, num_queries, num_words)`` (distribution over words in a
            query for each document)
  
      are valid input "vectors", producing tensors of shape:
      ``(batch_size, num_queries, embedding_dim)`` and
      ``(batch_size, num_documents, num_queries, embedding_dim)`` respectively.
      """
      # We'll special-case a few settings here, where there are efficient (but poorly-named)
      # operations in pytorch that already do the computation we need.
      if attention.dim() == 2 and matrix.dim() == 3:
          return attention.unsqueeze(1).bmm(matrix).squeeze(1)
      if attention.dim() == 3 and matrix.dim() == 3:
          return attention.bmm(matrix)
      if matrix.dim() - 1 < attention.dim():
          expanded_size = list(matrix.size())
          for i in range(attention.dim() - matrix.dim() + 1):
              matrix = matrix.unsqueeze(1)
              expanded_size.insert(i + 1, attention.size(i + 1))
          matrix = matrix.expand(*expanded_size)
      intermediate = attention.unsqueeze(-1).expand_as(matrix) * matrix
      return intermediate.sum(dim=-2)
  
imports: from __future__ import division
  from __future__ import absolute_import
  from collections import defaultdict
  import logging
  import math
  import torch
  from allennlp.common.checks import ConfigurationError
label_desc: Use image node_id 16 for calling a global function with example usage: weighted_sum(matrix, attention) and returns: intermediate, attention, attention