李沐深度学习-02-线性代数实现与矩阵运算

本文介绍了如何使用PyTorch库进行基本的线性代数操作,如标量和向量处理,矩阵创建、转置、对称性检查,以及多维张量的处理。此外,文章还涉及矩阵求导理论及其在自动微分中的应用,展示了如何通过PyTorch实现梯度计算和自动求导功能。
摘要由CSDN通过智能技术生成
import torch

线性代数实现

#标量
a=torch.tensor([3.0])
a
tensor([3.])
#向量
x=torch.arange(4)
#按下标访问
x[3]
tensor(3)
#长度
len(x)
4
#形状
x.shape
torch.Size([4])
#矩阵
A=torch.arange(20).reshape(5,4)
A
tensor([[ 0,  1,  2,  3],
        [ 4,  5,  6,  7],
        [ 8,  9, 10, 11],
        [12, 13, 14, 15],
        [16, 17, 18, 19]])
#矩阵转置
A.T
tensor([[ 0,  4,  8, 12, 16],
        [ 1,  5,  9, 13, 17],
        [ 2,  6, 10, 14, 18],
        [ 3,  7, 11, 15, 19]])
#对称矩阵
B = torch.tensor([[1, 2, 3], [2, 0, 4], [3, 4, 5]])
B
tensor([[1, 2, 3],
        [2, 0, 4],
        [3, 4, 5]])
#判断是否为对称矩阵
B==B.T
tensor([[True, True, True],
        [True, True, True],
        [True, True, True]])
#多维....注意建立直觉
X=torch.arange(24).reshape(2,3,4)
X
tensor([[[ 0,  1,  2,  3],
         [ 4,  5,  6,  7],
         [ 8,  9, 10, 11]],

        [[12, 13, 14, 15],
         [16, 17, 18, 19],
         [20, 21, 22, 23]]])
#通过分配新内存,将A的一个副本分配给B....A.clone(),否则是给索引,并非分配内存
A=torch.arange(20).reshape(5,4)
B=A.clone()
#判断
id(A)==id(B)
False
#矩阵乘法
A*B
tensor([[  0,   1,   4,   9],
        [ 16,  25,  36,  49],
        [ 64,  81, 100, 121],
        [144, 169, 196, 225],
        [256, 289, 324, 361]])
#若是张量和一个标量进行运算,意味着对张量的所有元素都与该标量进行运算
a=2
X=torch.arange(20).reshape(4,5)
a*X
tensor([[ 0,  2,  4,  6,  8],
        [10, 12, 14, 16, 18],
        [20, 22, 24, 26, 28],
        [30, 32, 34, 36, 38]])
#计算各元素的和
x=torch.arange(4).reshape(2,2)
x.sum()
tensor(6)
#我们还可以指定张量沿哪一个轴来通过求和
#axis=0表示按列求和 axis=1表示按行求和
#即为0则消去第一个维度,1则消第二个维度,以此类推(例如shape(2,5)则消去2)(可以拓展到多维)
#{0,1
#2,3}
x.sum(axis=0)
tensor([2, 4])
#(2,5,4)->(2,4)
a=torch.ones((2,5,4))
a.sum(axis=1).shape
torch.Size([2, 4])
#keepdims=True保持该维度为1并非直接去掉(2,2)->(1,2)
x.sum(axis=0,keepdims=True).shape
torch.Size([1, 2])

矩阵计算

求导理论 (不太懂)

向量和标量混合求导,求出来依然是向量,向量关于向量求导较为复杂,求取出来为一个矩阵

矩阵求导公式的数学推导(矩阵求导——基础篇):https://zhuanlan.zhihu.com/p/273729929

矩阵求导公式的数学推导(矩阵求导——进阶篇):https://zhuanlan.zhihu.com/p/288541909

#自动求导分为两种一是正向积累,即先求链式求导后面的,二是反向积累,即先求链式前面的

自动求导实现

#计算y=2x(T)x求导
x=torch.arange(4.0)
#计算y关于x的梯度之前需要一个地方来存储梯度
x.requires_grad_(True)#等价于x=torch.arange(4.0,requires_grad=True)
#用于访问梯度
x.grad #默认None
#计算y
y= 2*torch.dot(x,x)
y
tensor(28., grad_fn=<MulBackward0>)
#通过调用反向传播函数来自动计算y关于x每个分量的梯度
y.backward()
x.grad
tensor([ 0.,  4.,  8., 12.])
#验证
x.grad==4*x
tensor([True, True, True, True])
#计算x的另外一个函数
#默认情况下,Pytorch会累积梯度,我们需要清空之前的值
#清0
x.grad.zero_()
#另外一个函数
y=x.sum()
y.backward()
x.grad
tensor([1., 1., 1., 1.])
#将某些计算移动到记录的计算图之外
x.grad.zero_()
y=x*x
#把y当作常量,若无detach则求导得出不一致
u=y.detach()
z=u*x
z.sum().backward()
#等于u
x.grad==u
tensor([True, True, True, True])
x.grad.zero_()
y.sum().backward()
x.grad==2*x
tensor([True, True, True, True])
#使用自动微分的一个好处是: 即使构建函数的计算图需要通过Python控制流(例如,条件、循环或任意函数调用),
#我们仍然可以计算得到的变量的梯度。 在下面的代码中,while循环的迭代次数和if语句的结果都取决于输入a的值。
def f(a):
    b = a * 2
    while b.norm() < 1000:
        b = b * 2
    if b.sum() > 0:
        c = b
    else:
        c = 100 * b
    return c
a = torch.randn(size=(), requires_grad=True)
d = f(a)
d.backward()
#验证
#相当于d=n*a,求导去除了a
a.grad==d/a
tensor(True)

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值