Pytorch学习-01
本次主要学习了三部分
- nn.Module部分,通过看知乎上一个源码分析博客习得
- pytorch梯度机制,这个主要是看一些博客然后进行总结的
- Visdom,Facebook的配合pytorch的可视化工具
nn.Module
方法
自定义时需要实现的方法
__init__
forward
:前向传播计算,返回类型无限制
转换相关
to()
:in-place改Module类型(device、dtype、non_blocking)non_blocking
:device
dtype
device转换相关
cuda(device=None)
:Moves all model parameters and buffers to the GPUcpu()
:Moves all model parameters and buffers to the CPU
类型转换相关:都是进行类型转换的函数
- type:指定类型转换
- float
- double
- half
apply与_apply
_apply
函数调用children()方法循环遍历一遍全部的子模型,都执行一次传入的函数;然后遍历一遍_parameters字典,也都执行一次传入的函数操作(会自行判断是否需要in-place);对parameters.grad和buffer也执行同样的操作;这个函数一般是用来内部调用的,外部使用apply- apply:递归执行传入的函数,常用来进行初始化
share_memory:将Module中的Tensor放到共享内存空间中(参数固定)
模型的保存与加载
state_dict()
:拿到parameter和buffer组成的字典load_state_dict()
_save_to_state_dict()
_load_from_state_dict()
获取内部属性相关方法
parameters
&named_parameters
buffer
&named_buffer
children
&named_children
modules
&named_modules
训练相关:分别设置为训练模式和评估模式,只对特定的Module有影响:dropout、batchnorm
train()
eval()
梯度相关
requires_grad_()
:用于设置self.parameters()
是否需要record
梯度,默认情况下是True
requires_grad
:是Tensor一个属性,用于说明当前量是否需要在计算中保留对应的梯度信息,若置为False则无法进行反向传播,常用来冻结部分参数class RESNET_MF(nn.Module): def __init__(self, model, pretrained): super(RESNET_MF, self).__init__() self.resnet = model(pretrained) for p in self.parameters(): p.requires_grad = False #预训练模型加载进来后全部设置为不更新参数,然后再后面加层 self.f = SpectralNorm(nn.Conv2d(2048, 512, 1)) self.g = SpectralNorm(nn.Conv2d(2048, 512, 1)) self.h = SpectralNorm(nn.Conv2d(2048, 2048, 1))
zero_grad()
:用于设置self.parameters()
的gradients
为零
class属性相关
常见的属性有
_parameters
、_modules
、_buffers
还有若干hooks_get_name
:返回类名extra_repr
:输出模块信息、需要自己实现__repr__
:输出子模块的信息__dir__
:输出属性的信息或者keys
运算调用细节相关
_slow_forward
封装forward方法
__call__
调用
_slow_forward
,另外还执行了hook的运算def __call__(self, *input, **kwargs): for hook in self._forward_pre_hooks.values(): # _forward_pre_hooks result = hook(self, input) if result is not None: if not isinstance(result, tuple): result = (result,) input = result if torch._C._get_tracing_state(): # _slow_forward -> forward result = self._slow_forward(*input, **kwargs) else: result = self.forward(*input, **kwargs) for hook in self._forward_hooks.values(): # _forward_hooks hook_result = hook(self, input, result) if hook_result is not None: result = hook_result if len(self._backward_hooks) > 0: # _backward_hooks var = result while not isinstance(var, torch.Tensor): if isinstance(var, dict): var = next((v for v in var.values() if isinstance(v, torch.Tensor))) else: var = var[0] grad_fn = var.grad_fn if grad_fn is not None: for hook in self._backward_hooks.values(): wrapper = functools.partial(hook, self) functools.update_wrapper(wrapper, hook) grad_fn.register_hook(wrapper) # variable hook return result
注册相关
register_parameter
:加入一个新参数到module中register_buffer
:有些非网络的参数如batchnorm的mean和varadd_module
钩子函数相关
通常配合
isinstance(module, nn.ReLU)
和model.named_children()
在特定位置加入hookregister_backward_hook
register_forward_pre_hook
register_forward_hook
_register_state_dict_hook
_register_load_state_dict_pre_hook
Pytorch梯度记录机制
torch.Tensor
中有一个requires_grad
属性,默认为False,决定是否反向传播计算梯度(1.若置为False其之前的都无法计算梯度;2.置为True的之后的中间变量默认都是True)
在nn.Module
中的参数默认是自动计算梯度的,Module中用requires_grad_
方法递归改Tensor的requires_grad
属性
一个例子是冻结预训练模型参数
class RESNET_MF(nn.Module):
def __init__(self, model, pretrained):
super(RESNET_MF, self).__init__()
self.resnet = model(pretrained)
for p in self.parameters():
p.requires_grad = False #预训练模型加载进来后全部设置为不更新参数,然后再后面加层
self.f = SpectralNorm(nn.Conv2d(2048, 512, 1))
self.g = SpectralNorm(nn.Conv2d(2048, 512, 1))
self.h = SpectralNorm(nn.Conv2d(2048, 2048, 1))
torch.no_grad()
: 将下文Tensor、Module的requires_grad都置为空,常用于冻结权值、evalwith torch.no_grad(): ...
optimizer.zero_grad()
&model.zero_grad()
将
self.parameters()
的gradients
置零,因为在计算图反向传播过程中必须用+=而不是赋值来算梯度torch.Tensor.backward()
:tensor执行反向传播retain_graph参数
If False, the graph used to compute the grad will be freed. Note that in nearly all cases setting this option to True is not needed and often can be worked around in a much more efficient way. Defaults to the value of create_graph.
optimizer.step()
: 参数更新optimizer.zero_grad() loss.backward() optimizer.step()
Performs a single optimization step (parameter update).
torch.detach()
返回一个新的
Variable
,从当前计算图中分离下来的,但是仍指向原变量的存放位置,不同之处只是requires_grad为false,得到的这个Variable
永远不需要计算其梯度,不具有grad。
Visdom
visdom是FB的,所以对pytorch会更友好一些;并且可以通过visdom显示matplotlib的图片
启动
python3 -m visdom.server
文字
vis.text('Hello World', win='text1', append=True)
绘制单条折线图
win:某个窗格id
env:某个大标签栏id 默认为main
vis.line(y, x, win, env, opts={title:"title_name"})
绘制多条折线图
绘制图片
好处是不用转化成numpy数据就可以传到visdom里面