text: '''Some helper functions for PyTorch.'''
  import os
  import sys
  import time
  import math
  
  import torch
  import torch.nn as nn
  
  
  def get_mean_and_std(dataset, max_load=10000):
      '''Compute the mean and std value of dataset.'''
      # dataloader = torch.utils.data.DataLoader(dataset, batch_size=1, shuffle=True, num_workers=2)
      mean = torch.zeros(3)
      std = torch.zeros(3)
      print('==> Computing mean and std..')
      N = min(max_load, len(dataset))
      for i in range(N):
          print(i)
          im,_,_ = dataset.load(1)
          for j in range(3):
              mean[j] += im[:,j,:,:].mean()
              std[j] += im[:,j,:,:].std()
      mean.div_(N)
      std.div_(N)
      return mean, std
  
  def mask_select(input, mask, dim=0):
      '''Select tensor rows/cols using a mask tensor.
  
      Args:
        input: (tensor) input tensor, sized [N,M].
        mask: (tensor) mask tensor, sized [N,] or [M,].
        dim: (tensor) mask dim.
  
      Returns:
        (tensor) selected rows/cols.
  
      Example:
      >>> a = torch.randn(4,2)
      >>> a
      -0.3462 -0.6930
       0.4560 -0.7459
      -0.1289 -0.9955
       1.7454  1.9787
      [torch.FloatTensor of size 4x2]
      >>> i = a[:,0] > 0
      >>> i
      0
      1
      0
      1
      [torch.ByteTensor of size 4]
      >>> masked_select(a, i, 0)
      0.4560 -0.7459
      1.7454  1.9787
      [torch.FloatTensor of size 2x2]
      '''
      index = mask.nonzero().squeeze(1)
      return input.index_select(dim, index)
  
  def meshgrid(x, y, row_major=True):
      '''Return meshgrid in range x & y.
  
      Args:
        x: (int) first dim range.
        y: (int) second dim range.
        row_major: (bool) row major or column major.
  
      Returns:
        (tensor) meshgrid, sized [x*y,2]
  
      Example:
      >> meshgrid(3,2)
      0  0
      1  0
      2  0
      0  1
      1  1
      2  1
      [torch.FloatTensor of size 6x2]
  
      >> meshgrid(3,2,row_major=False)
      0  0
      0  1
      0  2
      1  0
      1  1
      1  2
      [torch.FloatTensor of size 6x2]
      '''
      a = torch.arange(0,x) / 2.0  #v3
      b = torch.arange(0,y)        #v3
  
      xx = a.repeat(y).view(-1,1)
      yy = b.view(-1,1).repeat(1,x).view(-1,1)
      return torch.cat([xx,yy],1).float() if row_major else torch.cat([yy,xx],1).float()
  
  def change_box_order(boxes, order):
      '''Change box order between (xmin,ymin,xmax,ymax) and (xcenter,ycenter,width,height).
  
      Args:
        boxes: (tensor) bounding boxes, sized [N,4] or [N, 8] .
        order: (str) one of ['xyxy2xywh','xywh2xyxy', 'xywh2quad', 'quad2xyxy']
  
      Returns:
        (tensor) converted bounding boxes, sized [N,4] or [N,8].
      '''
      assert order in ['xyxy2xywh','xywh2xyxy', 'xywh2quad', 'quad2xyxy']
      
      if order is 'xyxy2xywh':
          a = boxes[:,:2]
          b = boxes[:,2:]
          new_boxes = torch.cat([(a+b)/2,b-a+1], 1)
          
      elif order is 'xywh2xyxy':
          a = boxes[:,:2]
          b = boxes[:,2:]
          new_boxes = torch.cat([a-b/2,a+b/2], 1)
          
      elif order is 'xywh2quad':
          x0, y0, w0, h0 = torch.split(boxes, 1, dim=1)
          
          new_boxes = torch.cat([x0-w0/2, y0-h0/2,  
                                 x0+w0/2, y0-h0/2, 
                                 x0+w0/2, y0+h0/2, 
                                 x0-w0/2, y0+h0/2], dim=1)
          
      elif order is "quad2xyxy":
          """quad : [num_boxes, 8] / rect : [num_boxes, 4] #yxyx"""
          boxes = boxes.view((-1, 4, 2))
          
          new_boxes = torch.cat([torch.min(boxes[:, :, 0:1], dim=1)[0],
                                 torch.min(boxes[:, :, 1:2], dim=1)[0],
                                 torch.max(boxes[:, :, 0:1], dim=1)[0],
                                 torch.max(boxes[:, :, 1:2], dim=1)[0]], dim=1)
      
      return new_boxes
  
  def box_iou(box1, box2):
      '''Compute the intersection over union of two set of boxes.
  
      The default box order is (xmin, ymin, xmax, ymax).
  
      Args:
        box1: (tensor) anchor_rect_boxes, sized [N,4]. xywh
        box2: (tensor) gt_rect_boxes, sized [M,4]. xyxy
  
      Return:
        (tensor) iou, sized [N,M].
  
      Reference:
        https://github.com/chainer/chainercv/blob/master/chainercv/utils/bbox/bbox_iou.py
      '''
      box1 = change_box_order(box1, 'xywh2xyxy')
  
      N = box1.size(0)
      M = box2.size(0)
  
      lt = torch.max(box1[:,None,:2], box2[:,:2])  # [N,M,2]
      rb = torch.min(box1[:,None,2:], box2[:,2:])  # [N,M,2]
  
      wh = (rb-lt+1).clamp(min=0)      # [N,M,2]
      inter = wh[:,:,0] * wh[:,:,1]  # [N,M]
  
      area1 = (box1[:,2]-box1[:,0]+1) * (box1[:,3]-box1[:,1]+1)  # [N,]
      area2 = (box2[:,2]-box2[:,0]+1) * (box2[:,3]-box2[:,1]+1)  # [M,]
      iou = inter / (area1[:,None] + area2 - inter)
  
      return iou
  
  def box_nms(bboxes, scores, threshold=0.5, mode='union'):
      '''Non maximum suppression.
  
      Args:
        bboxes: (tensor) bounding boxes, sized [N,4].
        scores: (tensor) bbox scores, sized [N,].
        threshold: (float) overlap threshold.
        mode: (str) 'union' or 'min'.
  
      Returns:
        keep: (tensor) selected indices.
  
      Reference:
        https://github.com/rbgirshick/py-faster-rcnn/blob/master/lib/nms/py_cpu_nms.py
      '''
      x1 = bboxes[:,0]
      y1 = bboxes[:,1]
      x2 = bboxes[:,2]
      y2 = bboxes[:,3]
  
      areas = (x2-x1+1) * (y2-y1+1)
      _, order = scores.sort(0, descending=True)
  
      keep = []
      while order.numel() > 0:
          i = order[0]
          keep.append(i)
  
          if order.numel() == 1:
              break
  
          xx1 = x1[order[1:]].clamp(min=x1[i])
          yy1 = y1[order[1:]].clamp(min=y1[i])
          xx2 = x2[order[1:]].clamp(max=x2[i])
          yy2 = y2[order[1:]].clamp(max=y2[i])
  
          w = (xx2-xx1+1).clamp(min=0)
          h = (yy2-yy1+1).clamp(min=0)
          inter = w*h
  
          if mode == 'union':
              ovr = inter / (areas[i] + areas[order[1:]] - inter)
          elif mode == 'min':
              ovr = inter / areas[order[1:]].clamp(max=areas[i])
          else:
              raise TypeError('Unknown nms mode: %s.' % mode)
  
          ids = (ovr<=threshold).nonzero().squeeze()
          if ids.numel() == 0:
              break
          order = order[ids+1]
      return torch.LongTensor(keep)
  
  def softmax(x):
      '''Softmax along a specific dimension.
  
      Args:
        x: (tensor) input tensor, sized [N,D].
  
      Returns:
        (tensor) softmaxed tensor, sized [N,D].
      '''
      xmax, _ = x.max(1)
      x_shift = x - xmax.view(-1,1)
      x_exp = x_shift.exp()
      return x_exp / x_exp.sum(1).view(-1,1)
  
  def one_hot_v3(batch, depth):
      emb = nn.Embedding(depth, depth)
      emb.weight.data = torch.eye(depth)
      return emb(batch)
  
  def one_hot_embedding(labels, num_classes):
      '''Embedding labels to one-hot form.
  
      Args:
        labels: (LongTensor) class labels, sized [N,].
        num_classes: (int) number of classes.
  
      Returns:
        (tensor) encoded labels, sized [N,#classes].
      '''
      y = torch.eye(num_classes)  # [D,D]
      return y[labels]            # [N,D]
  
  def msr_init(net):
      '''Initialize layer parameters.'''
      for layer in net:
          if type(layer) == nn.Conv2d:
              n = layer.kernel_size[0]*layer.kernel_size[1]*layer.out_channels
              layer.weight.data.normal_(0, math.sqrt(2./n))
              layer.bias.data.zero_()
          elif type(layer) == nn.BatchNorm2d:
              layer.weight.data.fill_(1)
              layer.bias.data.zero_()
          elif type(layer) == nn.Linear:
              layer.bias.data.zero_()
  