pytorch拓展——numpy

引言

pytorch所有内置的函数都提供了自动求导功能,所以大部分的时候,我们只需要写出前向传播过程,然后调用tensor.backward()方法,就可以求出所有varible的grad。

例子一:自带函数的自动求导

# coding:utf-8
import torch
from torch.autograd import Variable

x = Variable(torch.Tensor([2.0]), requires_grad=True)

a = torch.tensor([2.0])       # 不需要梯度
a = Variable(torch.Tensor([2.0]), requires_grad=True)       # a也需要梯度

z = (x + a) ** 2 + 3

print(z)

print(u'求导之前x的梯度:', x.grad)

z.backward()

print(u'求导之后x的梯度:', x.grad)

print(a.grad)
tensor([ 19.])
求导之前x的梯度: None
求导之后x的梯度: tensor([ 8.])
tensor([ 8.])

解释:

  • 需要梯度的量必需声明为Variable,而且requires_grad属性等于True
  • 使用z.backward()的时候,z中至少有一个Variable变量,这句会求出所有需要梯度的Variable的梯度,但是整个流程用idle是没法跟踪的,在Variable._execution_engine.run_backward( tensors, grad_tensors, retain_graph, create_graph, allow_unreachable=True) # allow_unreachable flag就断了。
  • 这里的前向运算是 (x + a) ** 2 + 3,并没用torch.add, torch.pow, 我想应该是重构的结果

例子二:手动实现求导

采用numpy手动实现(x+2) ** 2 + 3 对x的求导

具体代码
# coding:utf-8
import torch
from torch.autograd import Function,Variable
import numpy as np

class BadFFTFunction(Function):

    def forward(self, input):
        numpy_input = input.detach().numpy()
        # ctx.save_for_backward(numpy_input)        # ctx.save_for_backward只能存Variable
        self.input = numpy_input
        result = np.power(np.add(numpy_input, 2), 2) + 3        # (x+2) ** 2 + 3
        return input.new(result)                    # 和input一样类型的tensor

    def backward(self, grad_output):                       # 用numpy实现手动求导
        input = self.input
        result = np.dot(np.add(input, 2), 2)
        return grad_output.new(result) * grad_output

# since this layer does not have any parameters, we can
# simply declare this as a function, rather than as an nn.Module class

def incorrect_fft(input):
    return BadFFTFunction()(input)


x = Variable(torch.Tensor([2.0]), requires_grad=True)

result = incorrect_fft(x)

result.backward(torch.ones(result.size()) * 0.01)

print(x.grad)

解释:

  1. ctx.save_for_backward只能存Variable,所以这里用self.input来存numpy
  2. 自己写的操作要继承torch.autograd.Function,然后重写forwark和backward
  3. result.backward(torch.ones(result.size()) * 0.01)反向传播的时候会将Variable的grid放缩一定的倍数
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值