class_docstr: Memory Network agent.
  
  Tips:
  - time features are necessary when memory order matters
  - multiple hops allow multiple steps of reasoning, but also seem to make it
      easier to learn to read the memories if you have at least two hops
  - 'adam' seems to work very poorly compared to 'sgd' for hogwild training
class_docstr_tok: ["Memory","Network","agent",".","Tips",":","-","time","features","are","necessary","when","memory","order","matters","-","multiple","hops","allow","multiple","steps","of","reasoning",",","but","also","seem","to","make","it","easier","to","learn","to","read","the","memories","if","you","have","at","least","two","hops","-","'adam","'","seems","to","work","very","poorly","compared","to","'sgd","'","for","hogwild","training"]
docstr: Build memory tensors.
  
  During building, will add time features to the memories if enabled.
  
  :param mems:
      list of length batchsize containing inner lists of 1D tensors
      containing the individual memories for each row in the batch.
  
  :returns:
      3d padded tensor of memories (bsz x num_mems x seqlen)
docstr_tok: ["Build","memory","tensors",".","During","building",",","will","add","time","features","to","the","memories","if","enabled",".",":","param","mems",":","list","of","length","batchsize","containing","inner","lists","of","1D","tensors","containing","the","individual","memories","for","each","row","in","the","batch",".",":","returns",":","3d","padded","tensor","of","memories","(","bsz","x","num_mems","x","seqlen",")"]
code: def _build_mems(self, mems):
      """
      Build memory tensors.
  
      During building, will add time features to the memories if enabled.
  
      :param mems:
          list of length batchsize containing inner lists of 1D tensors
          containing the individual memories for each row in the batch.
  
      :returns:
          3d padded tensor of memories (bsz x num_mems x seqlen)
      """
      if mems is None:
          return None
      bsz = len(mems)
      if bsz == 0:
          return None
  
      num_mems = max(len(mem) for mem in mems)
      if num_mems == 0 or self.memsize <= 0:
          return None
      elif num_mems > self.memsize:
          # truncate to memsize most recent memories
          num_mems = self.memsize
          mems = [mem[-self.memsize :] for mem in mems]
  
      try:
          seqlen = max(len(m) for mem in mems for m in mem)
          if self.use_time_features:
              seqlen += 1  # add time token to each sequence
      except ValueError:
          return None
  
      padded = torch.LongTensor(bsz, num_mems, seqlen).fill_(0)
  
      for i, mem in enumerate(mems):
          tf_offset = len(mem) - 1
          for j, m in enumerate(mem):
              padded[i, j, : len(m)] = m
              if self.use_time_features:
                  padded[i, j, -1] = self.dict[
                      self._time_feature(tf_offset - j)
                  ]
  
      if self.use_cuda:
          padded = padded.cuda()
  
      return padded
  
imports: from typing import Optional
  from parlai.core.params import ParlaiParser
  from parlai.core.opt import Opt
  from functools import lru_cache
  import torch
  from parlai.core.torch_ranker_agent import TorchRankerAgent
  from .modules import MemNN, opt_to_kwargs
label_desc: Use image node_id 12 for calling the MemnnAgent obj's underlying member method code with example usage: obj._build_mems(mems) and returns: padded, None, None, None, None