番外-PyTorch细节知识

一、torch.nn.Parameter

1.1 Parameter与buffer的区别

Pytorch模型中的parameter与buffer ---- https://zhuanlan.zhihu.com/p/89442276

1.2 nn.Module类中实现注册Parameter的机制

Pytorch中Module,Parameter和Buffer的区别 ---- https://www.cnblogs.com/marsggbo/p/12075244.html

二、Pytorch 中的 Tensor , Variable & Parameter

Pytorch 中的 Tensor , Variable & Parameter ---- https://www.jianshu.com/p/cb739922ce88

2.1 Tensor

  • pytorch中的Tensor类似于numpy中的array,之所以“另起炉灶”,是因为tensor能够更方便地在GPU上进行运算。pytorch为tensor设计了许多方便的操作,同时tensor也可以轻松地和numpy数组进行相互转换。

1) 像使用numpy的arrray一样,使用pytorch的tensor

import torch 
# numpy array -> tensor 
pt_tensor1 = torch.Tensor(numpy_array) 
pt_tensor2 = torch.from_numpy(numpy_array) 
# tensor -> numpy_array 
my_array = pt_tensor1.numpy() # 如果是放在gpu上,要先.cpu()一下
  1. 访问Tensor的一些属性
# my_tensor是一个3x4的tensor 
# 访问维度 
my_tensor.dim()          # 2 
# 访问大小 
my_tensor.size()        # (3,4) 
my_tensor.shape 
# 访问元素个数 
my_tensor.numel() 
# 访问元素数据类型 
my_tensor.type() 
# 访问tensor内的某个元素或某些元素 
my_tensor[0, 0]         # 第0个元素,等价于my_tensor[0][0] my_tensor[1:3, 0:2]    # 第2~3行、1~2列的元素,等价于my_tensor[1:3][0:2]  

~~疑问:tensor和Variable的.data操作有何作用,和item()有何区别 # item是从0维tensor中拿出具体数值(int,float等) # .data取出的仍然是tensor
  1. 常用的tensor操作
# 用到再往这里面加   

# 矩阵乘法 
torch.matmul(x, y)

2.2 Variable

  • Variable是对Tensor的封装,操作与tensor基本一致,不同的是,每一个Variable被构建的时候,都包含三个属性:
    • Variable中所包含的tensor
    • tensor的梯度 .grad
    • 以何种方式得到这种梯度 .grad_fn
  • 之所以有Variable这个数据结构,是为了引入计算图(自动求导),方便构建神经网络。下面用例子说明:
# 1. 对标量自动求导 
from torch.autograd import Variable 
a = torch.randn(10, 5) 
b = torch.randn(10, 5) 
x = Variable(a, requires_grad=True) 
y = Variable(b, requires_grad=True) 
z = x + y z.backward() 
x.grad            # x的梯度 10x1 的全1tensor 
z.grad_fn         # <SumBackward0 object at 0x7f809e33fcf8>
# 2. 对向量、矩阵进行求导 
n = Variable(torch.zeros(1, 2), requires_grad=True) 
m = Variable(torch.FloatTensor([2, 3]), requires_grad=True) 
n[0, 0] = m[0, 0] ** 2 
n[0, 1] = m[0, 1] ** 3 
n.backward(torch.ones_like(n)) 
m.grad 
# [4., 27.]
  • 通过调用backward(),我们可以对某个Variable(譬如说y)进行一次自动求导,但如果我们再对这个Variable进行一次backward()操作,会发现程序报错。这是因为PyTorch默认做完一次自动求导后,就把计算图丢弃了。我们可以通过设置retain_graph来实现多次求导。
# 多次自动求导 
x = Variable(torch.Tensor([2]), requires_grad=True) 
y =  x * 2 + x ** 2 + 3 
y.backward() 
x.grad                           # 6 
y.backward()       
# 报错-->RuntimeError: Trying to backward through the graph a second time, but the buffers have already been freed. Specify retain_graph=True when calling backward the first time. 

z = x * 2 + x ** 2 + 3 
z.backward(retain_graph=True)         #参数设定,保留计算图 
x.grad                                   # 第一次求导的梯度 
x.grad.data.zero_()      # 梯度归0,否则梯度会叠加(求和) 
z.backward()                    # 第二次求导 
x.grad                                   # 第二次求导的梯度 
# 注意retain_graph参数的效用只有一次,也就是说在这块代码里,我如果想对z进行第三次求导,同样会报错,因为第二次求导的时候没有声明retain_graph=True

2.3 Parameter

  • 我们知道网络中存在很多参数,这些参数需要在网络训练的过程中实时更新(一个batch更新一次),完成“学习”的过程,譬如最直观的梯度下降法更新参数w
w.data = w.data - lr * w.grad.data  # lr 是学习率
  • 那么这里就遇到一个很直观的问题:麻烦啊
    • 网络中若是有100个参数,都要手写更新代码吗?1000个呢?10000个呢…
    • Variable默认是不需要求梯度的,那我还需要手动设置参数 requires_grad=True咯
    • Variable因为要多次反向传播,那么在backward的时候还要手动注明参数w.backward(retain_graph=True)
    • Pytorch主要通过引入nn.Parameter类型的变量和optimizer机制来解决了这个问题。
    • Parameter是Variable的子类,本质上和后者一样,只不过parameter默认是求梯度的,同时一个网络net中的parameter变量是可以通过 net.parameters() 来很方便地访问到的,只需将网络中所有需要训练更新的参数定义为Parameter类型,再佐以optimizer,就能够完成所有参数的更新了,具体如下:
class Net(Module):         
    def __init__(self, a, b, ...):
        super(net, self).__init__()
        self...   #  parameters
        self...    # layers
    def forward(self):
        x = ...                 
        x = ...    # 数据流                 
        return x 
net = Net(a, b, ...) 
net.train() 
... 
optimizer = torch.optim.SGD(net.parameters(), lr=1e-1) 
# 然后在每一个batch中,调用optimizer.step()即可完成参数更新了(loss.backward()之后)

三、pytorch的常用函数总结

https://dreamhomes.top/posts/201906081516/ ---- PyTorch 常用函数解析

3.1 .data 与 .detach

PyTorch0.4中,.data 仍保留,但建议使用 .detach(), 区别在于 .data 返回和 x 的相同数据 tensor, 但不会加入到x的计算历史里,且require s_grad = False, 这样有些时候是不安全的, 因为 x.data 不能被 autograd 追踪求微分 。 .detach() 返回相同数据的 tensor ,且 requires_grad=False ,但能通过 in-place 操作报告给 autograd 在进行反向传播的时候.

3.2 .scatter 与 ._scatter

https://www.cnblogs.com/dogecheng/p/11938009.html ---- PyTorch笔记之 scatter() 函数

3.3 .new()

https://blog.csdn.net/u014386899/article/details/108420955 ---- pytorch 中Tensor.new()的使用

创建一个新的Tensor,该Tensortypedevice都和原有Tensor一致,且无内容

3.4 .cpu().numpy()

  • 可以将gpu上的数据转换至cpu,并取其numpy类型的数据进行下一步使用

四、在pytorch中使用tensorboard

  • step1: pip install tensorboard 下载 tensorboard
  • step2 使用 from torch.utils.tensorboard import SummaryWriter 导入 SummaryWriter
  • step3:
# 1. 创建写入数据的对象
# log_dir 决定生成的文件存放的位置
tb_writer = SummaryWriter(log_dir='./runs')

# 2. 绘制模型图
# model:模型对象
# input_to_model:制造一个可以传入model的tensor
tb_writer.add_graph(model, input_to_model)

# 3. 保存数据
# tag: 数据名称
# scalar_value: 数据的值
# global_step: 当前的阶段数
tb_writer.add_scalar(tag, scalar_value, global_step)             

# main_tag: 一级数据名称
# tag_scalar_dict: 传入一个dict对象,key是二级数据名称,value是对应的值(**将绘制在一个图中**)
# global_step: 当前的阶段数
tb_writer.add_scalars(main_tag, tag_scalar_dict, global_step)

# 将数据写入到文件中
tb_writer.flush()

# 关闭tensorboard对象
tb_writer.close()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ModelBulider

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值