深度学习 矩阵计算

1. 标量导数

2. 亚导数

3. 求导

3.1 梯度

 y是向量,x是标量的话,求导为向量。

 y是向量,x是向量的话,求导为矩阵。

3.2 标量对向量求导

3.3 向量对标量求导

3.4 向量对向量求导

3.5 扩展矩阵对矩阵求导

4. 向量链式法则

例子1是一个线性回归的例子,如下图所示。

5. 自动求导-理论

6. 计算图

7. 两种模型

b是之前计算的结果,是一个已知的值。

8. 复杂度

9. 自动求导-编程

假设想对函数y=2x⊤x关于列向量x求导

import torch
x = torch.arange(4.0) #tensor([0., 1., 2., 3.])
x.requires_grad_(True) # 等价于 x = torch.arange(4.0,requires_grad=True)
print(x.grad) # 默认为None
y = 2 * torch.dot(x,x) #tensor(28., grad_fn=<MulBackward0>)
y.backward() # 反向传播后会有梯度计算出来
print(x.grad) # 访问导数,即访问梯度
print(x.grad == 4 * x) # 4 * x 是 2 * x * x 的导数
"""
tensor([ 0.,  4.,  8., 12.])
tensor([True, True, True, True])
"""

计算x的另一个函数 

import torch
x = torch.arange(4.0,requires_grad=True)
y = 2 * torch.dot(x,x)
y.backward()
# 默认情况下,PyTorch会累积梯度,需要清除之前的值
x.grad.zero_() # y.backward() 后才能产生梯度,才能梯度清零,没有反向传播,无法梯度清零
y = x.sum() # 这里的y是一个标量,sum函数其实就是x_1+x_2+...x_n,求偏导自然是全1
y.backward()
print(x.grad)#tensor([1., 1., 1., 1.])

 在深度学习中,目的不是计算微分矩阵,而是批量中每个样本单独计算的偏导数之和。

import torch
x = torch.arange(4.0,requires_grad=True)
y = 2 * torch.dot(x,x)
y.backward()
# 默认情况下,PyTorch会累积梯度,需要清除之前的值
# 对非标量调用 'backward' 需要传入一个 'gradient' 参数,该参数指定微分函数
x.grad.zero_()
y = x * x  # 这里的y不是一个标量,这是一个向量
print(y)#tensor([0., 1., 4., 9.], grad_fn=<MulBackward0>)
# 等价于y.backward(torch.ones(len(x)))
y.sum().backward() # y.sum()后就讲向量转为标量了,对标量求导
print(x.grad)#tensor([0., 2., 4., 6.])

将某些计算移动到记录的计算图之外。

import torch
x = torch.arange(4.0,requires_grad=True)
y = 2 * torch.dot(x,x)
y.backward()
x.grad.zero_()
y = x * x
print(y)
u = y.detach() # y.detach把y当作一个常数,而不是关于x的一个函数
print(y.detach())
print(u)
z = u * x
z.sum().backward()
print(x.grad == u)
"""
tensor([0., 1., 4., 9.], grad_fn=<MulBackward0>)
tensor([0., 1., 4., 9.])
tensor([0., 1., 4., 9.])
tensor([True, True, True, True])
"""

即使构建函数的计算图需要通过Python控制流(例如,条件、循环或任意函数调用),仍然可以计算得到的变量的梯度。

def f(a):
    b = a * 2
    while b.norm() < 1000: # norm是L2范数
        b = b * 2
    if b.sum() > 0:
        c = b
    else:
        c = 100 * b
    return c

a = torch.randn(size=(),requires_grad=True)
print(a)
d = f(a)
d.backward()
print(a.grad)
print(d/a)
print(a.grad == d/a) # d是a的线性函数,所以导数就是斜率d/a
"""
tensor(-0.7712, requires_grad=True)
tensor(204800.)
tensor(204800., grad_fn=<DivBackward0>)
tensor(True)
"""

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值