Skip to content

PyTorch文档阅读笔记

DingfengShi edited this page Mar 1, 2018 · 6 revisions

PyTorch文档阅读笔记

试用了一下PyTorch,发现PyTorch不但上手快,而且用着灵活,写起来也非常有条理,易读性非常好!

一些细节点

  • 使用Variable包装Tensor,Variable其实只是一个装Tensor的容器,可用于自动求导

    x = torch.randn(3)
    x = Variable(x, requires_grad=True)
    
    y = x * 2
    y.backward(...) #省略号里面shape要和y相同
    #此时
    x.grad  #可以得到梯度值
  • 使用torch.nn包来加速模型建立

    #例子
    #nn里分为两种类型Module(直接在nn里),functional。两者的差别就是该层需不需要参数  
    #比如卷积层,声明需要定义一些参数:  
    nn.Conv2d(1, 6, 5)(inputTensor)  
    #需要声明类后要通过__call__方式调用  
    #而functional对于无参数的网络结构则更方便,比如  
    x = nn.functional.relu(inputTensor)
    #一般functional也有Module的实现,比如  
    x = nn.Relu()(inputTersor)

    注意:torch.nn的输入一定是要带batch维度的,所以就算只有一条数据,也要在最前面补上一个值为1的维度:data.unsqueeze(0)

  • 继承torch.nn.Module来定义模型或者模块
    通过继承该类并重写forward方法即可,不需要写反向传播

    class Net(nn.Module):
    ...
       def __init__(self):
         #通过把子模块赋值给该Module,PyTorch会自动注册(register)到模型的参数列表里,这样对Module调用cuda()等方法的时候便会连同处理到这些子模块
         self.Cov1=nn.Conv2d(10,10,4)
    
         #用sequential能很方便的按顺序堆叠模型
         self.fc = nn.Sequential(
         nn.Linear(input, 64, bias=False),
         nn.BatchNorm1d(64),
         nn.ReLU(True))
       ...
       #只需要重写前向传播,不需要自己写反向传播
       def forward(input):
         return self.fc(input)  
    ...
    net=Net()
    #使用GPU,直接对Module调用cuda()方法即可使里面原定义好的参数放入GPU
    net=net.cuda()
    
    #模型变成GPU以后,输入数据也要调用cuda方法
    out = net.forward(data.cuda())
    
    #一开始要对模型参数的梯度缓存归零
    net.zero_grad() 
    loss = loss_fn(out,target)
    loss.backward(...)
  • 权值的初始化 直接调用nn里的模块不会自动初始化,需要手动处理

    #对某个模块初始化,比如卷积层
    self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3)
    nn.init.xavier_uniform(self.conv1.weight)
    nn.init.constant(self.conv1.bias, 0.1)
    
    #一般定义模块的时候,可以统一对里面的各种层初始化
    def weights_init(m):
      classname=m.__class__.__name__
      if classname.find('Conv') != -1:
          nn.init.xavier_uniform(m.weight)
          nn.init.xavier_uniform(m.bias) 
    
    net = Net()
    #对一个模块调用apply方法,传入的是个函数,会对该模块的所有子模块执行该函数
    net.apply(weights_init) 
  • 使用optimizer更新权值
    对loss进行反向传播只会在缓存里更改grad值,要更新权值还是需要optimizer去处理,用起来也很简单,比如Adam

    import torch.optim as optim
    
    net = Net()
    optimizer = optim.Adam(net.parameters, lr = 0.0001)
    ...
    loss = ..
    loss.backward()
    
    #执行一次更新操作
    optimizer.step()
  • 使用GPU
    如果单独对某些Variable或者Tensor存入GPU中,只需对其执行cuda()方法即可。(Variable和Tensor都右cuda()方法,先把Tensor放入GPU再用Variable包装,和先把Tensor放入Variable都能得到同样的结果)

    ten = torch.FloatTensor(2)
    ten_cuda = ten1.cuda()
    V = autograd.Variable(ten_cuda)
    #和下面能得到同样结果
    ten = torch.FloatTensor(2)
    V = autograd.Variable(ten)
    V = V.cuda()
Clone this wiki locally