Pytorch:自定义网络层实例

  

<>强自定义Autograd函数

  

对于浅层的网络,我们可以手动的书写前向传播和反向传播过程。但是当网络变得很大时,特别是在做深度学习时,网络结构变得复杂。前向传播和反向传播也随之变得复杂,手动书写这两个过程就会存在很大的困难。幸运地是在pytorch中存在了自动微分的包,可以用来解决该问题。在使用自动求导的时候,网络的前向传播会定义一个计算图计算图,图中的节点是张量(张量),两个节点之间的边对应了两个张量之间变换关系的函数。有了计算图的存在,张量的梯度计算也变得容易了些,例如,x是一个张量,其属性x。requires_grad=True,那么x.grad就是一个保存这个张量x的梯度的一些标量值。

  

最基础的自动求导操作在底层就是作用在两个张量上。前向传播函数是从输入张量到输出张量的计算过程;反向传播是输入输出张量的梯度(一些标量)并输出输入张量的梯度(一些标量)。在pytorch中我们可以很容易地定义自己的自动求导操作,通过继承torch.autograd.Function并定义向前和向后函数。

  

向前():前向传播操作。可以输入任意多的参数,任意的python对象都可以。

  

向后():反向传播(梯度公式)。输出的梯度个数需要与所使用的张量个数保持一致,且返回的顺序也要对应起来。

        #继承功能   类LinearFunction(函数):      #注意,前后都是@staticmethods   @staticmethod   #偏见是一个可选参数   def向前(ctx、输入、重量、偏见=None):   # ctx在这里类似自我,ctx的属性可以在落后的中调用   ctx。save_for_backward(输入、重量偏差)   输出=input.mm (weight.t ())   如果偏差不是没有:   输出+=bias.unsqueeze (0) .expand_as(输出)   返回输出      #这个函数>   类MulConstant(函数):   @staticmethod   def向前(ctx,张量,常数):   # ctx上下文对象,可以用来存放信息   #为了向后计算   ctx。常数=常数   张量*返回常数      @staticmethod   grad_output def向后(ctx):   #我们返回尽可能多的输入梯度有参数。   # non-Tensor参数的梯度必须没有。   grad_output * ctx返回。常数,没有   之前      

<强>高阶导数

        grad_x=t.autograd。研究生(y, x, create_graph=True)      grad_grad_x=t.autograd.grad (grad_x [0], x)   之前      

<>强自定义模块

  

计算图和自动求导在定义复杂网络和求梯度的时候非常好用,但对于大型的网络,这个还是有点偏底层。在我们构建网络的时候,经常希望将计算限制在每个层之内(参数更新分层更新)。而且在TensorFlow等其他深度学习框架中都提供了高级抽象结构,因此,在pytorch中也提供了类似的包神经网络,它定义了一组等价于层(层)的模块(模块),一个模块接受输入张量并得到输出张量,同时也会包含可学习的参数。

  

有时候,我们希望运用一些新的且神经网络包中不存在的模块。此时就需要定义自己的模块了。自定义的模块需要继承nn。模块且自定义向前函数。其向前中函数可以接受输入张量并利用其它模型或者其他自动求导操作来产生输出张量。但并不需要重倒写函数,因此神经网络使用了autograd。这也就意味着,需要自定义模块,都必须有对应的autograd函数以调用其中的落后。

        类线性(nn.Module):   def __init__(自我、input_features output_features偏见=True):   超级(线性,自我). __init__ ()   自我。input_features=input_features   自我。output_features=output_features      #神经网络。参数是一种特殊的张量,将得到的   #自动注册为一旦分配模块的参数   #作为一个属性。参数和缓冲区需要注册,或   #他们不会出现在.parameters()(不适用于缓冲区),和   #不会转换时如.cuda ()。您可以使用   # .register_buffer()注册缓冲区。   #(很重要!参数一定需要梯度!)神经网络。默认参数需要渐变。   自我。体重=nn.Parameter(火炬。张量(output_features input_features))   如果偏差:   自我。偏见=nn.Parameter (torch.Tensor (output_features))   其他:   #你应该注册所有可能的参数,但是   如果你想要#可以没有可选的。   自我。register_parameter(“偏见”,没有一个)      #不是一个非常聪明的方式来初始化权重   self.weight.data.uniform_ (-0.1, 0.1)   如果偏差不是没有:   self.bias.data.uniform_ (-0.1, 0.1)      def向前(自我、输入):   #请autograd部分解释这里发生了什么。   LinearFunction返回。应用(输入、自我。重量、self.bias)      def extra_repr(自我):   #(可选)设置额外的信息关于这个模块。您可以测试   #印刷这个类的一个对象。   返回“in_features={}, out_features={},偏见={}' .format (   自我。in_features,自我。out_features,自我。偏见不是没有

Pytorch:自定义网络层实例