pytorch学习笔记二:动态图、自动求导及逻辑回归

本文详细介绍了PyTorch中的动态图机制、自动求导原理,并通过实例展示了逻辑回归的实现。动态图允许在运行时构建计算图,便于调试和调整。自动求导通过torch.autograd.backward()实现梯度计算,同时讨论了梯度清零、高阶求导以及在非标量子计算中的应用。最后,文章探讨了逻辑回归模型及其sigmoid激活函数的应用。
摘要由CSDN通过智能技术生成

一、计算图

计算图是描述运算的有向无环图,有两个主要的元素:节点(Node)和边(Edge),节点表示数据,如向量,矩阵,张量。边表示运算,如加减乘除等。
用计算图表示: y = ( x + w ) ∗ ( w + 1 ) y = \left ( x+w \right ) \ast \left ( w+1 \right ) y=(x+w)(w+1) ,如下所示:
在这里插入图片描述
从上面可以看出y = a × b,而a = w + x, b = w + 1,只要给出x和w的值,即可根据计算图得出y的值。

计算图与梯度求导
求y对w的导数,根据求导规则,如下:
在这里插入图片描述
体现到计算图中,就是根节点 y 到叶子节点 w 有两条路径 y -> a -> w和y ->b -> w。根节点依次对每条路径的叶子节点求导,一直到叶子节点w,最后把每条路径的导数相加即可。
在这里插入图片描述

x = torch.tensor([2.], requires_grad=True)
w = torch.tensor([1.], requires_grad=True)

# y = (x + w) * (w + 1)
a = torch.add(w, x)
b = torch.add(w, 1)
y = torch.mul(a, b)

#y求导
y.backward()
#w的梯度就是y对w的求导
print(w.grad)

###result
tensor([5.])

在tensor中包含一个is_leaf(叶子节点)属性,叶子节点就是用户创建的节点,在上面的例子中,x 和 w 是叶子节点,其他所有节点都依赖于叶子节点。叶子节点的概念主要是为了节省内存,在计算图中的一轮反向传播结束之后,非叶子节点的梯度是会被释放的。

#查看是否是叶子节点
print(w.is_leaf, x.is_leaf, a.is_leaf, b.is_leaf)

###result
True True False False
#查看梯度
print(w.grad, x.grad, a.grad, b.grad, y.grad)

输出结果:
在这里插入图片描述
只有叶子节点的梯度保留了下来,而非叶子的梯度为空,如果在反向传播之后仍需要保留非叶子节点的梯度,可以对节点使用retain_grad()方法。
grad_fn:记录创建该张量时所用的方法(函数),记录这个方法主要是用于【梯度的求导】
在这里插入图片描述

二、动态图机制

pytroch采用的是动态图机制,而tensorflow采用的是静态图机制

静态图是先搭建,后运算
动态图是运算和搭建同时进行,也就是可以先计算前面节点的值,再根据这些值搭建后面的计算图。优点是灵活,易调节,易调试。
在这里插入图片描述

三、自动求导机制

pytorch的自动求导机制是torch.autograd.backward()方法,功能是自动求取梯度

torch.autograd.backward(
    tensors: Union[torch.Tensor, Sequence[torch.Tensor]],
    grad_tensors: Union[torch.Tensor, Sequence[torch.Tensor], NoneType] = None,
    retain_graph: Union[bool, NoneType] = None,
    create_graph: bool = False,
    grad_variables: Union[torch.Tensor, Sequence[torch.Tensor], NoneType] = None,
    inputs: Union[torch.Tensor, Sequence[torch.Tensor], NoneType] = None,
) -> None

● tensor:表示用于求导的张量,如loss,
● grad_tensor: 设置梯度权重,在计算矩阵的梯度时会用到,也是一个tensor,shape和前面的tensor保持一致
● retain_graph:表示保存计算图,由于pytorch采用了动态图机制,在每一次反向传播之后,计算图都会被释放掉。如果不想释放,就设置这个参数为True
● create_graph:创建导数计算图,用于高阶求导

在上面对y求导 y.backward() 处设置断点,进行debug,可以看出调用的是 torch.autograd.backward() 方法,所以 torch.autograd.backward(y)==y.backward()
在这里插入图片描述
在每一次反向传播之后,计算图会释放掉,如果想要使用计算图,可以设置参数retain_graph=True

x = torch.tensor([2.], requires_grad=True)
w = torch.tensor([1.], requires_grad=True)

# y = (x + w) * (w + 1)
a = torch.add(w, x)
b = torch.add(w, 1)
y = torch.mul(a, b)

#y求导
y.backward()
#w的梯度就是y对w的求导
# print(w.grad)

y.backward()

输出结果:
在这里插入图片描述
设置梯度权重

x = torch.tensor([2.], requires_grad=True)
w = torch.tensor([1.], requires_grad=True)

# y = (x + w) * (w + 1)
a = torch.add(w, x)
b = torch.add(w, 1)

y0 = torch.mul(a, b)
y1 = torch.add(a, b)

loss = torch.cat([y0, y1], dim=0)
grad_tensor = torch.tensor([1., 1.])

loss.backward(gradient=grad_tensor)
print(w.grad)

# result
tensor([7.])

torch.autograd.grad()这个方法的功能也是求梯度,可以实现高阶的求导。

torch.autograd.grad(
    outputs: Union[torch.Tensor, Sequence[torch.Tensor]],
    inputs: Union[torch.Tensor, Sequence[torch.Tensor]],
    grad_outputs: Union[torch.Tensor, Sequence[torch.Tensor], NoneType] = None,
    retain_graph: Union[bool, NoneType] = None,
    create_graph: bool = False,
    only_inputs: bool = True,
    allow_unused: bool = False,
) -> Tuple[torch.Tensor, ...]
  • outputs:用于求导的张量;
  • inputs: 需要梯度的张量;
  • create_graph:创建导数计算图,用于高阶求导
  • retain_graph:保存计算图
  • grad_outputs:多梯度权重

使用autograd需要注意:
● 梯度不自动清零;
● 依赖于叶子结点的结点,默认requires_grad=True;
● 叶子结点不可执行in-place;
示例如下:

x = torch.tensor([2.], requires_grad=True)
w = torch.tensor([1.], requires_grad=True)

for i in range(4):
    a = torch.add(w, x)
    b = torch.add(w, 1)
    y = torch.mul(a, b)

    y.backward()
    print(w.grad)

    # w.grad.zero_()
# 梯度不清零,运算结果
tensor([5.])
tensor([10.]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值