一些用到的Pytorch知识点的总结

这几天写模型遇到的一点知识点的总结

文章目录

  • 加载网络模型
    • load_state_dict与torch.load
  • 查看网络参数
    • model.paramenters() 和model.state_dict()
  • 自适应优化算法
  • 梯度裁剪
    • 长期依赖的问题----梯度消失与梯度爆炸
    • 优化长期依赖---梯度截断(gradient clipping)
    • torch.nn.utils.clip_grad_norm
  • 总结


加载网络模型

load_state_dict与torch.load

文档地址:load_state_dict(state_dict, strict=True)

para_in_last_net = torch.load('./resnet_ckp.txt')     # 把之前网络的参数下载到para_in_last_net中

model.load_state_dict(para_in_last_net)    # 把para_in_last_net加载到model中

model = myNet(opts)
model.load_state_dict(torch.load('./resnet_ckp.txt''))
# 这两步可以合并写 

查看网络参数

model.paramenters() 和model.state_dict()

model.named_parameters()、model.paramenters() 和model.state_dict() 这三个是Pytorch用于查看网络参数的方法。

model.named_parameters() : 返回模块参数上的迭代器,同时产生参数名称和参数本身
model.paramenters(): 返回模块参数上的迭代器,常传递给优化器 tensor格式
相当于少返回了named

>>> for param in model.parameters():
>>>     print(type(param), param.size())
<class 'torch.Tensor'> (20L,)
<class 'torch.Tensor'> (20L, 1L, 5L, 5L)

state_dict(destination=None, prefix=’’, keep_vars=False)
返回包含module所有状态的字典。包括参数和持久缓冲区(例如运行平均值)。 键是相应的参数和缓冲区名称。
示例:

>>> module.state_dict().keys()
['bias', 'weight']

自适应优化算法

自己能力不够写不出来,这里有两个很好的学习材料
花书讲解参考,有关于AdaGrad, RMSProp和Adam。但是书上的东西笔记难理解
这个B站的视频讲的很清楚关于各种优化算法的讲解
b站视频深度学习优化

梯度裁剪

长期依赖的问题----梯度消失与梯度爆炸

这一部分参考花书,我摘抄下来:
当计算图变的很深时,神经网络优化算法会面临长期依赖问题----------由于变深的结构使模型丧失了学习到向前信息的能力,让优化变得极其困难.

例如,假设某个计算图中包含一条反复与矩阵 W W W相乘的路径。那么 t t t步后,相当于乘以 W t W^t Wt。假设 W W W有特征分解
W = V d i a g ( λ ) V − 1 W=Vdiag(λ)V^{-1} W=Vdiag(λ)V1在这种情况下
W t = ( V d i a g ( λ ) V − 1 ) t = V d i a g ( λ ) t V − 1 W^t= (V diag(λ) V^{-1})^t = V diag(λ)^t V^{-1} Wt=(Vdiag(λ)V1)t=Vdiag(λ)tV1

当特征值 λ i λ_i λi不在1附近时:若量级大于1则会爆炸, 若梯度小于1则会消失。
梯度爆炸使得学习不稳定。(很少,但是对优化过程影响很大)
梯度消失使得我们难以知道参数朝那个方向移动能够改进代价函数。(大部分情况)
关于梯度消失和梯度爆炸的细节可以进一步看花书8.2.5节和10.7节

优化长期依赖—梯度截断(gradient clipping)

这个不是很理解,是在花书的后面两节,这里有一个优化算法的博客写的很好
优化算法——截断梯度法(TG)

torch.nn.utils.clip_grad_norm

这里贴一个torch.nn.utils.clip_grad_norm的源码解析,因为我也不熟悉,所有这个仅供参考。

def clip_grad_norm_(parameters: _tensor_or_tensors, max_norm: float, norm_type: float = 2.0) -> torch.Tensor:
    """Clips gradient norm of an iterable of parameters. 截断梯度范数的一个迭代参数

    The norm is computed over all gradients together, as if they were
    concatenated into a single vector. Gradients are modified in-place.
    这个范数是对所有的梯度值一起计算,它们连接成一个向量,梯度是就地修改

    Args:
        parameters (Iterable[Tensor] or Tensor): an iterable of Tensors or a
            single Tensor that will have gradients normalized
        一个可迭代的Tensors或者单个Tensor,它将会归一化梯度
        max_norm (float or int): max norm of the gradients    梯度的最大范数
        norm_type (float or int): type of the used p-norm. Can be ``'inf'`` for
            infinity norm. 规定范数的类型,默认L2

    Returns:
        Total norm of the parameters (viewed as a single vector).   
        参数的总体范数(作为单个向量来看)
    """
    if isinstance(parameters, torch.Tensor):
        parameters = [parameters]    # 要求Tensor
    parameters = [p for p in parameters if p.grad is not None]    # 传入和求梯度的参数
    max_norm = float(max_norm)
    norm_type = float(norm_type)
    if len(parameters) == 0:
        return torch.tensor(0.)
    device = parameters[0].grad.device    # GPU或CPU运算
    if norm_type == inf:
        total_norm = max(p.grad.detach().abs().max().to(device) for p in parameters)
        # 当梯度的最大范数是无穷大,参数中的p先取梯度(tensor),从计算图中脱离,按位求绝对值,取最大的
    else:
        total_norm = torch.norm(torch.stack([torch.norm(p.grad.detach(), norm_type).to(device) for p in parameters]), norm_type)
        #  先对p求2范数,将所有结果放到一个列表,用torch.stack 拼接,再求2范数。返回所给tensor的矩阵范数或向量范数
    clip_coef = max_norm / (total_norm + 1e-6)    # 裁剪系数,我设置max_norm为10, 也就是说total_norm>10时, clip_coef < 1
    if clip_coef < 1:
        for p in parameters:
            p.grad.detach().mul_(clip_coef.to(p.grad.device))    # p*clip_coef,对p进行剪裁
    return total_norm

这里的torch.norm,只举一个例子, 详解可以看文档

c = torch.tensor([[ 1, 2, 3],[-1, 1, 4]] , dtype= torch.float)
>>> torch.norm(c, dim=0)
---
tensor([1.4142, 2.2361, 5.0000])

总结

未完待续

你可能感兴趣的:(pytorch,深度学习基础,深度学习,pytorch)