精华内容
下载资源
问答
  • 尝试使用了pytorch,相比其他深度学习框架,pytorch显得简洁易懂。花时间读了部分源码,主要结合简单例子带着问题阅读,不涉及源码中C拓展库的实现。 一个简单例子 实现单层softmax二分类,输入特征维度为4,输出...

    尝试使用了pytorch,相比其他深度学习框架,pytorch显得简洁易懂。花时间读了部分源码,主要结合简单例子带着问题阅读,不涉及源码中C拓展库的实现。

    一个简单例子

    实现单层softmax二分类,输入特征维度为4,输出为2,经过softmax函数得出输入的类别概率。代码示意:定义网络结构;使用SGD优化;迭代一次,随机初始化三个样例,每个样例四维特征,target分别为1,0,1;前向传播,使用交叉熵计算loss;反向传播,最后由优化算法更新权重,完成一次迭代。

    1.  
      import torch
    2.  
      import torch.nn as nn
    3.  
      import torch.nn.functional as F
    4.  
       
    5.  
      class Net(nn.Module):
    6.  
       
    7.  
      def __init__(self):
    8.  
      super(Net, self).__init__()
    9.  
      self.linear = nn.Linear( 4, 2)
    10.  
       
    11.  
      def forward(self, input):
    12.  
      out = F.softmax(self.linear(input))
    13.  
      return out
    14.  
       
    15.  
      net = Net()
    16.  
      sgd = torch.optim.SGD(net.parameters(), lr= 0.001)
    17.  
      for epoch in range(1):
    18.  
      features = torch.autograd.Variable(torch.randn( 3, 4), requires_grad=True)
    19.  
      target = torch.autograd.Variable(torch.LongTensor([ 1, 0, 1]))
    20.  
      sgd.zero_grad()
    21.  
       
    22.  
      out = net(features)
    23.  
      loss = F.cross_entropy(out, target)
    24.  
      loss.backward()
    25.  
      sgd.step()

    从上面的例子,带着下面的问题阅读源码:

    • pytorch的主要概念:Tensor、autograd、Variable、Function、Parameter、Module(Layers)、Optimizer;
    • 自定义Module如何组织网络结构和网络参数;
    • 前向传播、反向传播实现流程
    • 优化算法类如何实现,如何和自定义Module联系并更新参数。

    pytorch的主要概念

    pytorch的主要概念官网有很人性化的教程Deep Learning with PyTorch: A 60 Minute Blitz, 这里简单概括这些概念:

    Tensor

    类似numpy的ndarrays,强化了可进行GPU计算的特性,由C拓展模块实现。如上面的torch.randn(3, 4) 返回一个3*4的Tensor。和numpy一样,也有一系列的Operation,如

    1.  
      x = torch.rand( 5, 3)
    2.  
      y = torch.rand( 5, 3)
    3.  
      print x + y
    4.  
      print torch.add(x, y)
    5.  
      print x.add_(y)

    Varaiable与autograd

    Variable封装了Tensor,包括了几乎所有的Tensor可以使用的Operation方法,主要使用在自动求导(autograd),Variable类继承_C._VariableBase,由C拓展类定义实现。
    Variable是autograd的计算单元,Variable通过Function组织成函数表达式(计算图):

    • data 为其封装的tensor值
    • grad 为其求导后的值
    • creator 为创建该Variable的Function,实现中grad_fn属性则指向该Function。
      如:
      1.  
        import torch
      2.  
        from torch.autograd import Variable
      3.  
        x = Variable(torch.ones( 2, 2), requires_grad=True)
      4.  
        y = x + 2
      5.  
        print y.grad_fn
      6.  
        print "before backward: ", x.grad
      7.  
        y.backward()
      8.  
        print "after backward: ", x.grad

      输出结果:

      1.  
        < torch.autograd.function.AddConstantBackward object at 0x7faa6f3bdd68>
      2.  
        before backward: None
      3.  
        after backward: Variable containing:
      4.  
        1
      5.  
        [torch.FloatTensor of size 1x1]

      调用y的backward方法,则会对创建y的Function计算图中所有requires_grad=True的Variable求导(这里的x)。例子中显然dy/dx = 1。

    Parameter

       Parameter 为Variable的一个子类,后面还会涉及,大概两点区别:

    • 作为Module参数会被自动加入到该Module的参数列表中;
    • 不能被volatile, 默认require gradient。

    Module

    Module为所有神经网络模块的父类,如开始的例子,Net继承该类,____init____中指定网络结构中的模块,并重写forward方法实现前向传播得到指定输入的输出值,以此进行后面loss的计算和反向传播。

    Optimizer

    Optimizer是所有优化算法的父类(SGD、Adam、...),____init____中传入网络的parameters, 子类实现父类step方法,完成对parameters的更新。

    自定义Module

    该部分说明自定义的Module是如何组织定义在构造函数中的子Module,以及自定义的parameters的保存形式,eg:

    1.  
      class Net(nn.Module):
    2.  
      def __init__(self):
    3.  
      super(Net, self).__init__()
    4.  
      self.linear = nn.Linear(4, 2)
    5.  
       
    6.  
      def forward(self, input):
    7.  
      out = F.softmax( self.linear(input))
    8.  
      return out

    首先看构造函数,Module的构造函数初始化了Module的基本属性,这里关注_parameters和_modules,两个属性初始化为OrderedDict(),pytorch重写的有序字典类型。_parameters保存网络的所有参数,_modules保存当前Module的子Module。
    module.py:

    1.  
      class Module(object):
    2.  
       
    3.  
      def __init__(self):
    4.  
      self._parameters = OrderedDict()
    5.  
      self._modules = OrderedDict()
    6.  
      ...

    下面来看自定义Net类中self.linear = nn.Linear(4, 2)语句和_modules、_parameters如何产生联系,或者self.linear及其参数如何被添加到_modules、_parameters字典中。答案在Module的____setattr____方法,该Python内建方法会在类的属性被赋值时调用。
    module.py:

    1.  
      def __setattr__(self, name, value):
    2.  
      def remove_from(*dicts):
    3.  
      for d in dicts:
    4.  
      if name in d:
    5.  
      del d[name]
    6.  
       
    7.  
      params = self.__dict__.get( '_parameters')
    8.  
      if isinstance(value, Parameter): # ----------- <1>
    9.  
      if params is None:
    10.  
      raise AttributeError(
    11.  
      "cannot assign parameters before Module.__init__() call")
    12.  
      remove_from(self.__dict__, self._buffers, self._modules)
    13.  
      self.register_parameter(name, value)
    14.  
      elif params is not None and name in params:
    15.  
      if value is not None:
    16.  
      raise TypeError("cannot assign '{}' as parameter '{}' "
    17.  
      "(torch.nn.Parameter or None expected)"
    18.  
      .format(torch.typename(value), name))
    19.  
      self.register_parameter(name, value)
    20.  
      else:
    21.  
      modules = self.__dict__.get( '_modules')
    22.  
      if isinstance(value, Module):# ----------- <2>
    23.  
      if modules is None:
    24.  
      raise AttributeError(
    25.  
      "cannot assign module before Module.__init__() call")
    26.  
      remove_from(self.__dict__, self._parameters, self._buffers)
    27.  
      modules[name] = value
    28.  
      elif modules is not None and name in modules:
    29.  
      if value is not None:
    30.  
      raise TypeError("cannot assign '{}' as child module '{}' "
    31.  
      "(torch.nn.Module or None expected)"
    32.  
      .format(torch.typename(value), name))
    33.  
      modules[name] = value
    34.  
      ......
    35.  
       

    调用self.linear = nn.Linear(4, 2)时,父类____setattr____被调用,参数name为“linear”, value为nn.Linear(4, 2),内建的Linear类同样是Module的子类。所以<2>中的判断为真,接着modules[name] = value,该linear被加入_modules字典。
    同样自定义Net类的参数即为其子模块Linear的参数,下面看Linear的实现:
    linear.py:

    1.  
      class Linear(Module):
    2.  
       
    3.  
      def __init__(self, in_features, out_features, bias=True):
    4.  
      super(Linear, self).__init__()
    5.  
      self.in_features = in_features
    6.  
      self.out_features = out_features
    7.  
      self.weight = Parameter(torch.Tensor(out_features, in_features))
    8.  
      if bias:
    9.  
      self.bias = Parameter(torch.Tensor(out_features))
    10.  
      else:
    11.  
      self.register_parameter('bias', None)
    12.  
      self.reset_parameters()
    13.  
       
    14.  
      def reset_parameters(self):
    15.  
      stdv = 1. / math.sqrt(self.weight.size(1))
    16.  
      self.weight.data.uniform_(-stdv, stdv)
    17.  
      if self.bias is not None:
    18.  
      self.bias.data.uniform_(-stdv, stdv)
    19.  
       
    20.  
      def forward(self, input):
    21.  
      return F.linear(input, self.weight, self.bias)

    同样继承Module类,____init____中参数为输入输出维度,是否需要bias参数。在self.weight = Parameter(torch.Tensor(out_features, in_features))的初始化时,同样会调用父类Module的____setattr____, name为“weight”,value为Parameter,此时<1>判断为真,调用self.register_parameter(name, value),该方法中对参数进行合法性校验后放入self._parameters字典中。

    Linear在reset_parameters方法对权重进行了初始化。

    最终可以得出结论自定义的Module以树的形式组织子Module,子Module及其参数以字典的方式保存。

    前向传播、反向传播

    前向传播

    例子中out = net(features)实现了网络的前向传播,该语句会调用Module类的forward方法,该方法被继承父类的子类实现。net(features)使用对象作为函数调用,会调用Python内建的____call____方法,Module重写了该方法。

    module.py:

    1.  
      def __call__( self, *input, **kwargs):
    2.  
      for hook in self._forward_pre_hooks.values():
    3.  
      hook( self, input)
    4.  
      result = self.forward(*input, **kwargs)
    5.  
      for hook in self._forward_hooks.values():
    6.  
      hook_result = hook( self, input, result)
    7.  
      if hook_result is not None:
    8.  
      raise RuntimeError(
    9.  
      "forward hooks should never return any values, but '{}'"
    10.  
      "didn't return None".format(hook))
    11.  
      if len(self._backward_hooks) > 0:
    12.  
      var = result
    13.  
      while not isinstance(var, Variable):
    14.  
      var = var[0]
    15.  
      grad_fn = var.grad_fn
    16.  
      if grad_fn is not None:
    17.  
      for hook in self._backward_hooks.values():
    18.  
      wrapper = functools.partial(hook, self)
    19.  
      functools.update_wrapper(wrapper, hook)
    20.  
      grad_fn.register_hook(wrapper)
    21.  
      return result

    ____call____方法中调用result = self.forward(*input, **kwargs)前后会查看有无hook函数需要调用(预处理和后处理)。
    例子中Net的forward方法中out = F.softmax(self.linear(input)),同样会调用self.linear的forward方法F.linear(input, self.weight, self.bias)进行矩阵运算(仿射变换)。
    functional.py:

    1.  
      def linear(input, weight, bias=None):
    2.  
      if input.dim() == 2 and bias is not None:
    3.  
      # fused op is marginally faster
    4.  
      return torch.addmm(bias, input, weight.t())
    5.  
       
    6.  
      output = input.matmul(weight.t())
    7.  
      if bias is not None:
    8.  
      output += bias
    9.  
      return output

    最终经过F.softmax,得到前向输出结果。F.softmax和F.linear类似前面说到的Function(Parameters的表达式或计算图)。

    反向传播

    得到前向传播结果后,计算loss = F.cross_entropy(out, target),接下来反向传播求导数d(loss)/d(weight)和d(loss)/d(bias):

    loss.backward()
    

    backward()方法同样底层由C拓展,这里暂不深入,调用该方法后,loss计算图中的所有Variable(这里linear的weight和bias)的grad被求出。

    Optimizer参数更新

    在计算出参数的grad后,需要根据优化算法对参数进行更新,不同的优化算法有不同的更新策略。
    optimizer.py:

    1.  
      class Optimizer(object):
    2.  
       
    3.  
      def __init__(self, params, defaults):
    4.  
      if isinstance(params, Variable) or torch.is_tensor(params):
    5.  
      raise TypeError("params argument given to the optimizer should be "
    6.  
      "an iterable of Variables or dicts, but got " +
    7.  
      torch.typename(params))
    8.  
       
    9.  
      self.state = defaultdict(dict)
    10.  
      self.param_groups = list(params)
    11.  
      ......
    12.  
       
    13.  
      def zero_grad(self):
    14.  
      """Clears the gradients of all optimized :class:`Variable` s."""
    15.  
      for group in self.param_groups:
    16.  
      for p in group['params']:
    17.  
      if p.grad is not None:
    18.  
      if p.grad.volatile:
    19.  
      p.grad.data.zero_()
    20.  
      else:
    21.  
      data = p.grad.data
    22.  
      p.grad = Variable(data.new().resize_as_(data).zero_())
    23.  
       
    24.  
      def step(self, closure):
    25.  
      """Performs a single optimization step (parameter update).
    26.  
       
    27.  
      Arguments:
    28.  
      closure (callable): A closure that reevaluates the model and
    29.  
      returns the loss. Optional for most optimizers.
    30.  
      """
    31.  
      raise NotImplementedError

    Optimizer在init中将传入的params保存到self.param_groups,另外两个重要的方法zero_grad负责将参数的grad置零方便下次计算,step负责参数的更新,由子类实现。
    以列子中的sgd = torch.optim.SGD(net.parameters(), lr=0.001)为例,其中net.parameters()返回Net参数的迭代器,为待优化参数;lr指定学习率。
    SGD.py:

    1.  
      class SGD(Optimizer):
    2.  
       
    3.  
      def __init__(self, params, lr=required, momentum=0, dampening=0,
    4.  
      weight_decay=0, nesterov=False):
    5.  
      defaults = dict(lr=lr, momentum=momentum, dampening=dampening,
    6.  
      weight_decay=weight_decay, nesterov=nesterov)
    7.  
      if nesterov and (momentum <= 0 or dampening != 0):
    8.  
      raise ValueError("Nesterov momentum requires a momentum and zero dampening")
    9.  
      super(SGD, self).__init__(params, defaults)
    10.  
       
    11.  
      def __setstate__(self, state):
    12.  
      super(SGD, self).__setstate__(state)
    13.  
      for group in self.param_groups:
    14.  
      group.setdefault( 'nesterov', False)
    15.  
       
    16.  
      def step(self, closure=None):
    17.  
      """Performs a single optimization step.
    18.  
       
    19.  
      Arguments:
    20.  
      closure (callable, optional): A closure that reevaluates the model
    21.  
      and returns the loss.
    22.  
      """
    23.  
      loss = None
    24.  
      if closure is not None:
    25.  
      loss = closure()
    26.  
       
    27.  
      for group in self.param_groups:
    28.  
      weight_decay = group[ 'weight_decay']
    29.  
      momentum = group[ 'momentum']
    30.  
      dampening = group[ 'dampening']
    31.  
      nesterov = group[ 'nesterov']
    32.  
       
    33.  
      for p in group['params']:
    34.  
      if p.grad is None:
    35.  
      continue
    36.  
      d_p = p.grad.data
    37.  
      if weight_decay != 0:
    38.  
      d_p.add_(weight_decay, p.data)
    39.  
      if momentum != 0:
    40.  
      param_state = self.state[p]
    41.  
      if 'momentum_buffer' not in param_state:
    42.  
      buf = param_state[ 'momentum_buffer'] = d_p.clone()
    43.  
      else:
    44.  
      buf = param_state[ 'momentum_buffer']
    45.  
      buf.mul_(momentum).add_( 1 - dampening, d_p)
    46.  
      if nesterov:
    47.  
      d_p = d_p.add(momentum, buf)
    48.  
      else:
    49.  
      d_p = buf
    50.  
       
    51.  
      p.data.add_(-group[ 'lr'], d_p)
    52.  
       
    53.  
      return loss
    54.  
       

    SGD的step方法中,判断是否使用权重衰减和动量更新,如果不使用,直接更新权重param := param - lr * d(param)。例子中调用sgd.step()后完成一次epoch。这里由于传递到Optimizer的参数集是可更改(mutable)的,step中对参数的更新同样是Net中参数的更新。

    小结

    到此,根据一个简单例子阅读了pytorch中Python实现的部分源码,没有深入到底层Tensor、autograd等部分的C拓展实现,后面再继续读一读C拓展部分的代码。


    转自链接:https://www.jianshu.com/p/f5eb8c2e671c

    转载于:https://www.cnblogs.com/jfdwd/p/11434087.html

    展开全文
  • wtalc-pytorch源码解析

    2020-10-28 16:05:49
    wtalc-pytorch源码解析 论文名:W-TALC: Weakly-supervised Temporal Activity Localization and Classification 代码链接:https://github.com/sujoyp/wtalc-pytorch 代码的主要结构如下: python file function...

    wtalc-pytorch源码解析

    论文名:W-TALC: Weakly-supervised Temporal Activity Localization and Classification

    代码链接:https://github.com/sujoyp/wtalc-pytorch

    代码的主要结构如下:

    python filefunction
    main.py主函数
    options.py参数配置
    video_dataset.py数据集分类与载入
    model.py弱监督层模型
    train.py训练代码
    test.py测试代码
    detectionMAP.pymap
    classificationMAP.py分类的map

    1.opts.py是参数配置。

    parser = argparse.ArgumentParser(description='WTALC')
    parser.add_argument('--lr', type=float, default=0.00001,help='learning rate (default: 0.0001)')
    parser.add_argument('--batch-size', type=int, default=10, help='number of instances in a batch of data (default: 10)')
    parser.add_argument('--model-name', default='weakloc', help='name to save model')
    parser.add_argument('--pretrained-ckpt', default=None, help='ckpt for pretrained model')
    parser.add_argument('--feature-size', default=2048, help='size of feature (default: 2048)')
    parser.add_argument('--num-class', default=20, help='number of classes (default: )')
    parser.add_argument('--dataset-name', default='Thumos14reduced', help='dataset to train on (default: )')
    parser.add_argument('--max-seqlen', type=int, default=1200, help='maximum sequence length during training (default: 750)')
    parser.add_argument('--Lambda', type=float, default=0.5, help='weight on Co-Activity Loss (default: 0.5)')
    parser.add_argument('--num-similar', default=3, help='number of similar pairs in a batch of data  (default: 3)')
    parser.add_argument('--seed', type=int, default=1, help='random seed (default: 1)')
    parser.add_argument('--max-iter', type=int, default=100000, help='maximum iteration to train (default: 50000)')
    parser.add_argument('--feature-type', type=str, default='I3D', help='type of feature to be used I3D or UNT (default: I3D)')
    

    –lr 学习率

    –batch-size

    –model-name 保存的模型名

    –pretrained-ckpt 预训练模型

    –feature-size 特征维度

    –num-class 类别数

    –dataset-name 数据集名称

    –max-seqlen 在训练期间最大的序列长度

    –Lambda Co-Activity Loss占总损失的权重

    –num-similar 一个batch中视频相似对

    –max-iter 训练周期

    –feature-type 提取的特征用的模型

    2.video_dataset.py是数据集分类和载入部分

    2.1 init()

    init()首先获取本数据集的一些配置,然后调用train_test_idx()函数和classwise_feature_mapping()函数。

    2.2 train_test_idx()

    train_test_idx()的功能以序号的形式分为训练集和测试集

        def train_test_idx(self):
            for i, s in enumerate(self.subset):
                if s.decode('utf-8') == 'validation':   # Specific to Thumos14
                    self.trainidx.append(i)  # 训练集序号
                else:
                    self.testidx.append(i)  # 测试集序号
    

    2.3 classwise_feature_mapping()

    classwise_feature_mapping()对数据集视频进行归类

        def classwise_feature_mapping(self):
            for category in self.classlist:
                idx = [] # 一个类别的视频序号添加到一个idx中
                for i in self.trainidx:
                    for label in self.labels[i]:
                        if label == category.decode('utf-8'):
                            idx.append(i); break;
                self.classwiseidx.append(idx)
    

    2.4 load_data()

    load_data()的主要功能是获取相似视频对,最后返回5个视频对的特征矩阵和label

        def load_data(self, n_similar=3, is_training=True):
            if is_training==True:
                features = []
                labels = []
                idx = []
    
                # Load similar pairs-->3对相似的视频对
                rand_classid = np.random.choice(len(self.classwiseidx), size=n_similar)
                
                # 加载一对相似的视频
                for rid in rand_classid:
                    rand_sampleid = np.random.choice(len(self.classwiseidx[rid]), size=2)
                    idx.append(self.classwiseidx[rid][rand_sampleid[0]])
                    idx.append(self.classwiseidx[rid][rand_sampleid[1]])
    
                # idx = [6,]-->idx[10,]
                # Load rest pairs-->随机又生成2个视频对?并且不一定是相似的  有什么用
                rand_sampleid = np.random.choice(len(self.trainidx), size=self.batch_size-2*n_similar)
    
                for r in rand_sampleid:
                    idx.append(self.trainidx[r])
                # 返回5个视频对的特征矩阵和label
                return np.array([utils.process_feat(self.features[i], self.t_max) for i in idx]), np.array([self.labels_multihot[i] for i in idx])
    
            else:
                labs = self.labels_multihot[self.testidx[self.currenttestidx]]
                feat = self.features[self.testidx[self.currenttestidx]]
    
                if self.currenttestidx == len(self.testidx)-1:
                    done = True; self.currenttestidx = 0
                else:
                    done = False; self.currenttestidx += 1
             
                return np.array(feat), np.array(labs), done
    
    

    3.mdel.py是模型部分

    model.py的功能主要是实现弱监督层模块的模型(很简单,看源码与论文的弱监督公式相对应即可)。

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-sniWRnPJ-1603872318456)(C:\Users\shan\AppData\Roaming\Typora\typora-user-images\image-20201028153100513.png)]

    class Model(torch.nn.Module):
        def __init__(self, n_feature, n_class):
            super(Model, self).__init__()
    
            self.fc = nn.Linear(n_feature, n_feature)
            self.fc1 = nn.Linear(n_feature, n_feature)
            self.classifier = nn.Linear(n_feature, n_class)
            self.dropout = nn.Dropout(0.7)
    
            self.apply(weights_init)
    
            #self.train()
    
        def forward(self, inputs, is_training=True):
    
            x = F.relu(self.fc(inputs))
            if is_training:
                x = self.dropout(x)
            #x = F.relu(self.fc1(x))
            #if is_training:
            #    x = self.dropout(x)
    
            
            return x, self.classifier(x)
    

    4.train.py是训练模块

    train.py的主要部分是求多实例损失和 Co-Activity Similiarity损失

    4.1 MILL()是多实例损失函数

    def MILL(element_logits, seq_len, batch_size, labels, device):
        ''' element_logits should be torch tensor of dimension (B, n_element, n_class),
             k should be numpy array of dimension (B,) indicating the top k locations to average over, 
             labels should be a numpy array of dimension (B, n_class) of 1 or 0
             return is a torch tensor of dimension (B, n_class) '''
        print('******************************')
        # [18 68 20 43 68 22 16 37 42 37]
        k = np.ceil(seq_len/8).astype('int32')
        labels = labels / torch.sum(labels, dim=1, keepdim=True)
        instance_logits = torch.zeros(0).to(device)
       
    
        for i in range(batch_size):
            # 取batch_size的第i批次的前seq_len[i]行,在第0个维度进行排序,取一个视频特征相对突出的前k行特征
            tmp, _ = torch.topk(element_logits[i][:seq_len[i]], k=int(k[i]), dim=0)  # [seq_len[i], 20]
    
            instance_logits = torch.cat([instance_logits, torch.mean(tmp, 0, keepdim=True)], dim=0)  # [1,20]
        # 套论文公式求出millloss 
        milloss = -torch.mean(torch.sum(Variable(labels) * F.log_softmax(instance_logits, dim=1), dim=1), dim=0)
      
        return milloss
    

    4.2 CASL()是Co-Activity Similiarity损失函数

    def CASL(x, element_logits, seq_len, n_similar, labels, device):
        ''' x is the torch tensor of feature from the last layer of model of dimension (n_similar, n_element, n_feature), 
            element_logits should be torch tensor of dimension (n_similar, n_element, n_class) 
            seq_len should be numpy array of dimension (B,)
            labels should be a numpy array of dimension (B, n_class) of 1 or 0 '''
    
        sim_loss = 0.
        n_tmp = 0.
        for i in range(0, n_similar*2, 2):
            # 使用softmax对每个视频类的激活分数沿时间轴进行标准化
            atn1 = F.softmax(element_logits[i][:seq_len[i]], dim=0)
            atn2 = F.softmax(element_logits[i+1][:seq_len[i+1]], dim=0)
    
            n1 = torch.FloatTensor([np.maximum(seq_len[i]-1, 1)]).to(device)
            n2 = torch.FloatTensor([np.maximum(seq_len[i+1]-1, 1)]).to(device)
            # 首先定义高、低attention区域的类的特征向量
            Hf1 = torch.mm(torch.transpose(x[i][:seq_len[i]], 1, 0), atn1)
            Hf2 = torch.mm(torch.transpose(x[i+1][:seq_len[i+1]], 1, 0), atn2)
            Lf1 = torch.mm(torch.transpose(x[i][:seq_len[i]], 1, 0), (1 - atn1)/n1)
            Lf2 = torch.mm(torch.transpose(x[i+1][:seq_len[i+1]], 1, 0), (1 - atn2)/n2)
    	    # 使用余弦相似度来衡量两个特征向量之间的相似度
            d1 = 1 - torch.sum(Hf1*Hf2, dim=0) / (torch.norm(Hf1, 2, dim=0) * torch.norm(Hf2, 2, dim=0))
            d2 = 1 - torch.sum(Hf1*Lf2, dim=0) / (torch.norm(Hf1, 2, dim=0) * torch.norm(Lf2, 2, dim=0))
            d3 = 1 - torch.sum(Hf2*Lf1, dim=0) / (torch.norm(Hf2, 2, dim=0) * torch.norm(Lf1, 2, dim=0))
    		# 为了加强上述两个性质,使用了rank hinge loss
            sim_loss = sim_loss + 0.5*torch.sum(torch.max(d1-d2+0.5, torch.FloatTensor([0.]).to(device))*Variable(labels[i,:])*Variable(labels[i+1,:]))
            sim_loss = sim_loss + 0.5*torch.sum(torch.max(d1-d3+0.5, torch.FloatTensor([0.]).to(device))*Variable(labels[i,:])*Variable(labels[i+1,:]))
            n_tmp = n_tmp + torch.sum(Variable(labels[i,:])*Variable(labels[i+1,:]))
        # 整个训练集的总损失
        sim_loss = sim_loss / n_tmp
        return sim_loss
    

    5.test.py是测试模块

    test.py的主要公式是调用dmAP()函数和cmAP()分别求map和分类的map

    对于map的理解参考链接如下:https://blog.csdn.net/better_boy/article/details/109334234

    6.main.py

    最后我们来讲解主函数,将上述的类和函数串联起来。

    6.1 获取参数配置

    args = options.parser.parse_args()
    

    6.2 加载数据集

     dataset = Dataset(args)
    

    6.3 实例化好模型和参数

    model = Model(dataset.feature_size, dataset.num_class).to(device)
    optimizer = optim.Adam(model.parameters(), lr=args.lr, weight_decay=0.0005)
    

    6.4 然后开始每个epoch迭代,调用训练函数和测试函数并保存每500次迭代的模型

        for itr in range(args.max_iter):
           train(itr, dataset, args, model, optimizer, logger, device)
           if  itr % 5 == 0 and not itr == 0:
              torch.save(model.state_dict(), './ckpt/' + args.model_name + '.pkl')
              test(itr, dataset, args, model, logger, device)
    

    7.函数调用图

    在这里插入图片描述

    展开全文
  • pytorch源码解析

    2019-04-18 19:37:19
    optimizer.py │ ├── pycache │ ├── rmsprop.py │ ├── rprop.py │ ├── sgd.py │ └── sparse_adam.py ├── pycache │ ├── functional.cpython-36.pyc │ ├── hub.cpython-...

    torch /// -tree -L 1

    .
    ├── autograd
    ├── backends
    ├── _C.cpython-36m-x86_64-linux-gnu.so
    ├── contrib
    ├── cuda
    ├── distributed
    ├── distributions
    ├── _dl.cpython-36m-x86_64-linux-gnu.so
    ├── for_onnx
    ├── functional.py
    ├── hub.py
    ├── init.py
    ├── init.pyi
    ├── jit
    ├── _jit_internal.py
    ├── lib
    ├── multiprocessing
    ├── nn
    ├── onnx
    ├── _ops.py
    ├── optim
    ├── pycache
    ├── random.py
    ├── serialization.py
    ├── share
    ├── _six.py
    ├── sparse
    ├── _storage_docs.py
    ├── storage.py
    ├── _tensor_docs.py
    ├── tensor.py
    ├── _tensor_str.py
    ├── testing
    ├── _thnn
    ├── _torch_docs.py
    ├── utils
    ├── _utils_internal.py
    ├── _utils.py
    └── version.py

    19 directories, 20 files

    torch /// -tree -L 2

    .
    ├── autograd
    │ ├── anomaly_mode.py
    │ ├── function.py
    │ ├── _functions
    │ ├── gradcheck.py
    │ ├── grad_mode.py
    │ ├── init.py
    │ ├── profiler.py
    │ ├── pycache
    │ └── variable.py
    ├── backends
    │ ├── cuda
    │ ├── cudnn
    │ ├── init.py
    │ ├── mkl
    │ └── pycache
    ├── _C.cpython-36m-x86_64-linux-gnu.so
    ├── contrib
    │ ├── _graph_vis.py
    │ ├── init.py
    │ ├── pycache
    │ └── _tensorboard_vis.py
    ├── cuda
    │ ├── comm.py
    │ ├── error.py
    │ ├── init.py
    │ ├── nccl.py
    │ ├── nvtx.py
    │ ├── profiler.py
    │ ├── pycache
    │ ├── random.py
    │ ├── sparse.py
    │ ├── streams.py
    │ └── _utils.py
    ├── distributed
    │ ├── deprecated
    │ ├── distributed_c10d.py
    │ ├── init.py
    │ ├── launch.py
    │ ├── pycache
    │ └── rendezvous.py
    ├── distributions
    │ ├── bernoulli.py
    │ ├── beta.py
    │ ├── binomial.py
    │ ├── categorical.py
    │ ├── cauchy.py
    │ ├── chi2.py
    │ ├── constraint_registry.py
    │ ├── constraints.py
    │ ├── dirichlet.py
    │ ├── distribution.py
    │ ├── exp_family.py
    │ ├── exponential.py
    │ ├── fishersnedecor.py
    │ ├── gamma.py
    │ ├── geometric.py
    │ ├── gumbel.py
    │ ├── half_cauchy.py
    │ ├── half_normal.py
    │ ├── independent.py
    │ ├── init.py
    │ ├── kl.py
    │ ├── laplace.py
    │ ├── logistic_normal.py
    │ ├── log_normal.py
    │ ├── lowrank_multivariate_normal.py
    │ ├── multinomial.py
    │ ├── multivariate_normal.py
    │ ├── negative_binomial.py
    │ ├── normal.py
    │ ├── one_hot_categorical.py
    │ ├── pareto.py
    │ ├── poisson.py
    │ ├── pycache
    │ ├── relaxed_bernoulli.py
    │ ├── relaxed_categorical.py
    │ ├── studentT.py
    │ ├── transformed_distribution.py
    │ ├── transforms.py
    │ ├── uniform.py
    │ ├── utils.py
    │ └── weibull.py
    ├── _dl.cpython-36m-x86_64-linux-gnu.so
    ├── for_onnx
    │ ├── init.py
    │ └── pycache
    ├── functional.py
    ├── hub.py
    ├── init.py
    ├── init.pyi
    ├── jit
    │ ├── annotations.py
    │ ├── batchop.py
    │ ├── frontend.py
    │ ├── init.py
    │ ├── pycache
    │ └── supported_ops.py
    ├── _jit_internal.py
    ├── lib
    │ ├── include
    │ ├── libc10.so
    │ ├── libcaffe2_detectron_ops.so
    │ ├── libcaffe2_module_test_dynamic.so
    │ ├── libcaffe2_observers.so
    │ ├── libcaffe2.so
    │ ├── libonnxifi_dummy.so
    │ ├── libonnxifi.so
    │ ├── libshm.so
    │ ├── libtorch_python.so
    │ ├── libtorch.so
    │ ├── libtorch.so.1
    │ ├── THCUNN.h
    │ ├── THNN.h
    │ └── torch_shm_manager
    ├── multiprocessing
    │ ├── init.py
    │ ├── pool.py
    │ ├── pycache
    │ ├── queue.py
    │ ├── reductions.py
    │ └── spawn.py
    ├── nn
    │ ├── backends
    │ ├── functional.py
    │ ├── _functions
    │ ├── grad.py
    │ ├── init.py
    │ ├── init.py
    │ ├── modules
    │ ├── parallel
    │ ├── parameter.py
    │ ├── pycache
    │ ├── _reduction.py
    │ ├── utils
    │ └── _VF.py
    ├── onnx
    │ ├── init.py
    │ ├── operators.py
    │ ├── pycache
    │ ├── symbolic.py
    │ └── utils.py
    ├── _ops.py
    ├── optim
    │ ├── adadelta.py
    │ ├── adagrad.py
    │ ├── adamax.py
    │ ├── adam.py
    │ ├── asgd.py
    │ ├── init.py
    │ ├── lbfgs.py
    │ ├── lr_scheduler.py
    │ ├── optimizer.py
    │ ├── pycache
    │ ├── rmsprop.py
    │ ├── rprop.py
    │ ├── sgd.py
    │ └── sparse_adam.py
    ├── pycache
    │ ├── functional.cpython-36.pyc
    │ ├── hub.cpython-36.pyc
    │ ├── init.cpython-36.pyc
    │ ├── _jit_internal.cpython-36.pyc
    │ ├── _ops.cpython-36.pyc
    │ ├── random.cpython-36.pyc
    │ ├── serialization.cpython-36.pyc
    │ ├── _six.cpython-36.pyc
    │ ├── storage.cpython-36.pyc
    │ ├── _storage_docs.cpython-36.pyc
    │ ├── tensor.cpython-36.pyc
    │ ├── _tensor_docs.cpython-36.pyc
    │ ├── _tensor_str.cpython-36.pyc
    │ ├── _torch_docs.cpython-36.pyc
    │ ├── _utils.cpython-36.pyc
    │ ├── _utils_internal.cpython-36.pyc
    │ └── version.cpython-36.pyc
    ├── random.py
    ├── serialization.py
    ├── share
    │ └── cmake
    ├── _six.py
    ├── sparse
    │ ├── init.py
    │ └── pycache
    ├── _storage_docs.py
    ├── storage.py
    ├── _tensor_docs.py
    ├── tensor.py
    ├── _tensor_str.py
    ├── testing
    │ ├── init.py
    │ └── pycache
    ├── _thnn
    │ ├── init.py
    │ ├── pycache
    │ └── utils.py
    ├── _torch_docs.py
    ├── utils
    │ ├── backcompat
    │ ├── bottleneck
    │ ├── checkpoint.py
    │ ├── collect_env.py
    │ ├── cpp_extension.py
    │ ├── _cpp_extension_versioner.py
    │ ├── data
    │ ├── dlpack.py
    │ ├── ffi
    │ ├── file_baton.py
    │ ├── hooks.py
    │ ├── init.py
    │ ├── model_zoo.py
    │ └── pycache
    ├── _utils_internal.py
    ├── _utils.py
    └── version.py

    51 directories, 164 files

    torch /// -tree -L 3

    .
    ├── autograd
    │ ├── anomaly_mode.py
    │ ├── function.py
    │ ├── _functions
    │ │ ├── init.py
    │ │ ├── pycache
    │ │ ├── tensor.py
    │ │ └── utils.py
    │ ├── gradcheck.py
    │ ├── grad_mode.py
    │ ├── init.py
    │ ├── profiler.py
    │ ├── pycache
    │ │ ├── anomaly_mode.cpython-36.pyc
    │ │ ├── function.cpython-36.pyc
    │ │ ├── gradcheck.cpython-36.pyc
    │ │ ├── grad_mode.cpython-36.pyc
    │ │ ├── init.cpython-36.pyc
    │ │ ├── profiler.cpython-36.pyc
    │ │ └── variable.cpython-36.pyc
    │ └── variable.py
    ├── backends
    │ ├── cuda
    │ │ ├── init.py
    │ │ └── pycache
    │ ├── cudnn
    │ │ ├── init.py
    │ │ ├── pycache
    │ │ └── rnn.py
    │ ├── init.py
    │ ├── mkl
    │ │ ├── init.py
    │ │ └── pycache
    │ └── pycache
    │ └── init.cpython-36.pyc
    ├── _C.cpython-36m-x86_64-linux-gnu.so
    ├── contrib
    │ ├── _graph_vis.py
    │ ├── init.py
    │ ├── pycache
    │ │ ├── _graph_vis.cpython-36.pyc
    │ │ ├── init.cpython-36.pyc
    │ │ └── _tensorboard_vis.cpython-36.pyc
    │ └── _tensorboard_vis.py
    ├── cuda
    │ ├── comm.py
    │ ├── error.py
    │ ├── init.py
    │ ├── nccl.py
    │ ├── nvtx.py
    │ ├── profiler.py
    │ ├── pycache
    │ │ ├── comm.cpython-36.pyc
    │ │ ├── error.cpython-36.pyc
    │ │ ├── init.cpython-36.pyc
    │ │ ├── nccl.cpython-36.pyc
    │ │ ├── nvtx.cpython-36.pyc
    │ │ ├── profiler.cpython-36.pyc
    │ │ ├── random.cpython-36.pyc
    │ │ ├── sparse.cpython-36.pyc
    │ │ ├── streams.cpython-36.pyc
    │ │ └── _utils.cpython-36.pyc
    │ ├── random.py
    │ ├── sparse.py
    │ ├── streams.py
    │ └── _utils.py
    ├── distributed
    │ ├── deprecated
    │ │ ├── init.py
    │ │ ├── pycache
    │ │ └── remote_types.py
    │ ├── distributed_c10d.py
    │ ├── init.py
    │ ├── launch.py
    │ ├── pycache
    │ │ ├── distributed_c10d.cpython-36.pyc
    │ │ ├── init.cpython-36.pyc
    │ │ ├── launch.cpython-36.pyc
    │ │ └── rendezvous.cpython-36.pyc
    │ └── rendezvous.py
    ├── distributions
    │ ├── bernoulli.py
    │ ├── beta.py
    │ ├── binomial.py
    │ ├── categorical.py
    │ ├── cauchy.py
    │ ├── chi2.py
    │ ├── constraint_registry.py
    │ ├── constraints.py
    │ ├── dirichlet.py
    │ ├── distribution.py
    │ ├── exp_family.py
    │ ├── exponential.py
    │ ├── fishersnedecor.py
    │ ├── gamma.py
    │ ├── geometric.py
    │ ├── gumbel.py
    │ ├── half_cauchy.py
    │ ├── half_normal.py
    │ ├── independent.py
    │ ├── init.py
    │ ├── kl.py
    │ ├── laplace.py
    │ ├── logistic_normal.py
    │ ├── log_normal.py
    │ ├── lowrank_multivariate_normal.py
    │ ├── multinomial.py
    │ ├── multivariate_normal.py
    │ ├── negative_binomial.py
    │ ├── normal.py
    │ ├── one_hot_categorical.py
    │ ├── pareto.py
    │ ├── poisson.py
    │ ├── pycache
    │ │ ├── bernoulli.cpython-36.pyc
    │ │ ├── beta.cpython-36.pyc
    │ │ ├── binomial.cpython-36.pyc
    │ │ ├── categorical.cpython-36.pyc
    │ │ ├── cauchy.cpython-36.pyc
    │ │ ├── chi2.cpython-36.pyc
    │ │ ├── constraint_registry.cpython-36.pyc
    │ │ ├── constraints.cpython-36.pyc
    │ │ ├── dirichlet.cpython-36.pyc
    │ │ ├── distribution.cpython-36.pyc
    │ │ ├── exp_family.cpython-36.pyc
    │ │ ├── exponential.cpython-36.pyc
    │ │ ├── fishersnedecor.cpython-36.pyc
    │ │ ├── gamma.cpython-36.pyc
    │ │ ├── geometric.cpython-36.pyc
    │ │ ├── gumbel.cpython-36.pyc
    │ │ ├── half_cauchy.cpython-36.pyc
    │ │ ├── half_normal.cpython-36.pyc
    │ │ ├── independent.cpython-36.pyc
    │ │ ├── init.cpython-36.pyc
    │ │ ├── kl.cpython-36.pyc
    │ │ ├── laplace.cpython-36.pyc
    │ │ ├── logistic_normal.cpython-36.pyc
    │ │ ├── log_normal.cpython-36.pyc
    │ │ ├── lowrank_multivariate_normal.cpython-36.pyc
    │ │ ├── multinomial.cpython-36.pyc
    │ │ ├── multivariate_normal.cpython-36.pyc
    │ │ ├── negative_binomial.cpython-36.pyc
    │ │ ├── normal.cpython-36.pyc
    │ │ ├── one_hot_categorical.cpython-36.pyc
    │ │ ├── pareto.cpython-36.pyc
    │ │ ├── poisson.cpython-36.pyc
    │ │ ├── relaxed_bernoulli.cpython-36.pyc
    │ │ ├── relaxed_categorical.cpython-36.pyc
    │ │ ├── studentT.cpython-36.pyc
    │ │ ├── transformed_distribution.cpython-36.pyc
    │ │ ├── transforms.cpython-36.pyc
    │ │ ├── uniform.cpython-36.pyc
    │ │ ├── utils.cpython-36.pyc
    │ │ └── weibull.cpython-36.pyc
    │ ├── relaxed_bernoulli.py
    │ ├── relaxed_categorical.py
    │ ├── studentT.py
    │ ├── transformed_distribution.py
    │ ├── transforms.py
    │ ├── uniform.py
    │ ├── utils.py
    │ └── weibull.py
    ├── _dl.cpython-36m-x86_64-linux-gnu.so
    ├── for_onnx
    │ ├── init.py
    │ └── pycache
    │ └── init.cpython-36.pyc
    ├── functional.py
    ├── hub.py
    ├── init.py
    ├── init.pyi
    ├── jit
    │ ├── annotations.py
    │ ├── batchop.py
    │ ├── frontend.py
    │ ├── init.py
    │ ├── pycache
    │ │ ├── annotations.cpython-36.pyc
    │ │ ├── batchop.cpython-36.pyc
    │ │ ├── frontend.cpython-36.pyc
    │ │ ├── init.cpython-36.pyc
    │ │ └── supported_ops.cpython-36.pyc
    │ └── supported_ops.py
    ├── _jit_internal.py
    ├── lib
    │ ├── include
    │ │ ├── ATen
    │ │ ├── c10
    │ │ ├── caffe2
    │ │ ├── pybind11
    │ │ ├── TH
    │ │ └── torch
    │ ├── libc10.so
    │ ├── libcaffe2_detectron_ops.so
    │ ├── libcaffe2_module_test_dynamic.so
    │ ├── libcaffe2_observers.so
    │ ├── libcaffe2.so
    │ ├── libonnxifi_dummy.so
    │ ├── libonnxifi.so
    │ ├── libshm.so
    │ ├── libtorch_python.so
    │ ├── libtorch.so
    │ ├── libtorch.so.1
    │ ├── THCUNN.h
    │ ├── THNN.h
    │ └── torch_shm_manager
    ├── multiprocessing
    │ ├── init.py
    │ ├── pool.py
    │ ├── pycache
    │ │ ├── init.cpython-36.pyc
    │ │ ├── pool.cpython-36.pyc
    │ │ ├── queue.cpython-36.pyc
    │ │ ├── reductions.cpython-36.pyc
    │ │ └── spawn.cpython-36.pyc
    │ ├── queue.py
    │ ├── reductions.py
    │ └── spawn.py
    ├── nn
    │ ├── backends
    │ │ ├── backend.py
    │ │ ├── init.py
    │ │ ├── pycache
    │ │ └── thnn.py
    │ ├── functional.py
    │ ├── _functions
    │ │ ├── init.py
    │ │ ├── pycache
    │ │ ├── thnn
    │ │ └── vision.py
    │ ├── grad.py
    │ ├── init.py
    │ ├── init.py
    │ ├── modules
    │ │ ├── activation.py
    │ │ ├── adaptive.py
    │ │ ├── batchnorm.py
    │ │ ├── container.py
    │ │ ├── conv.py
    │ │ ├── distance.py
    │ │ ├── dropout.py
    │ │ ├── fold.py
    │ │ ├── init.py
    │ │ ├── instancenorm.py
    │ │ ├── linear.py
    │ │ ├── loss.py
    │ │ ├── module.py
    │ │ ├── normalization.py
    │ │ ├── padding.py
    │ │ ├── pixelshuffle.py
    │ │ ├── pooling.py
    │ │ ├── pycache
    │ │ ├── rnn.py
    │ │ ├── sparse.py
    │ │ ├── upsampling.py
    │ │ └── utils.py
    │ ├── parallel
    │ │ ├── data_parallel.py
    │ │ ├── deprecated
    │ │ ├── distributed_cpu.py
    │ │ ├── distributed.py
    │ │ ├── _functions.py
    │ │ ├── init.py
    │ │ ├── parallel_apply.py
    │ │ ├── pycache
    │ │ ├── replicate.py
    │ │ └── scatter_gather.py
    │ ├── parameter.py
    │ ├── pycache
    │ │ ├── functional.cpython-36.pyc
    │ │ ├── grad.cpython-36.pyc
    │ │ ├── init.cpython-36.pyc
    │ │ ├── init.cpython-36.pyc
    │ │ ├── parameter.cpython-36.pyc
    │ │ ├── _reduction.cpython-36.pyc
    │ │ └── _VF.cpython-36.pyc
    │ ├── _reduction.py
    │ ├── utils
    │ │ ├── clip_grad.py
    │ │ ├── convert_parameters.py
    │ │ ├── init.py
    │ │ ├── pycache
    │ │ ├── rnn.py
    │ │ ├── spectral_norm.py
    │ │ └── weight_norm.py
    │ └── _VF.py
    ├── onnx
    │ ├── init.py
    │ ├── operators.py
    │ ├── pycache
    │ │ ├── init.cpython-36.pyc
    │ │ ├── operators.cpython-36.pyc
    │ │ ├── symbolic.cpython-36.pyc
    │ │ └── utils.cpython-36.pyc
    │ ├── symbolic.py
    │ └── utils.py
    ├── _ops.py
    ├── optim
    │ ├── adadelta.py
    │ ├── adagrad.py
    │ ├── adamax.py
    │ ├── adam.py
    │ ├── asgd.py
    │ ├── init.py
    │ ├── lbfgs.py
    │ ├── lr_scheduler.py
    │ ├── optimizer.py
    │ ├── pycache
    │ │ ├── adadelta.cpython-36.pyc
    │ │ ├── adagrad.cpython-36.pyc
    │ │ ├── adamax.cpython-36.pyc
    │ │ ├── adam.cpython-36.pyc
    │ │ ├── asgd.cpython-36.pyc
    │ │ ├── init.cpython-36.pyc
    │ │ ├── lbfgs.cpython-36.pyc
    │ │ ├── lr_scheduler.cpython-36.pyc
    │ │ ├── optimizer.cpython-36.pyc
    │ │ ├── rmsprop.cpython-36.pyc
    │ │ ├── rprop.cpython-36.pyc
    │ │ ├── sgd.cpython-36.pyc
    │ │ └── sparse_adam.cpython-36.pyc
    │ ├── rmsprop.py
    │ ├── rprop.py
    │ ├── sgd.py
    │ └── sparse_adam.py
    ├── pycache
    │ ├── functional.cpython-36.pyc
    │ ├── hub.cpython-36.pyc
    │ ├── init.cpython-36.pyc
    │ ├── _jit_internal.cpython-36.pyc
    │ ├── _ops.cpython-36.pyc
    │ ├── random.cpython-36.pyc
    │ ├── serialization.cpython-36.pyc
    │ ├── _six.cpython-36.pyc
    │ ├── storage.cpython-36.pyc
    │ ├── _storage_docs.cpython-36.pyc
    │ ├── tensor.cpython-36.pyc
    │ ├── _tensor_docs.cpython-36.pyc
    │ ├── _tensor_str.cpython-36.pyc
    │ ├── _torch_docs.cpython-36.pyc
    │ ├── _utils.cpython-36.pyc
    │ ├── _utils_internal.cpython-36.pyc
    │ └── version.cpython-36.pyc
    ├── random.py
    ├── serialization.py
    ├── share
    │ └── cmake
    │ ├── ATen
    │ ├── Caffe2
    │ ├── Gloo
    │ └── Torch
    ├── _six.py
    ├── sparse
    │ ├── init.py
    │ └── pycache
    │ └── init.cpython-36.pyc
    ├── _storage_docs.py
    ├── storage.py
    ├── _tensor_docs.py
    ├── tensor.py
    ├── _tensor_str.py
    ├── testing
    │ ├── init.py
    │ └── pycache
    │ └── init.cpython-36.pyc
    ├── _thnn
    │ ├── init.py
    │ ├── pycache
    │ │ ├── init.cpython-36.pyc
    │ │ └── utils.cpython-36.pyc
    │ └── utils.py
    ├── _torch_docs.py
    ├── utils
    │ ├── backcompat
    │ │ ├── init.py
    │ │ └── pycache
    │ ├── bottleneck
    │ │ ├── init.py
    │ │ ├── main.py
    │ │ └── pycache
    │ ├── checkpoint.py
    │ ├── collect_env.py
    │ ├── cpp_extension.py
    │ ├── _cpp_extension_versioner.py
    │ ├── data
    │ │ ├── dataloader.py
    │ │ ├── dataset.py
    │ │ ├── distributed.py
    │ │ ├── init.py
    │ │ ├── pycache
    │ │ └── sampler.py
    │ ├── dlpack.py
    │ ├── ffi
    │ │ ├── init.py
    │ │ └── pycache
    │ ├── file_baton.py
    │ ├── hooks.py
    │ ├── init.py
    │ ├── model_zoo.py
    │ └── pycache
    │ ├── checkpoint.cpython-36.pyc
    │ ├── collect_env.cpython-36.pyc
    │ ├── cpp_extension.cpython-36.pyc
    │ ├── _cpp_extension_versioner.cpython-36.pyc
    │ ├── dlpack.cpython-36.pyc
    │ ├── file_baton.cpython-36.pyc
    │ ├── hooks.cpython-36.pyc
    │ ├── init.cpython-36.pyc
    │ └── model_zoo.cpython-36.pyc
    ├── _utils_internal.py
    ├── _utils.py
    └── version.py

    77 directories, 335 files

    torch -tree

    .
    ├── autograd
    │ ├── anomaly_mode.py
    │ ├── function.py
    │ ├── _functions
    │ │ ├── init.py
    │ │ ├── pycache
    │ │ │ ├── init.cpython-36.pyc
    │ │ │ ├── tensor.cpython-36.pyc
    │ │ │ └── utils.cpython-36.pyc
    │ │ ├── tensor.py
    │ │ └── utils.py
    │ ├── gradcheck.py
    │ ├── grad_mode.py
    │ ├── init.py
    │ ├── profiler.py
    │ ├── pycache
    │ │ ├── anomaly_mode.cpython-36.pyc
    │ │ ├── function.cpython-36.pyc
    │ │ ├── gradcheck.cpython-36.pyc
    │ │ ├── grad_mode.cpython-36.pyc
    │ │ ├── init.cpython-36.pyc
    │ │ ├── profiler.cpython-36.pyc
    │ │ └── variable.cpython-36.pyc
    │ └── variable.py
    ├── backends
    │ ├── cuda
    │ │ ├── init.py
    │ │ └── pycache
    │ │ └── init.cpython-36.pyc
    │ ├── cudnn
    │ │ ├── init.py
    │ │ ├── pycache
    │ │ │ ├── init.cpython-36.pyc
    │ │ │ └── rnn.cpython-36.pyc
    │ │ └── rnn.py
    │ ├── init.py
    │ ├── mkl
    │ │ ├── init.py
    │ │ └── pycache
    │ │ └── init.cpython-36.pyc
    │ └── pycache
    │ └── init.cpython-36.pyc
    ├── _C.cpython-36m-x86_64-linux-gnu.so
    ├── contrib
    │ ├── _graph_vis.py
    │ ├── init.py
    │ ├── pycache
    │ │ ├── _graph_vis.cpython-36.pyc
    │ │ ├── init.cpython-36.pyc
    │ │ └── _tensorboard_vis.cpython-36.pyc
    │ └── _tensorboard_vis.py
    ├── cuda
    │ ├── comm.py
    │ ├── error.py
    │ ├── init.py
    │ ├── nccl.py
    │ ├── nvtx.py
    │ ├── profiler.py
    │ ├── pycache
    │ │ ├── comm.cpython-36.pyc
    │ │ ├── error.cpython-36.pyc
    │ │ ├── init.cpython-36.pyc
    │ │ ├── nccl.cpython-36.pyc
    │ │ ├── nvtx.cpython-36.pyc
    │ │ ├── profiler.cpython-36.pyc
    │ │ ├── random.cpython-36.pyc
    │ │ ├── sparse.cpython-36.pyc
    │ │ ├── streams.cpython-36.pyc
    │ │ └── _utils.cpython-36.pyc
    │ ├── random.py
    │ ├── sparse.py
    │ ├── streams.py
    │ └── _utils.py
    ├── distributed
    │ ├── deprecated
    │ │ ├── init.py
    │ │ ├── pycache
    │ │ │ ├── init.cpython-36.pyc
    │ │ │ └── remote_types.cpython-36.pyc
    │ │ └── remote_types.py
    │ ├── distributed_c10d.py
    │ ├── init.py
    │ ├── launch.py
    │ ├── pycache
    │ │ ├── distributed_c10d.cpython-36.pyc
    │ │ ├── init.cpython-36.pyc
    │ │ ├── launch.cpython-36.pyc
    │ │ └── rendezvous.cpython-36.pyc
    │ └── rendezvous.py
    ├── distributions
    │ ├── bernoulli.py
    │ ├── beta.py
    │ ├── binomial.py
    │ ├── categorical.py
    │ ├── cauchy.py
    │ ├── chi2.py
    │ ├── constraint_registry.py
    │ ├── constraints.py
    │ ├── dirichlet.py
    │ ├── distribution.py
    │ ├── exp_family.py
    │ ├── exponential.py
    │ ├── fishersnedecor.py
    │ ├── gamma.py
    │ ├── geometric.py
    │ ├── gumbel.py
    │ ├── half_cauchy.py
    │ ├── half_normal.py
    │ ├── independent.py
    │ ├── init.py
    │ ├── kl.py
    │ ├── laplace.py
    │ ├── logistic_normal.py
    │ ├── log_normal.py
    │ ├── lowrank_multivariate_normal.py
    │ ├── multinomial.py
    │ ├── multivariate_normal.py
    │ ├── negative_binomial.py
    │ ├── normal.py
    │ ├── one_hot_categorical.py
    │ ├── pareto.py
    │ ├── poisson.py
    │ ├── pycache
    │ │ ├── bernoulli.cpython-36.pyc
    │ │ ├── beta.cpython-36.pyc
    │ │ ├── binomial.cpython-36.pyc
    │ │ ├── categorical.cpython-36.pyc
    │ │ ├── cauchy.cpython-36.pyc
    │ │ ├── chi2.cpython-36.pyc
    │ │ ├── constraint_registry.cpython-36.pyc
    │ │ ├── constraints.cpython-36.pyc
    │ │ ├── dirichlet.cpython-36.pyc
    │ │ ├── distribution.cpython-36.pyc
    │ │ ├── exp_family.cpython-36.pyc
    │ │ ├── exponential.cpython-36.pyc
    │ │ ├── fishersnedecor.cpython-36.pyc
    │ │ ├── gamma.cpython-36.pyc
    │ │ ├── geometric.cpython-36.pyc
    │ │ ├── gumbel.cpython-36.pyc
    │ │ ├── half_cauchy.cpython-36.pyc
    │ │ ├── half_normal.cpython-36.pyc
    │ │ ├── independent.cpython-36.pyc
    │ │ ├── init.cpython-36.pyc
    │ │ ├── kl.cpython-36.pyc
    │ │ ├── laplace.cpython-36.pyc
    │ │ ├── logistic_normal.cpython-36.pyc
    │ │ ├── log_normal.cpython-36.pyc
    │ │ ├── lowrank_multivariate_normal.cpython-36.pyc
    │ │ ├── multinomial.cpython-36.pyc
    │ │ ├── multivariate_normal.cpython-36.pyc
    │ │ ├── negative_binomial.cpython-36.pyc
    │ │ ├── normal.cpython-36.pyc
    │ │ ├── one_hot_categorical.cpython-36.pyc
    │ │ ├── pareto.cpython-36.pyc
    │ │ ├── poisson.cpython-36.pyc
    │ │ ├── relaxed_bernoulli.cpython-36.pyc
    │ │ ├── relaxed_categorical.cpython-36.pyc
    │ │ ├── studentT.cpython-36.pyc
    │ │ ├── transformed_distribution.cpython-36.pyc
    │ │ ├── transforms.cpython-36.pyc
    │ │ ├── uniform.cpython-36.pyc
    │ │ ├── utils.cpython-36.pyc
    │ │ └── weibull.cpython-36.pyc
    │ ├── relaxed_bernoulli.py
    │ ├── relaxed_categorical.py
    │ ├── studentT.py
    │ ├── transformed_distribution.py
    │ ├── transforms.py
    │ ├── uniform.py
    │ ├── utils.py
    │ └── weibull.py
    ├── _dl.cpython-36m-x86_64-linux-gnu.so
    ├── for_onnx
    │ ├── init.py
    │ └── pycache
    │ └── init.cpython-36.pyc
    ├── functional.py
    ├── hub.py
    ├── init.py
    ├── init.pyi
    ├── jit
    │ ├── annotations.py
    │ ├── batchop.py
    │ ├── frontend.py
    │ ├── init.py
    │ ├── pycache
    │ │ ├── annotations.cpython-36.pyc
    │ │ ├── batchop.cpython-36.pyc
    │ │ ├── frontend.cpython-36.pyc
    │ │ ├── init.cpython-36.pyc
    │ │ └── supported_ops.cpython-36.pyc
    │ └── supported_ops.py
    ├── _jit_internal.py
    ├── lib
    │ ├── include
    │ │ ├── ATen
    │ │ │ ├── AccumulateType.h
    │ │ │ ├── Allocator.h
    │ │ │ ├── ArrayRef.h
    │ │ │ ├── ATen.h
    │ │ │ ├── Backend.h
    │ │ │ ├── Backtrace.h
    │ │ │ ├── CheckGenerator.h
    │ │ │ ├── Config.h
    │ │ │ ├── Context.h
    │ │ │ ├── core
    │ │ │ │ ├── alias_info.h
    │ │ │ │ ├── ATenGeneral.h
    │ │ │ │ ├── aten_interned_strings.h
    │ │ │ │ ├── Backtrace.h
    │ │ │ │ ├── blob.h
    │ │ │ │ ├── context_base.h
    │ │ │ │ ├── DefaultDtype.h
    │ │ │ │ ├── Deprecated.h
    │ │ │ │ ├── DimVector.h
    │ │ │ │ ├── Formatting.h
    │ │ │ │ ├── functional.h
    │ │ │ │ ├── function_schema.h
    │ │ │ │ ├── Generator.h
    │ │ │ │ ├── Half.h
    │ │ │ │ ├── interned_strings_class.h
    │ │ │ │ ├── interned_strings.h
    │ │ │ │ ├── ivalue.h
    │ │ │ │ ├── jit_type.h
    │ │ │ │ ├── LegacyDeviceTypeInit.h
    │ │ │ │ ├── LegacyTypeDispatch.h
    │ │ │ │ ├── Macros.h
    │ │ │ │ ├── Range.h
    │ │ │ │ ├── Reduction.h
    │ │ │ │ ├── Scalar.h
    │ │ │ │ ├── ScalarType.h
    │ │ │ │ ├── SparseTensorRef.h
    │ │ │ │ ├── TensorAccessor.h
    │ │ │ │ ├── Tensor.h
    │ │ │ │ ├── TensorImpl.h
    │ │ │ │ ├── TensorMethods.h
    │ │ │ │ ├── TensorOptions.h
    │ │ │ │ ├── thread_pool.h
    │ │ │ │ ├── Type.h
    │ │ │ │ ├── typeid.h
    │ │ │ │ ├── UndefinedTensorImpl.h
    │ │ │ │ ├── VariableHooksInterface.h
    │ │ │ │ └── WrapDimMinimal.h
    │ │ │ ├── cpu
    │ │ │ │ ├── FlushDenormal.h
    │ │ │ │ └── vml.h
    │ │ │ ├── CPUApplyUtils.h
    │ │ │ ├── CPUByteType.h
    │ │ │ ├── CPUCharType.h
    │ │ │ ├── CPUDoubleType.h
    │ │ │ ├── CPUFixedAllocator.h
    │ │ │ ├── CPUFloatType.h
    │ │ │ ├── CPUGeneral.h
    │ │ │ ├── CPUGenerator.h
    │ │ │ ├── CPUHalfType.h
    │ │ │ ├── CPUIntType.h
    │ │ │ ├── CPULongType.h
    │ │ │ ├── CPUShortType.h
    │ │ │ ├── CPUTypeDefault.h
    │ │ │ ├── cuda
    │ │ │ │ ├── Array.h
    │ │ │ │ ├── ATenCUDAGeneral.h
    │ │ │ │ ├── CUDAApplyUtils.cuh
    │ │ │ │ ├── CUDAConfig.h
    │ │ │ │ ├── CUDAContext.h
    │ │ │ │ ├── CUDADevice.h
    │ │ │ │ ├── CUDAEvent.h
    │ │ │ │ ├── CUDAGuard.h
    │ │ │ │ ├── CUDAMultiStreamGuard.h
    │ │ │ │ ├── CUDAStream.h
    │ │ │ │ ├── CUDATensorMethods.cuh
    │ │ │ │ ├── CUDATypeDefault.h
    │ │ │ │ ├── CUDAUtils.h
    │ │ │ │ ├── _curand_mtgp32_host.h
    │ │ │ │ ├── detail
    │ │ │ │ │ ├── CUDAGuardImpl.h
    │ │ │ │ │ ├── CUDAHooks.h
    │ │ │ │ │ ├── IndexUtils.cuh
    │ │ │ │ │ ├── KernelUtils.h
    │ │ │ │ │ ├── OffsetCalculator.cuh
    │ │ │ │ │ └── TensorInfo.cuh
    │ │ │ │ ├── Exceptions.h
    │ │ │ │ ├── NumericLimits.cuh
    │ │ │ │ └── PinnedMemoryAllocator.h
    │ │ │ ├── CUDAByteType.h
    │ │ │ ├── CUDACharType.h
    │ │ │ ├── CUDADoubleType.h
    │ │ │ ├── CUDAFloatType.h
    │ │ │ ├── CUDAGenerator.h
    │ │ │ ├── CUDAHalfType.h
    │ │ │ ├── CUDAIntType.h
    │ │ │ ├── CUDALongType.h
    │ │ │ ├── CUDAShortType.h
    │ │ │ ├── cudnn
    │ │ │ │ ├── cudnn-wrapper.h
    │ │ │ │ ├── Descriptors.h
    │ │ │ │ ├── Exceptions.h
    │ │ │ │ ├── Handle.h
    │ │ │ │ ├── Handles.h
    │ │ │ │ ├── Types.h
    │ │ │ │ └── Utils.h
    │ │ │ ├── detail
    │ │ │ │ ├── ComplexHooksInterface.h
    │ │ │ │ ├── CPUGuardImpl.h
    │ │ │ │ ├── CUDAHooksInterface.h
    │ │ │ │ ├── FunctionTraits.h
    │ │ │ │ ├── HIPHooksInterface.h
    │ │ │ │ └── ScalarTypeConversions.h
    │ │ │ ├── DeviceGuard.h
    │ │ │ ├── Device.h
    │ │ │ ├── DimVector.h
    │ │ │ ├── Dispatch.h
    │ │ │ ├── div_rtn.h
    │ │ │ ├── DLConvertor.h
    │ │ │ ├── dlpack.h
    │ │ │ ├── ExpandUtils.h
    │ │ │ ├── Formatting.h
    │ │ │ ├── Functions.h
    │ │ │ ├── Generator.h
    │ │ │ ├── Half.h
    │ │ │ ├── InferSize.h
    │ │ │ ├── InitialTensorOptions.h
    │ │ │ ├── Layout.h
    │ │ │ ├── LegacyTHDispatcher.h
    │ │ │ ├── LegacyTHDispatch.h
    │ │ │ ├── MatrixRef.h
    │ │ │ ├── NativeFunctions.h
    │ │ │ ├── Parallel.h
    │ │ │ ├── RegisterCPU.h
    │ │ │ ├── RegisterCUDA.h
    │ │ │ ├── Scalar.h
    │ │ │ ├── ScalarOps.h
    │ │ │ ├── ScalarType.h
    │ │ │ ├── SmallVector.h
    │ │ │ ├── SparseCPUByteType.h
    │ │ │ ├── SparseCPUCharType.h
    │ │ │ ├── SparseCPUDoubleType.h
    │ │ │ ├── SparseCPUFloatType.h
    │ │ │ ├── SparseCPUIntType.h
    │ │ │ ├── SparseCPULongType.h
    │ │ │ ├── SparseCPUShortType.h
    │ │ │ ├── SparseCUDAByteType.h
    │ │ │ ├── SparseCUDACharType.h
    │ │ │ ├── SparseCUDADoubleType.h
    │ │ │ ├── SparseCUDAFloatType.h
    │ │ │ ├── SparseCUDAIntType.h
    │ │ │ ├── SparseCUDALongType.h
    │ │ │ ├── SparseCUDAShortType.h
    │ │ │ ├── SparseTensorImpl.h
    │ │ │ ├── SparseTensorUtils.h
    │ │ │ ├── Storage.h
    │ │ │ ├── TensorAccessor.h
    │ │ │ ├── TensorGeometry.h
    │ │ │ ├── Tensor.h
    │ │ │ ├── TensorOperators.h
    │ │ │ ├── TensorOptions.h
    │ │ │ ├── TensorUtils.h
    │ │ │ ├── TypeDefault.h
    │ │ │ ├── TypeExtendedInterface.h
    │ │ │ ├── Type.h
    │ │ │ ├── UndefinedType.h
    │ │ │ ├── Utils.h
    │ │ │ ├── WrapDimUtils.h
    │ │ │ └── WrapDimUtilsMulti.h
    │ │ ├── c10
    │ │ │ ├── core
    │ │ │ │ ├── Allocator.h
    │ │ │ │ ├── Backend.h
    │ │ │ │ ├── bitcasts.h
    │ │ │ │ ├── Layout.h
    │ │ │ │ ├── Scalar.h
    │ │ │ │ ├── ScalarType.h
    │ │ │ │ ├── ScalarTypeUtils.h
    │ │ │ │ ├── Storage.h
    │ │ │ │ ├── StorageImpl.h
    │ │ │ │ ├── TensorTypeId.h
    │ │ │ │ └── TensorTypeIdRegistration.h
    │ │ │ ├── cuda
    │ │ │ │ ├── CUDAException.h
    │ │ │ │ ├── CUDAFunctions.h
    │ │ │ │ ├── CUDAMacros.h
    │ │ │ │ ├── CUDAMathCompat.h
    │ │ │ │ └── impl
    │ │ │ │ └── CUDATest.h
    │ │ │ ├── DeviceGuard.h
    │ │ │ ├── Device.h
    │ │ │ ├── DeviceType.h
    │ │ │ ├── Half.h
    │ │ │ ├── Half-inl.h
    │ │ │ ├── impl
    │ │ │ │ ├── DeviceGuardImplInterface.h
    │ │ │ │ ├── FakeGuardImpl.h
    │ │ │ │ ├── InlineDeviceGuard.h
    │ │ │ │ ├── InlineStreamGuard.h
    │ │ │ │ └── VirtualGuardImpl.h
    │ │ │ ├── macros
    │ │ │ │ ├── cmake_macros.h
    │ │ │ │ ├── Export.h
    │ │ │ │ └── Macros.h
    │ │ │ ├── StreamGuard.h
    │ │ │ ├── Stream.h
    │ │ │ └── util
    │ │ │ ├── AlignOf.h
    │ │ │ ├── Array.h
    │ │ │ ├── ArrayRef.h
    │ │ │ ├── Backtrace.h
    │ │ │ ├── C++17.h
    │ │ │ ├── Exception.h
    │ │ │ ├── Flags.h
    │ │ │ ├── flat_hash_map.h
    │ │ │ ├── IdWrapper.h
    │ │ │ ├── intrusive_ptr.h
    │ │ │ ├── LeftRight.h
    │ │ │ ├── Logging.h
    │ │ │ ├── logging_is_google_glog.h
    │ │ │ ├── logging_is_not_google_glog.h
    │ │ │ ├── Metaprogramming.h
    │ │ │ ├── Optional.h
    │ │ │ ├── Registry.h
    │ │ │ ├── SmallVector.h
    │ │ │ ├── StringUtil.h
    │ │ │ ├── string_utils.h
    │ │ │ ├── Type.h
    │ │ │ ├── typeid.h
    │ │ │ ├── TypeList.h
    │ │ │ ├── TypeTraits.h
    │ │ │ └── UniqueVoidPtr.h
    │ │ ├── caffe2
    │ │ │ ├── core
    │ │ │ │ ├── allocator.h
    │ │ │ │ ├── asan.h
    │ │ │ │ ├── blob.h
    │ │ │ │ ├── blob_serialization.h
    │ │ │ │ ├── blob_serializer_base.h
    │ │ │ │ ├── blob_stats.h
    │ │ │ │ ├── common_cudnn.h
    │ │ │ │ ├── common_gpu.h
    │ │ │ │ ├── common.h
    │ │ │ │ ├── common_omp.h
    │ │ │ │ ├── context_base.h
    │ │ │ │ ├── context_gpu.h
    │ │ │ │ ├── context.h
    │ │ │ │ ├── cudnn_wrappers.h
    │ │ │ │ ├── db.h
    │ │ │ │ ├── event_cpu.h
    │ │ │ │ ├── event.h
    │ │ │ │ ├── flags.h
    │ │ │ │ ├── graph.h
    │ │ │ │ ├── init.h
    │ │ │ │ ├── logging.h
    │ │ │ │ ├── macros.h
    │ │ │ │ ├── memonger.h
    │ │ │ │ ├── module.h
    │ │ │ │ ├── net_async_base.h
    │ │ │ │ ├── net_async_scheduling.h
    │ │ │ │ ├── net_async_tracing.h
    │ │ │ │ ├── net_dag_utils.h
    │ │ │ │ ├── net.h
    │ │ │ │ ├── net_simple.h
    │ │ │ │ ├── net_simple_refcount.h
    │ │ │ │ ├── numa.h
    │ │ │ │ ├── observer.h
    │ │ │ │ ├── operator_c10wrapper.h
    │ │ │ │ ├── operator_gradient.h
    │ │ │ │ ├── operator.h
    │ │ │ │ ├── operator_schema.h
    │ │ │ │ ├── plan_executor.h
    │ │ │ │ ├── prof_dag_counters.h
    │ │ │ │ ├── qtensor.h
    │ │ │ │ ├── qtensor_serialization.h
    │ │ │ │ ├── scope_guard.h
    │ │ │ │ ├── static_tracepoint_elfx86.h
    │ │ │ │ ├── static_tracepoint.h
    │ │ │ │ ├── stats.h
    │ │ │ │ ├── storage.h
    │ │ │ │ ├── tensor.h
    │ │ │ │ ├── tensor_impl.h
    │ │ │ │ ├── tensor_int8.h
    │ │ │ │ ├── THCCachingAllocator_gpu.h
    │ │ │ │ ├── timer.h
    │ │ │ │ ├── transform.h
    │ │ │ │ ├── types.h
    │ │ │ │ └── workspace.h
    │ │ │ ├── proto
    │ │ │ │ ├── caffe2_legacy.pb.h
    │ │ │ │ ├── caffe2_pb.h
    │ │ │ │ ├── caffe2.pb.h
    │ │ │ │ ├── hsm.pb.h
    │ │ │ │ ├── metanet.pb.h
    │ │ │ │ ├── predictor_consts.pb.h
    │ │ │ │ ├── prof_dag.pb.h
    │ │ │ │ ├── torch_pb.h
    │ │ │ │ └── torch.pb.h
    │ │ │ └── utils
    │ │ │ ├── bench_utils.h
    │ │ │ ├── cast.h
    │ │ │ ├── cblas.h
    │ │ │ ├── conversions.h
    │ │ │ ├── cpuid.h
    │ │ │ ├── cpu_neon.h
    │ │ │ ├── eigen_utils.h
    │ │ │ ├── filler.h
    │ │ │ ├── fixed_divisor.h
    │ │ │ ├── map_utils.h
    │ │ │ ├── math-detail.h
    │ │ │ ├── math.h
    │ │ │ ├── math_utils.h
    │ │ │ ├── murmur_hash3.h
    │ │ │ ├── proto_convert.h
    │ │ │ ├── proto_utils.h
    │ │ │ ├── proto_wrap.h
    │ │ │ ├── signal_handler.h
    │ │ │ ├── simple_queue.h
    │ │ │ ├── smart_tensor_printer.h
    │ │ │ ├── string_utils.h
    │ │ │ ├── thread_name.h
    │ │ │ ├── thread_pool.h
    │ │ │ └── zmq_helper.h
    │ │ ├── pybind11
    │ │ │ ├── attr.h
    │ │ │ ├── buffer_info.h
    │ │ │ ├── cast.h
    │ │ │ ├── chrono.h
    │ │ │ ├── common.h
    │ │ │ ├── complex.h
    │ │ │ ├── detail
    │ │ │ │ ├── class.h
    │ │ │ │ ├── common.h
    │ │ │ │ ├── descr.h
    │ │ │ │ ├── init.h
    │ │ │ │ ├── internals.h
    │ │ │ │ └── typeid.h
    │ │ │ ├── eigen.h
    │ │ │ ├── embed.h
    │ │ │ ├── eval.h
    │ │ │ ├── functional.h
    │ │ │ ├── iostream.h
    │ │ │ ├── numpy.h
    │ │ │ ├── operators.h
    │ │ │ ├── options.h
    │ │ │ ├── pybind11.h
    │ │ │ ├── pytypes.h
    │ │ │ ├── stl_bind.h
    │ │ │ └── stl.h
    │ │ ├── TH
    │ │ │ ├── generic
    │ │ │ │ ├── THBlas.h
    │ │ │ │ ├── THLapack.h
    │ │ │ │ ├── THStorageCopy.h
    │ │ │ │ ├── THStorage.h
    │ │ │ │ ├── THTensorConv.h
    │ │ │ │ ├── THTensorFastGetSet.hpp
    │ │ │ │ ├── THTensor.h
    │ │ │ │ ├── THTensor.hpp
    │ │ │ │ ├── THTensorLapack.h
    │ │ │ │ ├── THTensorMath.h
    │ │ │ │ ├── THTensorRandom.h
    │ │ │ │ └── THVector.h
    │ │ │ ├── THAllocator.h
    │ │ │ ├── THBlas.h
    │ │ │ ├── THDiskFile.h
    │ │ │ ├── THFile.h
    │ │ │ ├── THFilePrivate.h
    │ │ │ ├── THGeneral.h
    │ │ │ ├── THGenerateAllTypes.h
    │ │ │ ├── THGenerateByteType.h
    │ │ │ ├── THGenerateCharType.h
    │ │ │ ├── THGenerateDoubleType.h
    │ │ │ ├── THGenerateFloatType.h
    │ │ │ ├── THGenerateFloatTypes.h
    │ │ │ ├── THGenerateHalfType.h
    │ │ │ ├── THGenerateIntType.h
    │ │ │ ├── THGenerateIntTypes.h
    │ │ │ ├── THGenerateLongType.h
    │ │ │ ├── THGenerateShortType.h
    │ │ │ ├── THGenerator.hpp
    │ │ │ ├── TH.h
    │ │ │ ├── THHalf.h
    │ │ │ ├── THLapack.h
    │ │ │ ├── THLogAdd.h
    │ │ │ ├── THMath.h
    │ │ │ ├── THMemoryFile.h
    │ │ │ ├── THRandom.h
    │ │ │ ├── THSize.h
    │ │ │ ├── THStorageFunctions.h
    │ │ │ ├── THStorageFunctions.hpp
    │ │ │ ├── THStorage.h
    │ │ │ ├── THTensorApply.h
    │ │ │ ├── THTensorDimApply.h
    │ │ │ ├── THTensor.h
    │ │ │ ├── THTensor.hpp
    │ │ │ └── THVector.h
    │ │ └── torch
    │ │ ├── csrc
    │ │ │ ├── api
    │ │ │ │ └── include
    │ │ │ │ └── torch
    │ │ │ │ ├── all.h
    │ │ │ │ ├── arg.h
    │ │ │ │ ├── cuda.h
    │ │ │ │ ├── data
    │ │ │ │ │ ├── dataloader.h
    │ │ │ │ │ ├── dataloader_options.h
    │ │ │ │ │ ├── datasets
    │ │ │ │ │ │ ├── base.h
    │ │ │ │ │ │ ├── map.h
    │ │ │ │ │ │ ├── mnist.h
    │ │ │ │ │ │ ├── shared.h
    │ │ │ │ │ │ └── tensor.h
    │ │ │ │ │ ├── datasets.h
    │ │ │ │ │ ├── detail
    │ │ │ │ │ │ ├── data_shuttle.h
    │ │ │ │ │ │ ├── queue.h
    │ │ │ │ │ │ └── sequencers.h
    │ │ │ │ │ ├── example.h
    │ │ │ │ │ ├── iterator.h
    │ │ │ │ │ ├── samplers
    │ │ │ │ │ │ ├── base.h
    │ │ │ │ │ │ ├── custom_batch_request.h
    │ │ │ │ │ │ ├── random.h
    │ │ │ │ │ │ ├── sequential.h
    │ │ │ │ │ │ ├── serialize.h
    │ │ │ │ │ │ └── stream.h
    │ │ │ │ │ ├── samplers.h
    │ │ │ │ │ ├── transforms
    │ │ │ │ │ │ ├── base.h
    │ │ │ │ │ │ ├── collate.h
    │ │ │ │ │ │ ├── lambda.h
    │ │ │ │ │ │ ├── stack.h
    │ │ │ │ │ │ └── tensor.h
    │ │ │ │ │ ├── transforms.h
    │ │ │ │ │ └── worker_exception.h
    │ │ │ │ ├── data.h
    │ │ │ │ ├── detail
    │ │ │ │ │ └── static.h
    │ │ │ │ ├── expanding_array.h
    │ │ │ │ ├── jit.h
    │ │ │ │ ├── nn
    │ │ │ │ │ ├── cloneable.h
    │ │ │ │ │ ├── init.h
    │ │ │ │ │ ├── module.h
    │ │ │ │ │ ├── modules
    │ │ │ │ │ │ ├── any.h
    │ │ │ │ │ │ ├── batchnorm.h
    │ │ │ │ │ │ ├── conv.h
    │ │ │ │ │ │ ├── dropout.h
    │ │ │ │ │ │ ├── embedding.h
    │ │ │ │ │ │ ├── functional.h
    │ │ │ │ │ │ ├── linear.h
    │ │ │ │ │ │ ├── rnn.h
    │ │ │ │ │ │ └── sequential.h
    │ │ │ │ │ ├── modules.h
    │ │ │ │ │ ├── parallel
    │ │ │ │ │ │ └── data_parallel.h
    │ │ │ │ │ ├── pimpl.h
    │ │ │ │ │ └── pimpl-inl.h
    │ │ │ │ ├── nn.h
    │ │ │ │ ├── optim
    │ │ │ │ │ ├── adagrad.h
    │ │ │ │ │ ├── adam.h
    │ │ │ │ │ ├── lbfgs.h
    │ │ │ │ │ ├── optimizer.h
    │ │ │ │ │ ├── rmsprop.h
    │ │ │ │ │ ├── serialize.h
    │ │ │ │ │ └── sgd.h
    │ │ │ │ ├── optim.h
    │ │ │ │ ├── ordered_dict.h
    │ │ │ │ ├── python.h
    │ │ │ │ ├── serialize
    │ │ │ │ │ ├── archive.h
    │ │ │ │ │ ├── input-archive.h
    │ │ │ │ │ ├── output-archive.h
    │ │ │ │ │ └── tensor.h
    │ │ │ │ ├── serialize.h
    │ │ │ │ ├── torch.h
    │ │ │ │ ├── types.h
    │ │ │ │ └── utils.h
    │ │ │ ├── autograd
    │ │ │ │ ├── anomaly_mode.h
    │ │ │ │ ├── autograd.h
    │ │ │ │ ├── edge.h
    │ │ │ │ ├── engine.h
    │ │ │ │ ├── function.h
    │ │ │ │ ├── function_hook.h
    │ │ │ │ ├── generated
    │ │ │ │ │ ├── Functions.h
    │ │ │ │ │ ├── python_functions.h
    │ │ │ │ │ ├── python_nn_functions_dispatch.h
    │ │ │ │ │ ├── python_nn_functions.h
    │ │ │ │ │ ├── python_torch_functions_dispatch.h
    │ │ │ │ │ ├── python_variable_methods_dispatch.h
    │ │ │ │ │ ├── variable_factories.h
    │ │ │ │ │ └── VariableType.h
    │ │ │ │ ├── grad_mode.h
    │ │ │ │ ├── input_buffer.h
    │ │ │ │ ├── input_metadata.h
    │ │ │ │ ├── profiler.h
    │ │ │ │ ├── python_anomaly_mode.h
    │ │ │ │ ├── python_cpp_function.h
    │ │ │ │ ├── python_engine.h
    │ │ │ │ ├── python_function.h
    │ │ │ │ ├── python_hook.h
    │ │ │ │ ├── python_legacy_variable.h
    │ │ │ │ ├── python_variable.h
    │ │ │ │ ├── python_variable_indexing.h
    │ │ │ │ ├── saved_variable.h
    │ │ │ │ ├── symbolic.h
    │ │ │ │ ├── type_and_shape.h
    │ │ │ │ ├── variable.h
    │ │ │ │ ├── VariableTypeUtils.h
    │ │ │ │ └── variable_version.h
    │ │ │ ├── byte_order.h
    │ │ │ ├── copy_utils.h
    │ │ │ ├── cuda
    │ │ │ │ ├── comm.h
    │ │ │ │ ├── cuda_check.h
    │ │ │ │ ├── device_set.h
    │ │ │ │ ├── Module.h
    │ │ │ │ ├── nccl.h
    │ │ │ │ ├── override_macros.h
    │ │ │ │ ├── python_comm.h
    │ │ │ │ ├── python_nccl.h
    │ │ │ │ ├── restore_macros.h
    │ │ │ │ ├── serialization.h
    │ │ │ │ ├── Storage.h
    │ │ │ │ ├── Stream.h
    │ │ │ │ ├── THCP.h
    │ │ │ │ ├── undef_macros.h
    │ │ │ │ └── utils.h
    │ │ │ ├── DataLoader.h
    │ │ │ ├── Device.h
    │ │ │ ├── Dtype.h
    │ │ │ ├── DynamicTypes.h
    │ │ │ ├── Exceptions.h
    │ │ │ ├── Generator.h
    │ │ │ ├── jit
    │ │ │ │ ├── alias_info.h
    │ │ │ │ ├── argument_spec.h
    │ │ │ │ ├── assertions.h
    │ │ │ │ ├── attributes.h
    │ │ │ │ ├── autodiff.h
    │ │ │ │ ├── code_template.h
    │ │ │ │ ├── constants.h
    │ │ │ │ ├── custom_operator.h
    │ │ │ │ ├── dynamic_dag.h
    │ │ │ │ ├── export.h
    │ │ │ │ ├── function_schema.h
    │ │ │ │ ├── generic_if.h
    │ │ │ │ ├── graph_executor.h
    │ │ │ │ ├── graph_node_list.h
    │ │ │ │ ├── hooks_for_testing.h
    │ │ │ │ ├── import.h
    │ │ │ │ ├── import_method.h
    │ │ │ │ ├── init.h
    │ │ │ │ ├── interned_strings_class.h
    │ │ │ │ ├── interned_strings.h
    │ │ │ │ ├── interpreter.h
    │ │ │ │ ├── ir.h
    │ │ │ │ ├── ir_views.h
    │ │ │ │ ├── ivalue.h
    │ │ │ │ ├── named_value.h
    │ │ │ │ ├── node_hashing.h
    │ │ │ │ ├── operator.h
    │ │ │ │ ├── passes
    │ │ │ │ │ ├── alias_analysis.h
    │ │ │ │ │ ├── batch_mm.h
    │ │ │ │ │ ├── canonicalize.h
    │ │ │ │ │ ├── canonicalize_ops.h
    │ │ │ │ │ ├── common_subexpression_elimination.h
    │ │ │ │ │ ├── constant_pooling.h
    │ │ │ │ │ ├── constant_propagation.h
    │ │ │ │ │ ├── create_autodiff_subgraphs.h
    │ │ │ │ │ ├── dead_code_elimination.h
    │ │ │ │ │ ├── erase_number_types.h
    │ │ │ │ │ ├── graph_fuser.h
    │ │ │ │ │ ├── inline_autodiff_subgraphs.h
    │ │ │ │ │ ├── inplace_check.h
    │ │ │ │ │ ├── loop_unrolling.h
    │ │ │ │ │ ├── lower_grad_of.h
    │ │ │ │ │ ├── lower_tuples.h
    │ │ │ │ │ ├── onnx.h
    │ │ │ │ │ ├── peephole.h
    │ │ │ │ │ ├── python_print.h
    │ │ │ │ │ ├── remove_expands.h
    │ │ │ │ │ ├── remove_inplace_ops.h
    │ │ │ │ │ ├── requires_grad_analysis.h
    │ │ │ │ │ ├── shape_analysis.h
    │ │ │ │ │ ├── specialize_undef.h
    │ │ │ │ │ └── to_batch.h
    │ │ │ │ ├── pybind.h
    │ │ │ │ ├── pybind_utils.h
    │ │ │ │ ├── python_arg_flatten.h
    │ │ │ │ ├── python_ir.h
    │ │ │ │ ├── python_tracer.h
    │ │ │ │ ├── resource_guard.h
    │ │ │ │ ├── scope.h
    │ │ │ │ ├── script
    │ │ │ │ │ ├── builtin_functions.h
    │ │ │ │ │ ├── compiler.h
    │ │ │ │ │ ├── error_report.h
    │ │ │ │ │ ├── init.h
    │ │ │ │ │ ├── jit_exception.h
    │ │ │ │ │ ├── lexer.h
    │ │ │ │ │ ├── module.h
    │ │ │ │ │ ├── parser.h
    │ │ │ │ │ ├── parse_string_literal.h
    │ │ │ │ │ ├── python_tree_views.h
    │ │ │ │ │ ├── tree.h
    │ │ │ │ │ └── tree_views.h
    │ │ │ │ ├── source_location.h
    │ │ │ │ ├── source_range.h
    │ │ │ │ ├── stack.h
    │ │ │ │ ├── symbolic_variable.h
    │ │ │ │ ├── tracer.h
    │ │ │ │ ├── tracing_state.h
    │ │ │ │ ├── type.h
    │ │ │ │ └── variable_tensor_list.h
    │ │ │ ├── Layout.h
    │ │ │ ├── Module.h
    │ │ │ ├── PtrWrapper.h
    │ │ │ ├── python_headers.h
    │ │ │ ├── PythonTypes.h
    │ │ │ ├── serialization.h
    │ │ │ ├── Size.h
    │ │ │ ├── StorageDefs.h
    │ │ │ ├── Storage.h
    │ │ │ ├── THP_API.h
    │ │ │ ├── THP_export.h
    │ │ │ ├── THP.h
    │ │ │ ├── TypeInfo.h
    │ │ │ ├── Types.h
    │ │ │ ├── utils
    │ │ │ │ ├── auto_gil.h
    │ │ │ │ ├── cuda_enabled.h
    │ │ │ │ ├── cuda_lazy_init.h
    │ │ │ │ ├── disallow_copy.h
    │ │ │ │ ├── functional.h
    │ │ │ │ ├── hash.h
    │ │ │ │ ├── invalid_arguments.h
    │ │ │ │ ├── memory.h
    │ │ │ │ ├── numpy_stub.h
    │ │ │ │ ├── object_ptr.h
    │ │ │ │ ├── pybind.h
    │ │ │ │ ├── python_arg_parser.h
    │ │ │ │ ├── python_compat.h
    │ │ │ │ ├── python_numbers.h
    │ │ │ │ ├── python_scalars.h
    │ │ │ │ ├── python_strings.h
    │ │ │ │ ├── python_stub.h
    │ │ │ │ ├── python_tuples.h
    │ │ │ │ ├── tempfile.h
    │ │ │ │ ├── tensor_apply.h
    │ │ │ │ ├── tensor_dtypes.h
    │ │ │ │ ├── tensor_flatten.h
    │ │ │ │ ├── tensor_layouts.h
    │ │ │ │ ├── tensor_list.h
    │ │ │ │ ├── tensor_new.h
    │ │ │ │ ├── tensor_numpy.h
    │ │ │ │ ├── tensor_types.h
    │ │ │ │ ├── tuple_parser.h
    │ │ │ │ └── variadic.h
    │ │ │ ├── utils.h
    │ │ │ ├── variable_tensor_functions.h
    │ │ │ └── WindowsTorchApiMacro.h
    │ │ ├── extension.h
    │ │ └── script.h
    │ ├── libc10.so
    │ ├── libcaffe2_detectron_ops.so
    │ ├── libcaffe2_module_test_dynamic.so
    │ ├── libcaffe2_observers.so
    │ ├── libcaffe2.so
    │ ├── libonnxifi_dummy.so
    │ ├── libonnxifi.so
    │ ├── libshm.so
    │ ├── libtorch_python.so
    │ ├── libtorch.so
    │ ├── libtorch.so.1
    │ ├── THCUNN.h
    │ ├── THNN.h
    │ └── torch_shm_manager
    ├── multiprocessing
    │ ├── init.py
    │ ├── pool.py
    │ ├── pycache
    │ │ ├── init.cpython-36.pyc
    │ │ ├── pool.cpython-36.pyc
    │ │ ├── queue.cpython-36.pyc
    │ │ ├── reductions.cpython-36.pyc
    │ │ └── spawn.cpython-36.pyc
    │ ├── queue.py
    │ ├── reductions.py
    │ └── spawn.py
    ├── nn
    │ ├── backends
    │ │ ├── backend.py
    │ │ ├── init.py
    │ │ ├── pycache
    │ │ │ ├── backend.cpython-36.pyc
    │ │ │ ├── init.cpython-36.pyc
    │ │ │ └── thnn.cpython-36.pyc
    │ │ └── thnn.py
    │ ├── functional.py
    │ ├── _functions
    │ │ ├── init.py
    │ │ ├── pycache
    │ │ │ ├── init.cpython-36.pyc
    │ │ │ └── vision.cpython-36.pyc
    │ │ ├── thnn
    │ │ │ ├── auto_double_backwards.py
    │ │ │ ├── auto.py
    │ │ │ ├── auto_symbolic.py
    │ │ │ ├── fold.py
    │ │ │ ├── init.py
    │ │ │ ├── normalization.py
    │ │ │ ├── pycache
    │ │ │ │ ├── auto.cpython-36.pyc
    │ │ │ │ ├── auto_double_backwards.cpython-36.pyc
    │ │ │ │ ├── auto_symbolic.cpython-36.pyc
    │ │ │ │ ├── fold.cpython-36.pyc
    │ │ │ │ ├── init.cpython-36.pyc
    │ │ │ │ ├── normalization.cpython-36.pyc
    │ │ │ │ └── sparse.cpython-36.pyc
    │ │ │ └── sparse.py
    │ │ └── vision.py
    │ ├── grad.py
    │ ├── init.py
    │ ├── init.py
    │ ├── modules
    │ │ ├── activation.py
    │ │ ├── adaptive.py
    │ │ ├── batchnorm.py
    │ │ ├── container.py
    │ │ ├── conv.py
    │ │ ├── distance.py
    │ │ ├── dropout.py
    │ │ ├── fold.py
    │ │ ├── init.py
    │ │ ├── instancenorm.py
    │ │ ├── linear.py
    │ │ ├── loss.py
    │ │ ├── module.py
    │ │ ├── normalization.py
    │ │ ├── padding.py
    │ │ ├── pixelshuffle.py
    │ │ ├── pooling.py
    │ │ ├── pycache
    │ │ │ ├── activation.cpython-36.pyc
    │ │ │ ├── adaptive.cpython-36.pyc
    │ │ │ ├── batchnorm.cpython-36.pyc
    │ │ │ ├── container.cpython-36.pyc
    │ │ │ ├── conv.cpython-36.pyc
    │ │ │ ├── distance.cpython-36.pyc
    │ │ │ ├── dropout.cpython-36.pyc
    │ │ │ ├── fold.cpython-36.pyc
    │ │ │ ├── init.cpython-36.pyc
    │ │ │ ├── instancenorm.cpython-36.pyc
    │ │ │ ├── linear.cpython-36.pyc
    │ │ │ ├── loss.cpython-36.pyc
    │ │ │ ├── module.cpython-36.pyc
    │ │ │ ├── normalization.cpython-36.pyc
    │ │ │ ├── padding.cpython-36.pyc
    │ │ │ ├── pixelshuffle.cpython-36.pyc
    │ │ │ ├── pooling.cpython-36.pyc
    │ │ │ ├── rnn.cpython-36.pyc
    │ │ │ ├── sparse.cpython-36.pyc
    │ │ │ ├── upsampling.cpython-36.pyc
    │ │ │ └── utils.cpython-36.pyc
    │ │ ├── rnn.py
    │ │ ├── sparse.py
    │ │ ├── upsampling.py
    │ │ └── utils.py
    │ ├── parallel
    │ │ ├── data_parallel.py
    │ │ ├── deprecated
    │ │ │ ├── distributed_cpu.py
    │ │ │ ├── distributed.py
    │ │ │ ├── init.py
    │ │ │ └── pycache
    │ │ │ ├── distributed_cpu.cpython-36.pyc
    │ │ │ ├── distributed.cpython-36.pyc
    │ │ │ └── init.cpython-36.pyc
    │ │ ├── distributed_cpu.py
    │ │ ├── distributed.py
    │ │ ├── _functions.py
    │ │ ├── init.py
    │ │ ├── parallel_apply.py
    │ │ ├── pycache
    │ │ │ ├── data_parallel.cpython-36.pyc
    │ │ │ ├── distributed_cpu.cpython-36.pyc
    │ │ │ ├── distributed.cpython-36.pyc
    │ │ │ ├── _functions.cpython-36.pyc
    │ │ │ ├── init.cpython-36.pyc
    │ │ │ ├── parallel_apply.cpython-36.pyc
    │ │ │ ├── replicate.cpython-36.pyc
    │ │ │ └── scatter_gather.cpython-36.pyc
    │ │ ├── replicate.py
    │ │ └── scatter_gather.py
    │ ├── parameter.py
    │ ├── pycache
    │ │ ├── functional.cpython-36.pyc
    │ │ ├── grad.cpython-36.pyc
    │ │ ├── init.cpython-36.pyc
    │ │ ├── init.cpython-36.pyc
    │ │ ├── parameter.cpython-36.pyc
    │ │ ├── _reduction.cpython-36.pyc
    │ │ └── _VF.cpython-36.pyc
    │ ├── _reduction.py
    │ ├── utils
    │ │ ├── clip_grad.py
    │ │ ├── convert_parameters.py
    │ │ ├── init.py
    │ │ ├── pycache
    │ │ │ ├── clip_grad.cpython-36.pyc
    │ │ │ ├── convert_parameters.cpython-36.pyc
    │ │ │ ├── init.cpython-36.pyc
    │ │ │ ├── rnn.cpython-36.pyc
    │ │ │ ├── spectral_norm.cpython-36.pyc
    │ │ │ └── weight_norm.cpython-36.pyc
    │ │ ├── rnn.py
    │ │ ├── spectral_norm.py
    │ │ └── weight_norm.py
    │ └── _VF.py
    ├── onnx
    │ ├── init.py
    │ ├── operators.py
    │ ├── pycache
    │ │ ├── init.cpython-36.pyc
    │ │ ├── operators.cpython-36.pyc
    │ │ ├── symbolic.cpython-36.pyc
    │ │ └── utils.cpython-36.pyc
    │ ├── symbolic.py
    │ └── utils.py
    ├── _ops.py
    ├── optim
    │ ├── adadelta.py
    │ ├── adagrad.py
    │ ├── adamax.py
    │ ├── adam.py
    │ ├── asgd.py
    │ ├── init.py
    │ ├── lbfgs.py
    │ ├── lr_scheduler.py
    │ ├── optimizer.py
    │ ├── pycache
    │ │ ├── adadelta.cpython-36.pyc
    │ │ ├── adagrad.cpython-36.pyc
    │ │ ├── adamax.cpython-36.pyc
    │ │ ├── adam.cpython-36.pyc
    │ │ ├── asgd.cpython-36.pyc
    │ │ ├── init.cpython-36.pyc
    │ │ ├── lbfgs.cpython-36.pyc
    │ │ ├── lr_scheduler.cpython-36.pyc
    │ │ ├── optimizer.cpython-36.pyc
    │ │ ├── rmsprop.cpython-36.pyc
    │ │ ├── rprop.cpython-36.pyc
    │ │ ├── sgd.cpython-36.pyc
    │ │ └── sparse_adam.cpython-36.pyc
    │ ├── rmsprop.py
    │ ├── rprop.py
    │ ├── sgd.py
    │ └── sparse_adam.py
    ├── pycache
    │ ├── functional.cpython-36.pyc
    │ ├── hub.cpython-36.pyc
    │ ├── init.cpython-36.pyc
    │ ├── _jit_internal.cpython-36.pyc
    │ ├── _ops.cpython-36.pyc
    │ ├── random.cpython-36.pyc
    │ ├── serialization.cpython-36.pyc
    │ ├── _six.cpython-36.pyc
    │ ├── storage.cpython-36.pyc
    │ ├── _storage_docs.cpython-36.pyc
    │ ├── tensor.cpython-36.pyc
    │ ├── _tensor_docs.cpython-36.pyc
    │ ├── _tensor_str.cpython-36.pyc
    │ ├── _torch_docs.cpython-36.pyc
    │ ├── _utils.cpython-36.pyc
    │ ├── _utils_internal.cpython-36.pyc
    │ └── version.cpython-36.pyc
    ├── random.py
    ├── serialization.py
    ├── share
    │ └── cmake
    │ ├── ATen
    │ │ └── ATenConfig.cmake
    │ ├── Caffe2
    │ │ ├── Caffe2Config.cmake
    │ │ ├── Caffe2ConfigVersion.cmake
    │ │ ├── Caffe2Targets.cmake
    │ │ ├── Caffe2Targets-release.cmake
    │ │ ├── Modules_CUDA_fix
    │ │ │ ├── FindCUDA.cmake
    │ │ │ └── upstream
    │ │ │ ├── CMakeInitializeConfigs.cmake
    │ │ │ ├── FindCUDA
    │ │ │ │ ├── make2cmake.cmake
    │ │ │ │ ├── parse_cubin.cmake
    │ │ │ │ ├── run_nvcc.cmake
    │ │ │ │ └── select_compute_arch.cmake
    │ │ │ ├── FindCUDA.cmake
    │ │ │ ├── FindPackageHandleStandardArgs.cmake
    │ │ │ └── FindPackageMessage.cmake
    │ │ └── public
    │ │ ├── cuda.cmake
    │ │ ├── gflags.cmake
    │ │ ├── glog.cmake
    │ │ ├── mkl.cmake
    │ │ ├── mkldnn.cmake
    │ │ ├── protobuf.cmake
    │ │ ├── threads.cmake
    │ │ └── utils.cmake
    │ ├── Gloo
    │ │ ├── GlooConfig.cmake
    │ │ ├── GlooConfigVersion.cmake
    │ │ ├── GlooTargets.cmake
    │ │ └── GlooTargets-release.cmake
    │ └── Torch
    │ ├── TorchConfig.cmake
    │ └── TorchConfigVersion.cmake
    ├── _six.py
    ├── sparse
    │ ├── init.py
    │ └── pycache
    │ └── init.cpython-36.pyc
    ├── _storage_docs.py
    ├── storage.py
    ├── _tensor_docs.py
    ├── tensor.py
    ├── _tensor_str.py
    ├── testing
    │ ├── init.py
    │ └── pycache
    │ └── init.cpython-36.pyc
    ├── _thnn
    │ ├── init.py
    │ ├── pycache
    │ │ ├── init.cpython-36.pyc
    │ │ └── utils.cpython-36.pyc
    │ └── utils.py
    ├── _torch_docs.py
    ├── utils
    │ ├── backcompat
    │ │ ├── init.py
    │ │ └── pycache
    │ │ └── init.cpython-36.pyc
    │ ├── bottleneck
    │ │ ├── init.py
    │ │ ├── main.py
    │ │ └── pycache
    │ │ ├── init.cpython-36.pyc
    │ │ └── main.cpython-36.pyc
    │ ├── checkpoint.py
    │ ├── collect_env.py
    │ ├── cpp_extension.py
    │ ├── _cpp_extension_versioner.py
    │ ├── data
    │ │ ├── dataloader.py
    │ │ ├── dataset.py
    │ │ ├── distributed.py
    │ │ ├── init.py
    │ │ ├── pycache
    │ │ │ ├── dataloader.cpython-36.pyc
    │ │ │ ├── dataset.cpython-36.pyc
    │ │ │ ├── distributed.cpython-36.pyc
    │ │ │ ├── init.cpython-36.pyc
    │ │ │ └── sampler.cpython-36.pyc
    │ │ └── sampler.py
    │ ├── dlpack.py
    │ ├── ffi
    │ │ ├── init.py
    │ │ └── pycache
    │ │ └── init.cpython-36.pyc
    │ ├── file_baton.py
    │ ├── hooks.py
    │ ├── init.py
    │ ├── model_zoo.py
    │ └── pycache
    │ ├── checkpoint.cpython-36.pyc
    │ ├── collect_env.cpython-36.pyc
    │ ├── cpp_extension.cpython-36.pyc
    │ ├── _cpp_extension_versioner.cpython-36.pyc
    │ ├── dlpack.cpython-36.pyc
    │ ├── file_baton.cpython-36.pyc
    │ ├── hooks.cpython-36.pyc
    │ ├── init.cpython-36.pyc
    │ └── model_zoo.cpython-36.pyc
    ├── _utils_internal.py
    ├── _utils.py
    └── version.py

    122 directories, 1067 files

    展开全文
  • PyTorch 开箱即用,带有 4 个这样的运算符,它们都在元素级运行: dist.reduce_op.SUM dist.reduce_op.PRODUCT dist.reduce_op.MAX dist.reduce_op.MIN 除了 dist.all_reduce(tensor, op, group) 之外,PyTorch 中...

    点上方计算机视觉联盟获取更多干货

    仅作学术分享,不代表本公众号立场,侵权联系删除

    转载于:商汤

    AI博士笔记系列推荐

    周志华《机器学习》手推笔记正式开源!可打印版本附pdf下载链接

    0 前言

    由于大规模机器学习的广泛普及,超大型深度学习模型的提出,联邦学习等分布式学习方法的快速发展,分布式机器学习模型训练与部署技术已经日益成为研究者和开发者的必备技术。PyTorch 作为应用最为广泛的深度学习框架,也发展出了一套分布式学习的解决方法。本文由浅入深讲解 torch.distributed 这一并行计算包的概念,实现细节和应用方式,并带大家快速入门 PyTorch 分布式训练。

    1 Torch.distributed 概念与定义

    定义:首先我们提供 Torch.distributed 的官方定义

    • torch.distributed 包为运行在一台或多台机器上的多个计算节点之间的 PyTorch 提供支持多进程并行性通信的原语。他能轻松地并行化在跨进程和机器集群的计算。

    • torch.nn.parallel.DistributedDataParalle(DDP) 是建立在此功能的基础上,以提供同步的分布式训练作为任何 PyTorch 模型的包装器。

    可以注意到的是,torch.distributed 的核心功能是进行多进程级别的通信(而非多线程),以此达到多卡多机分布式训练的目的。这与基于 DataParrallel 的多线程训练有明显区别。

    通信方式:torch.distributed 的底层通信主要使用 Collective Communication (c10d) library 来支持跨组内的进程发送张量,并主要支持两种类型的通信 API:

    • collective communication APIs: Distributed Data-Parallel Training (DDP)

    • P2P communication APIs: RPC-Based Distributed Training (RPC)

    这两种通信 API 在 PyTorch 中分别对应了两种分布式训练方式:Distributed Data-Parallel Training (DDP) 和 RPC-Based Distributed Training (RPC)。本文着重探讨 Distributed Data-Parallel Training (DDP) 的通信方式和 API

    基础概念: 下面介绍一些 torch.distributed 中的关键概念以供参考。这些概念在编写程序时至关重要

    • Group(进程组)是我们所有进程的子集。

    • Backend(后端)进程通信库。PyTorch 支持 NCCL,GLOO,MPI。本文不展开讲几种通信后端的区别,感兴趣的同学可以参考官方文档

    • world_size(世界大小)在进程组中的进程数。

    • Rank(秩)分配给分布式进程组中每个进程的唯一标识符。它们始终是从 0 到 world_size 的连续整数。

    2 Torch.distributed 实例

    例子 1:初始化

    """run.py:"""#!/usr/bin/env pythonimport osimport torchimport torch.distributed as distfrom torch.multiprocessing import Process
    def run(rank, size):    """ Distributed function to be implemented later. """    pass
    def init_process(rank, size, fn, backend='gloo'):    """ Initialize the distributed environment. """    os.environ['MASTER_ADDR'] = '127.0.0.1'    os.environ['MASTER_PORT'] = '29500'    dist.init_process_group(backend, rank=rank, world_size=size)fn(rank, size)
    if __name__ == "__main__":    size = 2    processes = []    for rank in range(size):        p = Process(target=init_process, args=(rank, size, run))        p.start()        processes.append(p)
        for p in processes:        p.join()
    

    本段程序执行了下面三件事

    1. 创建了两个进程

    2. 分别加入一个进程组

    3. 分别运行 run 函数。此时 run 是一个空白函数,之后的例子会扩充这个函数的内容并在函数内完成多进程的通信操作。

    例子 2:点对点通信

    最简单的多进程通信方式是点对点通信。信息从一个进程被发送到另一个进程。

    def run(rank, size):    tensor = torch.zeros(1)    if rank == 0:        tensor += 1        # Send the tensor to process 1        dist.send(tensor=tensor, dst=1)    else:        # Receive tensor from process 0        dist.recv(tensor=tensor, src=0)    print('Rank ', rank, ' has data ', tensor[0])
    
    

    在上面的示例中,两个进程都从 tensor(0) 开始,然后进程 0 递增张量并将其发送到进程 1,以便它们都以 tensor(1) 结尾。请注意,进程 1 需要分配内存以存储它将接收的数据。

    另请注意,send / recv 被阻塞:两个过程都停止,直到通信完成。我们还有另外一种无阻塞的通信方式,请看下例

    """Non-blocking point-to-point communication."""
    def run(rank, size):    tensor = torch.zeros(1)    req = None    if rank == 0:        tensor += 1        # Send the tensor to process 1        req = dist.isend(tensor=tensor, dst=1)        print('Rank 0 started sending')    else:        # Receive tensor from process 0        req = dist.irecv(tensor=tensor, src=0)        print('Rank 1 started receiving')    req.wait()    print('Rank ', rank, ' has data ', tensor[0])
    
    

    我们通过调用 wait 函数以使自己在子进程执行过程中保持休眠状态。由于我们不知道何时将数据传递给其他进程,因此在 req.wait() 完成之前,我们既不应该修改发送的张量也不应该访问接收的张量以防止不确定的写入。

    例子 3:进程组间通信

    与点对点通信相反,集合允许跨组中所有进程的通信模式。例如,为了获得所有过程中所有张量的总和,我们可以使用 dist.all_reduce(tensor, op, group) 函数进行组间通信

    """ All-Reduce example."""def run(rank, size):    """ Simple point-to-point communication. """    group = dist.new_group([0, 1])    tensor = torch.ones(1)    dist.all_reduce(tensor, op=dist.reduce_op.SUM, group=group)    print('Rank ', rank, ' has data ', tensor[0])
    
    

    这段代码首先将进程 0 和 1 组成进程组,然后将各自进程中 tensor(1) 相加。由于我们需要组中所有张量的总和,因此我们将 dist.reduce_op.SUM 用作化简运算符。一般来说,任何可交换的数学运算都可以用作运算符。PyTorch 开箱即用,带有 4 个这样的运算符,它们都在元素级运行:

    • dist.reduce_op.SUM

    • dist.reduce_op.PRODUCT

    • dist.reduce_op.MAX

    • dist.reduce_op.MIN

    除了 dist.all_reduce(tensor, op, group) 之外,PyTorch 中目前共有 6 种组间通信方式

    distributed.scatter(tensor, scatter_list=None, src=0, group=None, async_op=False):将张量 scatter_list[i] 复制第 i 个进程的过程。例如,在实现分布式训练时,我们将数据分成四份并分别发送到不同的机子上计算梯度。scatter 函数可以用来将信息从 src 进程发送到其他进程上。



    tensor发送的数据
    scatter_list存储发送数据的列表(只需在 src 进程中指定)
    dst发送进程的rank
    group指定进程组
    async_op该 op 是否是异步操作

    distributed.gather(tensor, gather_list=None, dst=0, group=None, async_op=False):从 dst 中的所有进程复制 tensor。例如,在实现分布式训练时,不同进程计算得到的梯度需要汇总到一个进程,并计算平均值以获得统一的梯度。gather 函数可以将信息从别的进程汇总到 dst 进程。



    tensor接受的数据
    gather_list存储接受数据的列表(只需在dst进程中指定)
    dst汇总进程的rank
    group指定进程组
    async_op该op是否是异步操作

    distributed.reduce(tensor, dst, op, group):将 op 应用于所有 tensor,并将结果存储在 dst 中。

    distributed.all_reduce(tensor, op, group):与 reduce 相同,但是结果存储在所有进程中。

    distributed.broadcast(tensor, src, group):将tensor从src复制到所有其他进程。

    distributed.all_gather(tensor_list, tensor, group):将所有进程中的 tensor 从所有进程复制到 tensor_list

    例子 4:分布式梯度下降

    分布式梯度下降脚本将允许所有进程在其数据 batch 上计算其模型的梯度,然后平均其梯度。为了在更改进程数时确保相似的收敛结果,我们首先必须对数据集进行分区。

    """ Dataset partitioning helper """class Partition(object):
        def __init__(self, data, index):        self.data = data        self.index = index
        def __len__(self):        return len(self.index)
        def __getitem__(self, index):        data_idx = self.index[index]        return self.data[data_idx]
    class DataPartitioner(object):
        def __init__(self, data, sizes=[0.7, 0.2, 0.1], seed=1234):        self.data = data        self.partitions = []        rng = Random()        rng.seed(seed)        data_len = len(data)        indexes = [x for x in range(0, data_len)]        rng.shuffle(indexes)
            for frac in sizes:            part_len = int(frac * data_len)            self.partitions.append(indexes[0:part_len])            indexes = indexes[part_len:]
        def use(self, partition):        return Partition(self.data, self.partitions[partition])
    
    

    使用上面的代码片段,我们现在可以使用以下几行简单地对任何数据集进行分区

    """ Partitioning MNIST """def partition_dataset():    dataset = datasets.MNIST('./data', train=True, download=True,                             transform=transforms.Compose([                                 transforms.ToTensor(),                                 transforms.Normalize((0.1307,), (0.3081,))                             ]))    size = dist.get_world_size()    bsz = 128 / float(size)    partition_sizes = [1.0 / size for _ in range(size)]    partition = DataPartitioner(dataset, partition_sizes)    partition = partition.use(dist.get_rank())    train_set = torch.utils.data.DataLoader(partition,                                         batch_size=bsz,                                         shuffle=True)    return train_set, bsz
    
    

    假设我们有 2 个进程,则每个进程的 train_set 为 60000/2 = 30000 个样本。我们还将 batch 大小除以进程数,以使整体 batch 大小保持为 128。

    现在,我们可以编写通常的向前-向后优化训练代码,并添加一个函数调用以平均模型的梯度。

    """ Distributed Synchronous SGD Example """def run(rank, size):    torch.manual_seed(1234)    train_set, bsz = partition_dataset()    model = Net()    optimizer = optim.SGD(model.parameters(),                          lr=0.01, momentum=0.5)
        num_batches = ceil(len(train_set.dataset) / float(bsz))    for epoch in range(10):        epoch_loss = 0.0        for data, target in train_set:            optimizer.zero_grad()            output = model(data)            loss = F.nll_loss(output, target)            epoch_loss += loss.item()            loss.backward()            average_gradients(model)            optimizer.step()        print('Rank ', dist.get_rank(), ', epoch ',              epoch, ': ', epoch_loss / num_batches)
    
    

    仍然需要执行 average_gradients(model) 函数,该函数只需要一个模型并计算在所有 rank 上梯度的平均值。

    """ Gradient averaging. """def average_gradients(model):    size = float(dist.get_world_size())    for param in model.parameters():        dist.all_reduce(param.grad.data, op=dist.reduce_op.SUM)        param.grad.data /= size
    
    

    3 PyTorch 并行/分布式训练

    在掌握 torch.distributed 的基础的前提下,我们可以根据自身机器和任务的具体情况使用不同的分布式或并行训练方式:

    • 如果数据和模型可以放在一个 GPU 中,并且不关心训练速度,请使用单设备训练。

    • 如果单个服务器上有多个 GPU,并且您希望更改较少的代码来加快训练速度,请使用单机多 GPU DataParallel。

    • 如果单个服务器上有多个 GPU,且您希望进一步添加代码并加快训练速度,请使用单机多 GPU DistributedDataParallel。

    • 如果应用程序需要跨多个服务器,请使用多机 DistributedDataParallel 和启动脚本。

    • 如果预计会出现错误(例如,OOM),或者在训练期间资源可以动态加入和离开,请使用 torch.elastic 进行分布式训练。

    3.1 DataParallel

    class torch.nn.DataParallel(module, device_ids=None, output_device=None, dim=0)
    

    DataParallel 自动分割您的数据,并将作业订单发送到多个 GPU 上的多个模型。每个模型完成工作后,DataParallel 会收集并合并结果,然后再将结果返回给您。DataParallel 将相同的模型复制到所有 GPU,其中每个 GPU 消耗输入数据的不同分区。在使用此方法时,batch 理大小应大于使用的 GPU 数量。我们需要注意的是,DataParallel 是通过多线程的方式进行的并行训练,所以并没有使用 torch.distributed 里的线程通信 API。的其运行过程如下图所示

    例子 5 DataParallel

    创建 dump 数据集和定义模型

    class RandomDataset(Dataset):
        def __init__(self, size, length):        self.len = length        self.data = torch.randn(length, size)
        def __getitem__(self, index):        return self.data[index]
        def __len__(self):        return self.len
    rand_loader = DataLoader(dataset=RandomDataset(input_size, data_size),                         batch_size=batch_size, shuffle=True)
    class Model(nn.Module):    # Our model
        def __init__(self, input_size, output_size):        super(Model, self).__init__()        self.fc = nn.Linear(input_size, output_size)
        def forward(self, input):        output = self.fc(input)        print("\tIn Model: input size", input.size(),              "output size", output.size())
            return output
    
    

    定义模型,放入设备并用 DataParallel 对象进行包装

    model = Model(input_size, output_size)if torch.cuda.device_count() > 1:  print("Let's use", torch.cuda.device_count(), "GPUs!")  # dim = 0 [30, xxx] -> [10, ...], [10, ...], [10, ...] on 3 GPUs  model = nn.DataParallel(model)
    model.to(device)
    
    

    运行模型并输出

    for data in rand_loader:    input = data.to(device)    output = model(input)    print("Outside: input size", input.size(),          "output_size", output.size())In Model: input size torch.Size([15, 5]) output size torch.Size([15, 2])        In Model: input size torch.Size([15, 5]) output size torch.Size([15, 2])Outside: input size torch.Size([30, 5]) output_size torch.Size([30, 2])        In Model: input size torch.Size([15, 5]) output size torch.Size([15, 2])        In Model: input size torch.Size([15, 5]) output size torch.Size([15, 2])Outside: input size torch.Size([30, 5]) output_size torch.Size([30, 2])        In Model: input size torch.Size([15, 5]) output size torch.Size([15, 2])        In Model: input size torch.Size([15, 5]) output size torch.Size([15, 2])Outside: input size torch.Size([30, 5]) output_size torch.Size([30, 2])        In Model: input size torch.Size([5, 5]) output size torch.Size([5, 2])        In Model: input size torch.Size([5, 5]) output size torch.Size([5, 2])Outside: input size torch.Size([10, 5]) output_size torch.Size([10, 2])
    
    

    我们可以看到,在模型中,数据是按照batch大小的维度被均匀分成多份。在输出后,多块 GPU 上的数据进行合并。

    3.2 DistributedDataParallel

    当我们了解了 DataParallel 后,下面开始介绍一种基于 torch.distributed 中进程通信函数包装的高层 API

    CLASS torch.nn.parallel.DistributedDataParallel(module, device_ids=None, output_device=None, dim=0, broadcast_buffers=True, process_group=None, bucket_cap_mb=**25**, find_unused_parameters=False, check_reduction=False, gradient_as_bucket_view=False)
    

    既然 DataParallel 可以进行并行的模型训练,那么为什么还需要提出 DistributedDataParallel呢?这里我们就需要知道两种方法的实现原理与区别:

    1. 如果模型太大而无法容纳在单个 GPU 上,则必须使用模型并行将其拆分到多个 GPU 中。DistributedDataParallel 可以与模型并行一起使用;但 DataParallel 因为必须将模型放入单块 GPU 中,所以难以完成大型模型的训练。

    2. DataParallel 是单进程,多线程的并行训练方式,并且只能在单台机器上运行,而DistributedDataParallel 是多进程,并且适用于单机和多机训练。DistributedDataParallel 还预先复制模型,而不是在每次迭代时复制模型,并避免了全局解释器锁定。

    3. 如果您的两个数据都太大而无法容纳在一台计算机和上,而您的模型又太大了以至于无法安装在单个 GPU 上,则可以将模型并行(跨多个 GPU 拆分单个模型)与 DistributedDataParallel 结合使用。在这种情况下,每个 DistributedDataParallel 进程都可以并行使用模型,而所有进程都将并行使用数据。

    例子 6 DistributedDataParallel

    首先我们需要创建一系列进程,其中需要用到 torch.multiprocessing 中的函数

    torch.multiprocessing.spawn(fn, args=(), nprocs=1, join=True, daemon=False, start_method='spawn')
    

    该函数使用 args 作为参数列表运行函数fn,并创建 nprocs 个进程。

    如果其中一个进程以非零退出状态退出,则其余进程将被杀死,并引发异常,以终止原因。如果子进程中捕获到异常,则将其转发并将其回溯包括在父进程中引发的异常中。

    该函数会通过 fn(i,args) 的形式被调用,其中i是进程索引,而 args 是传递的参数元组。

    基于创建的的进程,我们初始化进程组

    import osimport tempfileimport torchimport torch.distributed as distimport torch.nn as nnimport torch.optim as optimimport torch.multiprocessing as mp
    from torch.nn.parallel import DistributedDataParallel as DDP
    def setup(rank, world_size):    os.environ['MASTER_ADDR'] = 'localhost'    os.environ['MASTER_PORT'] = '12355'
        # initialize the process group    dist.init_process_group("gloo", rank=rank, world_size=world_size)
        # Explicitly setting seed to make sure that models created in two processes    # start from same random weights and biases.    torch.manual_seed(42)
    def cleanup():    dist.destroy_process_group()
    
    

    这里我们使用到了

    torch.distributed.init_process_group(backend, init_method=None, timeout=datetime.timedelta(0, 1800), world_size=-1, rank=-1, store=None, group_name='')
    

    这个 API 来初始化默认的分布式进程组,这还将初始化分布式程序包。

    该函数有两种主要的调用方式:

    1. 明确指定 store,rank 和 world_size。

    2. 指定 init_method(URL 字符串),它指示在何处/如何发现对等方。(可选)指定 rank 和 world_size,或在 URL 中编码所有必需的参数并忽略它们。

    现在,让我们创建一个 toy model,将其与 DDP 封装在一起,并提供一些虚拟输入数据。请注意,由于 DDP 将 0 级进程中的模型状态广播到 DDP 构造函数中的所有其他进程,因此无需担心不同的 DDP 进程从不同的模型参数初始值开始。

    class ToyModel(nn.Module):    def __init__(self):        super(ToyModel, self).__init__()        self.net1 = nn.Linear(10, 10)        self.relu = nn.ReLU()        self.net2 = nn.Linear(10, 5)
        def forward(self, x):        return self.net2(self.relu(self.net1(x)))
    def demo_basic(rank, world_size):    setup(rank, world_size)    # Assume we have 8 GPU in total    # setup devices for this process, rank 1 uses GPUs [0, 1, 2, 3] and    # rank 2 uses GPUs [4, 5, 6, 7].    n = torch.cuda.device_count() // world_size    device_ids = list(range(rank * n, (rank + 1) * n))
        # create model and move it to device_ids[0]    model = ToyModel().to(device_ids[0])    # output_device defaults to device_ids[0]    ddp_model = DDP(model, device_ids=device_ids)
        loss_fn = nn.MSELoss()    optimizer = optim.SGD(ddp_model.parameters(), lr=0.001)
        optimizer.zero_grad()    outputs = ddp_model(torch.randn(20, 10))    labels = torch.randn(20, 5).to(device_ids[0])    loss_fn(outputs, labels).backward()    optimizer.step()
        cleanup()
    def run_demo(demo_fn, world_size):    mp.spawn(demo_fn,             args=(world_size,),             nprocs=world_size,             join=True)if __name__ == "__main__":    run_demo(demo_basic, 2)
    
    

    例子 7 将 DDP 与模型并行性结合

    DDP 还可以与多 GPU 模型一起使用,但是不支持进程内的复制。您需要为每个模型副本创建一个进程,与每个进程的多个模型副本相比,通常可以提高性能。当训练具有大量数据的大型模型时,DDP 包装多 GPU 模型特别有用。使用此功能时,需要小心地实现多 GPU 模型,以避免使用硬编码的设备,因为会将不同的模型副本放置到不同的设备上。

    例如,下面这个模型显式的将不同的模块放置在不同的 GPU 上

    class ToyMpModel(nn.Module):    def __init__(self, dev0, dev1):        super(ToyMpModel, self).__init__()        self.dev0 = dev0        self.dev1 = dev1        self.net1 = torch.nn.Linear(10, 10).to(dev0)        self.relu = torch.nn.ReLU()        self.net2 = torch.nn.Linear(10, 5).to(dev1)
        def forward(self, x):        x = x.to(self.dev0)        x = self.relu(self.net1(x))        x = x.to(self.dev1)        return self.net2(x)
    
    

    将多 GPU 模型传递给 DDP 时,不得设置 device_ids 和 output_device。输入和输出数据将通过应用程序或模型 forward() 方法放置在适当的设备中。

    def demo_model_parallel(rank, world_size):    setup(rank, world_size)
        # setup mp_model and devices for this process    dev0 = rank * 2    dev1 = rank * 2 + 1    mp_model = ToyMpModel(dev0, dev1)    ddp_mp_model = DDP(mp_model)
        loss_fn = nn.MSELoss()    optimizer = optim.SGD(ddp_mp_model.parameters(), lr=0.001)
        optimizer.zero_grad()    # outputs will be on dev1    outputs = ddp_mp_model(torch.randn(20, 10))    labels = torch.randn(20, 5).to(dev1)    loss_fn(outputs, labels).backward()    optimizer.step()
        cleanup()if __name__ == "__main__":    run_demo(demo_model_parallel, 4)
    
    

    例子 8 保存和加载检查点

    使用 DDP 时,一种优化方法是仅在一个进程中保存模型,然后将其加载到所有进程中,从而减少写开销。

    def demo_checkpoint(rank, world_size):    setup(rank, world_size)
        # setup devices for this process, rank 1 uses GPUs [0, 1, 2, 3] and    # rank 2 uses GPUs [4, 5, 6, 7].    n = torch.cuda.device_count() // world_size    device_ids = list(range(rank * n, (rank + 1) * n))
        model = ToyModel().to(device_ids[0])    # output_device defaults to device_ids[0]    ddp_model = DDP(model, device_ids=device_ids)
        loss_fn = nn.MSELoss()    optimizer = optim.SGD(ddp_model.parameters(), lr=0.001)
        CHECKPOINT_PATH = tempfile.gettempdir() + "/model.checkpoint"    if rank == 0:        # All processes should see same parameters as they all start from same        # random parameters and gradients are synchronized in backward passes.        # Therefore, saving it in one process is sufficient.        torch.save(ddp_model.state_dict(), CHECKPOINT_PATH)
        # Use a barrier() to make sure that process 1 loads the model after process    # 0 saves it.    dist.barrier()    # configure map_location properly    rank0_devices = [x - rank * len(device_ids) for x in device_ids]    device_pairs = zip(rank0_devices, device_ids)    map_location = {'cuda:%d' % x: 'cuda:%d' % y for x, y in device_pairs}    ddp_model.load_state_dict(        torch.load(CHECKPOINT_PATH, map_location=map_location))
        optimizer.zero_grad()    outputs = ddp_model(torch.randn(20, 10))    labels = torch.randn(20, 5).to(device_ids[0])    loss_fn = nn.MSELoss()    loss_fn(outputs, labels).backward()    optimizer.step()
        # Use a barrier() to make sure that all processes have finished reading the    # checkpoint    dist.barrier()
        if rank == 0:        os.remove(CHECKPOINT_PATH)
        cleanup()
    
    

    4 总结

    本文讲解了 torch.distributed 这一并行计算包的概念,实现细节和应用方式,并带大家快速入门 PyTorch 分布式训练。我们着重分析了 DataParallel 和 DistributedDataParallel 两种并行训练 API 的使用方法和原理异同

    参考资料

    https://pytorch.org/docs/stable/distributed.html

    https://pytorch.apachecn.org/docs/1.7/59.html

    -------------------

    END

    --------------------

    我是王博Kings,985AI博士,华为云专家、CSDN博客专家(人工智能领域优质作者)。单个AI开源项目现在已经获得了2100+标星。现在在做AI相关内容,欢迎一起交流学习、生活各方面的问题,一起加油进步!

    我们微信交流群涵盖以下方向(但并不局限于以下内容):人工智能,计算机视觉,自然语言处理,目标检测,语义分割,自动驾驶,GAN,强化学习,SLAM,人脸检测,最新算法,最新论文,OpenCV,TensorFlow,PyTorch,开源框架,学习方法...

    这是我的私人微信,位置有限,一起进步!

    王博的公众号,欢迎关注,干货多多

    王博Kings的系列手推笔记(附高清PDF下载):

    博士笔记 | 周志华《机器学习》手推笔记第一章思维导图

    博士笔记 | 周志华《机器学习》手推笔记第二章“模型评估与选择”

    博士笔记 | 周志华《机器学习》手推笔记第三章“线性模型”

    博士笔记 | 周志华《机器学习》手推笔记第四章“决策树”

    博士笔记 | 周志华《机器学习》手推笔记第五章“神经网络”

    博士笔记 | 周志华《机器学习》手推笔记第六章支持向量机(上)

    博士笔记 | 周志华《机器学习》手推笔记第六章支持向量机(下)

    博士笔记 | 周志华《机器学习》手推笔记第七章贝叶斯分类(上)

    博士笔记 | 周志华《机器学习》手推笔记第七章贝叶斯分类(下)

    博士笔记 | 周志华《机器学习》手推笔记第八章集成学习(上)

    博士笔记 | 周志华《机器学习》手推笔记第八章集成学习(下)

    博士笔记 | 周志华《机器学习》手推笔记第九章聚类

    博士笔记 | 周志华《机器学习》手推笔记第十章降维与度量学习

    博士笔记 | 周志华《机器学习》手推笔记第十一章稀疏学习

    博士笔记 | 周志华《机器学习》手推笔记第十二章计算学习理论

    博士笔记 | 周志华《机器学习》手推笔记第十三章半监督学习

    博士笔记 | 周志华《机器学习》手推笔记第十四章概率图模型

    点分享

    点收藏

    点点赞

    点在看

    展开全文
  • pytorch源码解析:Python层

    千次阅读 2018-07-31 10:55:16
    尝试使用了pytorch,相比其他深度学习框架,pytorch显得简洁易懂。花时间读了部分源码,主要结合简单例子带着问题阅读,不涉及源码中C拓展库的实现。 一个简单例子 实现单层softmax二分类,输入特征维度为4,输出...
  • 否则不更新它们的值 weight 公式中的 \gamma,初始化为全 1 tensor bias 公式中的 \beta,初始化为全 0 tensor 这里贴一下 PyTorch源码: class _NormBase(Module): """Common base of _InstanceNorm and _...
  • BERT-pytorch Introduction: This mechine could be trained by "train_demo.py" And there are mainly two datasets demo, one is a json file about poem, another is a conversation demo created by myself. ...
  • 选取的代码版本为 junyanz/pytorch-CycleGAN-and-pix2pix 本文主要分析了网络架构与loss的计算 train.py 该脚本为训练的起始脚本,在前几行首先实例化TrainOptions(继承了BaseOptions)来接收命令行输入参数 opt = ...
  • 火炬优化器 ...https://pytorch-optimizer.rtfd.io 支持的优化器 A2GradExp https://arxiv.org/abs/1810.00553 A2GradInc https://arxiv.org/abs/1810.00553 A2GradUni https://arxiv.org/abs/1810.00
  • [pytorch源码解读]之DenseNet的源码解读

    千次阅读 2020-04-24 17:39:24
    pytorch的densenet模块在torchvision的models中。 DenseNet由多个DenseBlock组成。 所以DenseNet一共有DenseNet-121,DenseNet-169,DenseNet-201和DenseNet-264 四种实现方式。 拿DenseNet-121为例,121表示的是...
  • CNN Image Retrieval in PyTorch: Training and evaluating CNNs for Image Retrieval in PyTorch This is a Python toolbox that implements the training and testing of the approach described in our papers: ...
  • Transformer解读(论文 + PyTorch源码

    万次阅读 多人点赞 2019-04-08 20:22:17
    因此,这才仔仔细细地撸了这篇“古老”的论文和源码,这里将主要对照论文和相应的PyTorch源码进行逐一对照解读。因笔者能力有限,如有不详实之处,读者可移步至文末的传送门去看更多细节,并欢迎指出~ 文章目录 ...
  • MaskRCNN-BenchMark pytorch源码阅读笔记

    千次阅读 多人点赞 2019-10-16 14:26:10
    源码地址:https://github.com/facebookresearch/maskrcnn-benchmark modeling 部分解析来自:模型定义(modeling)之骨架网络(backbone),博主将resnet,fpn等实现细节讲述的非常详细,根据最新发布的maskrcnn-...
  • 1. 优化器 Optimizer 1.0 基本用法 优化器主要是在模型训练阶段对模型可学习参数进行更新, 常用优化器有 SGD,RMSprop,Adam等 优化器初始化时传入传入模型的可学习参数,以及其他超参数如lr,momentum等 在训练...
  • This is a PyTorch implementation of FOTS. Questions Should I fix weights of the backbone network, resnet50 ? for param in self.backbone.parameters(): param.requires_grad = False Answer: Yes, the ...
  • 本文会基于Pytorch源码,对Adagrad进行学习。 Adagrad 在SGD的年代,我们只能通过学习率(learning rate)来宏观控制网络的参数的学习速度,这从直观上是不太细致的。 随着人脑突触的实验进展,发现人脑神经元是有...
  • 3.1 源码解析 train.py 讲解 此代码为C3D模型的训练部分,分为训练前的准备,和训练部分两大部分。 1.训练前的准备 1.1 参数的设置 nEpochs = 101 # Number of epochs for training resume_epoch = 0 # Default is...
  • 目前神经网络的监督学习过程通常为: 数据加载(load)进神经网络 经过网络参数对数据的计算,得出预测值(predict) 根据预测值与标注值(label)之间的差距,产生损失(loss) ...本文主要想基于Pytorch
  • 读完 SSD 的论文内容能大致了解这一算法的核心思想和算法流程,但要将其应用到实际问题上还需要去读代码。SSD 的作者是用 Caffe ...恰好某站上有个超细节的up主录制了 Pytorch 实现 SSD 的视频,而且项目所需恰好也是Py
  • 完整代码见:https://github.com/yangyuke001/FIIQA-PyTorch 不废话,上干货! 1 数据准备 训练集: http://pan.baidu.com/s/1mhFBusg 验证集: http://pan.baidu.com/s/1miMDkt6 测试集: ...
  • # -*- coding: utf-8 -*- """ 用序列到序列神经网络和注意力进行翻译 ************************************...https://github.com/spro/practical-pytorch&gt;`_ 这个教程主要讲解用一个神经网...
  • Swapping to ADAMW Optimizer ADAMW may provide better convergence and stability when training than SGD. In the future this may replace SGD within this repo. python train.py data.train_manifest=data/...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,675
精华内容 670
关键字:

optimizerpytorch源码