code: def _test_memory_efficient_logic_exp(self):
      for _t in range(10):
          self.MEoptim.zero_grad()
          for pair in self.data_set:
              y_pred = (
                  pair[0]
                  .mm(self.parameters[0])
                  .clamp(min=0)
                  .mm(self.parameters[1])
              )
              loss = (y_pred - pair[1]).pow(2).sum()
              loss = loss / len(self.data_set)
              with fp16_optimizer.scale_loss(
                  loss, self.MEoptim, delay_unscale=False
              ) as scaled_loss:
                  scaled_loss.backward()
          # Run backprop
          # Check for overflow
          self.MEoptim.loss_scaler.check_overflow(
              self.MEoptim.param_groups
          )
          # If no overflow, unscale grad and update as usual
          if not self.MEoptim.loss_scaler.is_overflow:
              self.MEoptim.loss_scaler.unscale_grads(
                  self.MEoptim.param_groups
              )
              self.MEoptim.is_scaled = False
              self.MEoptim.inner_optimizer.step()
  
          """ if use the following code, weights can have slight abrevations.
                  this shows why memory efficient optimizer works slightly differently
                  from master maintaining optimizer
                  tensor.half().float() cannot always be equal to tensor
  
              self.MEoptim.step()
              # have to transfer it back fp32 for cpu
              self.MEoptim._FP16toFP32()
              """
  
imports: from __future__ import absolute_import, division, print_function, unicode_literals
  import copy
  import unittest
  import torch
  from pytext.optimizer import fp16_optimizer
  from torch.autograd import Variable
label_desc: Use image node_id 15 for calling the TestFp16Optimizer obj's underlying member method code with example usage: obj._test_memory_efficient_logic_exp() without return types