https://blog.csdn.net/u012609509/article/details/81203436
比如下图表示y=x⋅sin(x⋅a+b)的计算图。沿着计算图应用链式求导法则就可以求出梯度。
在底层实现中,PyTorch中的计算图的每个结点都是一个Function对象,这个对象可以使用apply()进行操作。
在前向传播过程中,Autograd一边执行着前向计算,一边搭建一个graph,这个graph的结点是用于计算梯度的函数,这些函数结点保存在对应Tensor的.grad_fn中;而反向传播就利用这个graph计算梯度。
torch.nn的核心数据结构是Module,它是一个抽象概念,既可以表示神经网络中的某个层(layer),也可以表示一个包含很多层的神经网络。无需纠结variable和tensor了,0.4版本已经将两个类彻底合并了。
定义自已的网络:需要继承nn.Module类,并实现forward方法。
nn中十分重要的类,包含网络各层的定义及forward方法。nn.Module实现的layer是由class Layer(nn.Module)定义的特殊类,会自动提取可学习参数nn.Parameter。
nn.Module的子类函数必须在构造函数中执行父类的构造函数: 自定义层Linear必须继承nn.Module,并且在其构造函数中需调用nn.Module的构造函数,即super(Linear, self).init() 或nn.Module.init(self),推荐使用第一种用法。
在构造函数__init__中必须自己定义可学习的参数,并封装成Parameter。
只要在nn.Module的子类中定义了forward函数,backward函数就会被自动实现(利用Autograd)。
使用时,直观上可将layer看成数学概念中的函数,调用layer(input)即可得到input对应的结果。它等价于layers.call(input),在__call__函数中,主要调用的是 layer.forward(x),另外还对钩子做了一些处理。所以在实际使用中应尽量使用layer(x)而不是使用layer.forward(x)。
Module中的可学习参数可以通过named_parameters()或者parameters()返回迭代器,前者会给每个parameter都附上名字,使其更具有辨识度。
import torch.nn as nn
import torch.nn.functional as F
class Model(nn.Module):
def __init__(self):
super(Model, self).__init__()
self.conv1 = nn.Conv2d(1, 20, 5)# submodule: Conv2d
self.conv2 = nn.Conv2d(20, 20, 5)
def forward(self, x):
x = F.relu(self.conv1(x))
return F.relu(self.conv2(x))
Modules也可以包含其它Modules,允许使用树结构嵌入他们。你可以将子模块赋值给模型属性。通过上面方式赋值的submodule会被注册。当调用 .cuda() 的时候,submodule的参数也会转换为cuda Tensor。
将所有的模型参数(parameters)和buffers赋值GPU
定义了每次执行的 计算步骤。 在所有的子类中都需要重写这个函数。
将module设置为 training mode。仅仅当模型中有Dropout和BatchNorm是才会有影响。
将module中的所有模型参数的梯度设置为0.
将state_dict中的parameters和buffers复制到此module和它的后代中。state_dict中的key必须和 model.state_dict()返回的key一致。 NOTE:用来加载模型参数。
对输入数据做线性变换:y=Ax+b
定义一个linear层,对输入数据做线性变换. (N, in_features) => (N, out_features)
parameters (Iterable[Variable]) – 一个基于变量的迭代器,会进行归一化(原文:an iterable of Variables that will have gradients normalized)
max_norm (float or int) – 梯度的最大范数(原文:max norm of the gradients)
norm_type(float or int) – 规定范数的类型,默认为L2(原文:type of the used p-norm. Can be'inf'for infinity norm)
梯度裁剪:解决梯度消失/爆炸(就是偏导无限接近0,导致长时记忆无法更新):
optimizer = optimizer()
PyTorch的optimizer默认情况会自动对梯度进行accumulate[4],所以对下一次iteration(一个新的batch),需要对optimizer进行清空操作。
https://blog.csdn.net/g11d111/article/details/83035270
https://blog.csdn.net/gdymind/article/details/82224011